/* Astraea Message -- feuille de style.
 *
 * Identite propre a cette application : un violet profond. Les autres apps
 * Astraea ont chacune la leur (Companion mandarine, Securite acier, PDF et
 * Monitor ivoire) -- on ne fait deliberement PAS une famille visuelle.
 * Pour changer la couleur de l'app, une seule ligne : --accent.
 */

:root {
  --accent:          #5b4bd6;
  --accent-sombre:   #4a3cb8;
  --accent-doux:     #ece9fc;

  --fond:            #ffffff;
  --fond-liste:      #f7f7fa;
  --fond-fil:        #f0eff5;
  --bulle-moi:       var(--accent);
  --bulle-moi-texte: #ffffff;
  --bulle-autre:     #ffffff;
  --texte:           #14141b;
  --texte-doux:      #6b6b7b;
  --trait:           #e4e4ec;
  --danger:          #c0392b;
  --etoile:          rgba(91, 75, 214, .38);
  --etoile-liste:    rgba(91, 75, 214, .16);

  --rayon:           14px;
  --largeur-liste:   340px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fond:            #15151c;
    --fond-liste:      #1b1b24;
    --fond-fil:        #101017;
    --bulle-autre:     #23232f;
    --texte:           #ececf2;
    --texte-doux:      #9a9aae;
    --trait:           #2c2c3a;
    --accent-doux:     #262046;
    --etoile:          rgba(160, 150, 255, .34);
    --etoile-liste:    rgba(160, 150, 255, .14);
  }
}
:root[data-theme="dark"] {
  --fond: #15151c; --fond-liste: #1b1b24; --fond-fil: #101017;
  --bulle-autre: #23232f; --texte: #ececf2; --texte-doux: #9a9aae;
  --trait: #2c2c3a; --accent-doux: #262046;
  --etoile: rgba(160, 150, 255, .34);
  --etoile-liste: rgba(160, 150, 255, .14);
}

* { box-sizing: border-box; }

html, body {
  height: 100%; margin: 0;
  background: var(--fond);
  color: var(--texte);
  /* « Astraea Emoji » EN TETE, et c'est voulu : la police est restreinte aux
   * plages d'emoji par unicode-range, donc elle ne touche pas au texte, mais
   * en etant premiere elle passe AVANT l'emoji du systeme. Sans ca, iOS
   * dessinerait ses emoji Apple et Android les siens -- le meme message
   * n'aurait pas le meme visage selon qui le lit. */
  font: 15px/1.45 "Astraea Emoji", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.ecran { height: 100dvh; }
[hidden] { display: none !important; }

/* ----------------------------------------------------------- CONNEXION */
/* Les DEUX ecrans d'entree partagent cette mise en page. Elle ne visait que
 * #ecran-connexion : le nouvel ecran d'accueil n'etait donc couvert par rien
 * et s'affichait colle en haut a gauche, pleine largeur (vu le 27/09). */
#ecran-connexion, #ecran-accueil {
  display: grid; place-items: center;
  padding: calc(24px + env(safe-area-inset-top)) 16px
           calc(24px + env(safe-area-inset-bottom));
  background: linear-gradient(160deg, var(--accent-doux), var(--fond) 60%);
}
.carte-connexion {
  width: 100%; max-width: 380px;
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 20px; padding: 28px 24px 24px;
  box-shadow: 0 18px 50px rgba(0,0,0,.10);
  display: flex; flex-direction: column; gap: 16px;
}
.marque { text-align: center; margin-bottom: 4px; }
.marque h1 { font-size: 21px; margin: 12px 0 2px; letter-spacing: -.2px; }
.marque-sous { margin: 0; color: var(--texte-doux); font-size: 13px; }
.marque-pastille {
  width: 56px; height: 56px; margin: 0 auto; border-radius: 18px;
  background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: 26px; font-weight: 600;
}
.champ { display: flex; flex-direction: column; gap: 6px; }
.champ span { font-size: 13px; color: var(--texte-doux); }
.champ input {
  font: inherit; color: var(--texte); background: var(--fond);
  border: 1px solid var(--trait); border-radius: 10px; padding: 11px 12px;
}
.champ input:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: transparent; }
#bouton-connexion {
  font: inherit; font-weight: 600; cursor: pointer;
  background: var(--accent); color: #fff; border: 0;
  border-radius: 10px; padding: 12px; margin-top: 4px;
}
#bouton-connexion:hover { background: var(--accent-sombre); }
#bouton-connexion:disabled { opacity: .6; cursor: progress; }
.erreur {
  margin: 0; color: var(--danger); font-size: 13px;
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border-radius: 8px; padding: 9px 11px;
}
.mention-serveur { margin: 2px 0 0; text-align: center; font-size: 11px; color: var(--texte-doux); }

/* --------------------------------------------------------- CHARGEMENT */
.chargement { display: grid; place-items: center; height: 100%; gap: 18px; }
.rond {
  width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid var(--accent-doux); border-top-color: var(--accent);
  animation: tourne .8s linear infinite;
}
@keyframes tourne { to { transform: rotate(360deg); } }
#texte-chargement { color: var(--texte-doux); margin: 0; }

/* ------------------------------------------------------------- APP */
.ecran-app { display: grid; grid-template-columns: var(--largeur-liste) 1fr; }

#panneau-liste {
  display: flex; flex-direction: column; min-width: 0;
  background-color: var(--fond-liste);
  /* Le meme semis que dans les conversations, mais DEUX FOIS plus rare et
   * plus pale : une liste doit rester lisible quand elle portera dix
   * conversations, alors qu'un fil a toujours des bulles par-dessus. */
  background-image:
    radial-gradient(circle at 25% 57%, var(--etoile-liste) 1.5px, transparent 2.1px),
    radial-gradient(circle at 92% 57%, var(--etoile-liste) 1.5px, transparent 2.1px),
    radial-gradient(circle at 85% 40%, var(--etoile-liste) 1.5px, transparent 2.1px),
    radial-gradient(circle at 65% 31%, var(--etoile-liste) 1.5px, transparent 2.1px),
    radial-gradient(circle at 64% 69%, var(--etoile-liste) 1.5px, transparent 2.1px),
    radial-gradient(circle at 27% 68%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 71% 34%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 4% 5%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 51% 78%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 58% 12%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 22% 33%, var(--etoile-liste) 1.0px, transparent 1.6px),
    radial-gradient(circle at 33% 92%, var(--etoile-liste) 1.0px, transparent 1.6px);
  background-size: 420px 420px, 420px 420px, 420px 420px, 420px 420px, 420px 420px, 300px 300px, 300px 300px, 300px 300px, 300px 300px, 300px 300px, 300px 300px, 300px 300px;
  border-right: 1px solid var(--trait);
}
.entete-liste, .entete-fil {
  display: flex; align-items: center; gap: 11px;
  /* La marge du haut s'ajoute a l'espace pris par la barre d'etat du
   * telephone (horloge, batterie). Sans elle, l'en-tete passe DESSOUS et le
   * nom se superpose a l'heure -- vu sur le Pixel le 26/09. Vaut 0 partout
   * ailleurs, donc rien a conditionner. */
  padding: calc(11px + env(safe-area-inset-top)) 14px 11px;
  border-bottom: 1px solid var(--trait);
  background: var(--fond-liste);
  min-height: calc(62px + env(safe-area-inset-top));
}
.entete-fil { background: var(--fond); }
.entete-titre { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.entete-titre strong { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.etat { font-size: 12px; color: var(--texte-doux); }

.pastille {
  width: 42px; height: 42px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center;
  font-weight: 600; font-size: 16px; color: #fff;
  background: var(--accent); user-select: none;
}
.icone {
  font: inherit; font-size: 20px; line-height: 1; cursor: pointer;
  background: transparent; border: 0; color: var(--texte-doux);
  width: 36px; height: 36px; border-radius: 50%;
}
.icone:hover { background: var(--trait); color: var(--texte); }
.retour { display: none; font-size: 28px; }

.barre-recherche { padding: 9px 12px; }
.barre-recherche input {
  width: 100%; font: inherit; color: var(--texte);
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 20px; padding: 8px 14px;
}
.barre-recherche input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.liste { flex: 1; overflow-y: auto; }
.conversation {
  display: flex; gap: 11px; align-items: center;
  padding: 10px 14px; cursor: pointer; border: 0; width: 100%;
  background: transparent; text-align: left; font: inherit; color: var(--texte);
}
.conversation:hover { background: var(--trait); }
.conversation[aria-current="true"] { background: var(--accent-doux); }
.conversation .corps { flex: 1; min-width: 0; }
.conversation .ligne1 { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.conversation .nom { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conversation .heure { font-size: 11px; color: var(--texte-doux); flex: 0 0 auto; }
.conversation .apercu {
  font-size: 13px; color: var(--texte-doux);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pastille-nonlus {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  background: var(--accent); color: #fff;
  font-size: 12px; font-weight: 600; display: grid; place-items: center;
}

/* ------------------------------------------------------------- FIL */
#panneau-fil {
  display: flex; flex-direction: column; min-width: 0;
  background-color: var(--fond-fil);
  /* LE FOND DE CONVERSATION. Un aplat uni donne l'impression d'une page qui
   * n'a pas fini de charger ; toutes les messageries mettent quelque chose
   * ici. Chez nous ce sont des etoiles -- Astraea est la deesse des etoiles.
   * Trois tailles et des positions irregulieres, sinon l'oeil repere la
   * repetition. Dessine en CSS : rien a telecharger, et le theme sombre est
   * gere par la seule variable --etoile.
   * ⚠️ Premiere version invisible a l'ecran : opacite trop faible, motif trop
   * espace. Il ne remplissait donc rien du tout (vu le 26/09). */
  background-image:
    radial-gradient(circle at 44% 22%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 53% 86%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 9% 12%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 71% 15%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 49% 77%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 10% 67%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 30% 7%, var(--etoile) 1.9px, transparent 2.5px),
    radial-gradient(circle at 14% 58%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 56% 11%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 33% 14%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 73% 57%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 10% 75%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 18% 31%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 83% 83%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 77% 10%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 76% 77%, var(--etoile) 1.3px, transparent 1.9px),
    radial-gradient(circle at 53% 9%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 31% 8%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 74% 20%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 40% 56%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 21% 72%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 18% 76%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 42% 74%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 90% 26%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 16% 77%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 76% 84%, var(--etoile) 0.9px, transparent 1.5px),
    radial-gradient(circle at 27% 50%, var(--etoile) 0.9px, transparent 1.5px);
  background-size: 340px 340px, 340px 340px, 340px 340px, 340px 340px, 340px 340px, 340px 340px, 340px 340px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 250px 250px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px, 190px 190px;
}

#panneau-fil.vide .entete-fil,
#panneau-fil.vide #fil-messages,
#panneau-fil.vide .barre-saisie { display: none; }
#panneau-fil:not(.vide) .accueil-vide { display: none; }

.accueil-vide { flex: 1; display: grid; place-content: center; text-align: center; gap: 6px; padding: 24px; }
.accueil-pastille {
  width: 72px; height: 72px; margin: 0 auto 10px; border-radius: 24px;
  background: var(--accent); color: #fff; display: grid; place-items: center;
  font-size: 34px; font-weight: 600;
}
.accueil-vide h2 { margin: 0; font-size: 20px; }
.accueil-vide p { margin: 0; color: var(--texte-doux); max-width: 34ch; }
.accueil-note { font-size: 12px; margin-top: 10px !important; }

.messages {
  flex: 1; overflow-y: auto; padding: 16px 16px 8px;
  display: flex; flex-direction: column; gap: 2px;
}
/* Une conversation courte se pose EN BAS, contre la barre de saisie, comme
 * dans toutes les messageries. On ne met pas justify-content: flex-end, qui
 * rend le haut du fil inatteignable des que ca deborde : une cale a marge
 * automatique fait la meme chose sans casser le defilement. */
.messages::before { content: ""; margin-top: auto; }

.jour {
  align-self: center; margin: 14px 0 8px;
  font-size: 11px; color: var(--texte-doux);
  background: var(--fond); border: 1px solid var(--trait);
  padding: 3px 11px; border-radius: 12px;
}

.msg { max-width: min(74%, 620px); display: flex; flex-direction: column; }
.msg.moi { align-self: flex-end; align-items: flex-end; }
.msg.autre { align-self: flex-start; }
.msg + .msg.suite { margin-top: 0; }
.msg:not(.suite) { margin-top: 10px; }

.bulle {
  padding: 7px 11px 6px; border-radius: var(--rayon);
  background: var(--bulle-autre); color: var(--texte);
  box-shadow: 0 1px 1px rgba(0,0,0,.06);
  overflow-wrap: anywhere; white-space: pre-wrap;
}
.msg.moi .bulle { background: var(--bulle-moi); color: var(--bulle-moi-texte); }
.msg.autre:not(.suite) .bulle { border-top-left-radius: 4px; }
.msg.moi:not(.suite)   .bulle { border-top-right-radius: 4px; }

.auteur { font-size: 12px; font-weight: 600; color: var(--accent); margin: 0 4px 2px; }
.meta { font-size: 10.5px; color: var(--texte-doux); margin: 2px 5px 0; }
.msg.moi .meta { text-align: right; }

/* Plus specifique que « .msg.moi .bulle », sinon un message illisible qu'on a
 * soi-meme envoye garde la couleur d'un message normal : il ressemble alors a
 * un message reussi, et plus personne ne comprend pourquoi le texte est
 * bizarre. La forme doit dire tout de suite « celui-la n'a pas pu s'ouvrir ». */
.msg .bulle.illisible {
  background: transparent; border: 1px dashed var(--trait);
  color: var(--texte-doux); font-style: italic; box-shadow: none;
}
.bulle.systeme { background: transparent; box-shadow: none; color: var(--texte-doux); font-size: 12.5px; text-align: center; }
.msg.systeme { align-self: center; max-width: 90%; }

/* --------------------------------------------------------- SAISIE */
.barre-saisie {
  display: flex; align-items: flex-end; gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--fond); border-top: 1px solid var(--trait);
}
#saisie-message {
  flex: 1; font: inherit; color: var(--texte); background: var(--fond-liste);
  border: 1px solid var(--trait); border-radius: 20px;
  padding: 10px 14px; resize: none; max-height: 140px; line-height: 1.4;
}
#saisie-message:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
#bouton-envoyer {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%;
  background: var(--accent); color: #fff; border: 0; cursor: pointer;
  font-size: 17px; display: grid; place-items: center;
}
#bouton-envoyer:hover { background: var(--accent-sombre); }
#bouton-envoyer:disabled { opacity: .45; cursor: default; }

/* --------------------------------------------------------- TELEPHONE */
@media (max-width: 760px) {
  .ecran-app { grid-template-columns: 1fr; }
  #panneau-fil { display: none; }
  .ecran-app.fil-ouvert #panneau-liste { display: none; }
  .ecran-app.fil-ouvert #panneau-fil { display: flex; }
  .retour { display: grid; place-items: center; }
  .msg { max-width: 82%; }
}


/* ------------------------------------------------- CLES DE CHIFFREMENT */
.voile {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(10,10,20,.55);
  display: grid; place-items: center; padding: 18px;
  overflow-y: auto;
}
.dialogue {
  width: 100%; max-width: 440px; background: var(--fond);
  border-radius: 18px; padding: 24px;
  box-shadow: 0 24px 60px rgba(0,0,0,.35);
  display: flex; flex-direction: column; gap: 14px;
}
.dialogue h2 { margin: 0; font-size: 19px; }
.dialogue p { margin: 0; font-size: 14px; color: var(--texte-doux); line-height: 1.5; }
.dialogue p strong { color: var(--texte); }

/* La cle doit etre lisible caractere par caractere : on la recopie a la main
 * sur du papier. Chasse fixe, gros, et de l'air entre les groupes. */
.cle-affichee {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 16px; letter-spacing: .06em; line-height: 1.9;
  background: var(--accent-doux); color: var(--texte);
  border-radius: 10px; padding: 14px; text-align: center;
  overflow-wrap: anywhere; user-select: all;
}
.cles-consigne { font-size: 13px !important; }
.cles-case { display: flex; align-items: center; gap: 9px; font-size: 14px; cursor: pointer; }
.cles-case input { width: 17px; height: 17px; accent-color: var(--accent); }
.dialogue-boutons { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; }
.dialogue-boutons button {
  font: inherit; font-weight: 600; cursor: pointer;
  border: 0; border-radius: 10px; padding: 11px 18px;
  background: var(--accent); color: #fff;
}
.dialogue-boutons button:hover { background: var(--accent-sombre); }
.dialogue-boutons button:disabled { opacity: .6; cursor: progress; }
.dialogue-boutons .secondaire { background: transparent; color: var(--texte-doux); }
.dialogue-boutons .secondaire:hover { background: var(--trait); color: var(--texte); }

.bouton-copier {
  font: inherit; font-size: 13px; cursor: pointer; align-self: center;
  background: transparent; color: var(--accent); font-weight: 600;
  border: 1px solid var(--accent); border-radius: 18px; padding: 7px 16px;
}
.bouton-copier:hover { background: var(--accent-doux); }

/* ------------------------------------------- NOUVELLE CONVERSATION */
#dialogue-nouvelle input[type="search"],
#dialogue-nouvelle input[type="text"] {
  font: inherit; color: var(--texte); background: var(--fond);
  border: 1px solid var(--trait); border-radius: 10px; padding: 11px 13px;
}
#dialogue-nouvelle input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.resultats { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; }
.resultats:empty { display: none; }
.personne {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 10px; cursor: pointer;
  background: transparent; text-align: left; font: inherit; color: var(--texte);
}
.personne:hover { background: var(--trait); }
.personne.choisie { background: var(--accent-doux); }
.personne.choisie::after { content: "✓"; color: var(--accent); font-weight: 700; }
.personne .corps { flex: 1; min-width: 0; }
.personne .nom { font-weight: 600; }

.lien {
  font: inherit; font-size: 13px; background: transparent; border: 0;
  color: var(--accent); cursor: pointer; text-decoration: underline;
  padding: 4px; align-self: center;
}

/* ------------------------------------------------------- INSTALLATION */
.bandeau-installer {
  display: flex; align-items: center; gap: 10px;
  background: var(--accent-doux); border-radius: 12px;
  padding: 11px 13px; font-size: 13px; color: var(--texte);
}
.bandeau-installer button {
  font: inherit; font-weight: 600; cursor: pointer; white-space: nowrap;
  background: var(--accent); color: #fff; border: 0;
  border-radius: 8px; padding: 8px 14px; margin-left: auto;
}
.bandeau-installer button:hover { background: var(--accent-sombre); }

/* ------------------------------------------------------- PICTOGRAMMES */
/* Dessines, pas ecrits. Un pictogramme en caractere (⏻, ➤, ‹) depend de la
 * police du systeme : le ⏻ de la deconnexion s'affichait en carre barre sur
 * le Pixel, Android ne connaissant pas ce caractere. Un trace vectoriel
 * s'affiche a l'identique partout, et se met a la couleur du texte. */
.icone svg, #bouton-envoyer svg {
  width: 21px; height: 21px; display: block;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.icone { display: grid; place-items: center; }
.retour svg { width: 25px; height: 25px; }
#bouton-envoyer svg { fill: currentColor; stroke: none; margin-left: 1px; }

/* ---------------------------------------------------- TEXTE NUMERIQUE */
/* Les heures et les dates n'empruntent JAMAIS la police d'emoji. Celle-ci
 * declare les chiffres (ils servent aux emoji-touches : 1 + U+20E3 = 1️⃣) et
 * les dessine a la largeur d'un emoji, c'est-a-dire un carre. Resultat sur
 * Android : « 1 4 : 0 5 » au lieu de « 14:05 » (vu sur le Pixel le 26/09).
 * On nomme donc explicitement une pile sans emoji, plutot que de compter sur
 * l'ordre de repli. font-variant-numeric aligne en prime les chiffres entre
 * eux, pour que l'heure ne danse pas d'un message a l'autre. */
.meta, .heure, .jour, .etat {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
}

/* ----------------------------------------------- AVIS DE CHIFFREMENT */
/* En tete de chaque conversation, comme dans les messageries usuelles. Il
 * occupe le haut du fil -- donc le vide devient une information -- et il dit
 * a la famille ce qu'elle a besoin de savoir, au moment ou elle le lit. */
.avis-chiffrement {
  align-self: center; max-width: 46ch; margin: 8px 0 16px;
  text-align: center; font-size: 12.5px; line-height: 1.5;
  color: var(--texte-doux);
  background: var(--accent-doux); border-radius: 12px; padding: 10px 14px;
}
.avis-chiffrement strong { color: var(--texte); }

/* --------------------------------------------- LISTE SANS CONVERSATION */
.liste-vide {
  display: grid; place-content: center; justify-items: center;
  gap: 8px; padding: 48px 28px; text-align: center; color: var(--texte-doux);
}
.liste-vide .rond-vide {
  width: 58px; height: 58px; border-radius: 50%;
  display: grid; place-items: center; background: var(--accent-doux);
}
.liste-vide .rond-vide svg { width: 26px; height: 26px; fill: none;
  stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.liste-vide strong { color: var(--texte); font-size: 15px; }
.liste-vide p { margin: 0; font-size: 13px; max-width: 26ch; }

/* ------------------------------------------- ENTETE ET LISTE, 2e JET */
/* Inspire des messageries usuelles : un titre plutot que le nom du porteur
 * du telephone (il sait qui il est), et des lignes plus grandes -- c'est
 * l'air entre les lignes qui empeche une liste courte de paraitre vide. */
#titre-app {
  margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.3px;
}
.entete-liste .entete-titre { gap: 0; }
/* L'etat ne s'affiche QUE s'il y a quelque chose a signaler : « en ligne »
 * permanent est un voyant qu'on ne regarde plus. */
#etat-synchro[hidden] { display: none; }

#panneau-liste { position: relative; }

.conversation { padding: 12px 16px; gap: 13px; }
.conversation .pastille { width: 54px; height: 54px; font-size: 19px; }
.conversation .nom { font-size: 16px; }
.conversation .apercu { font-size: 14px; margin-top: 2px; }
.conversation .heure { font-size: 12px; }

.flottant {
  position: absolute; right: 18px;
  bottom: calc(18px + env(safe-area-inset-bottom));
  width: 58px; height: 58px; border-radius: 19px; border: 0;
  background: var(--accent); color: #fff; cursor: pointer;
  display: grid; place-items: center;
  box-shadow: 0 6px 18px rgba(0,0,0,.22);
}
.flottant:hover { background: var(--accent-sombre); }
.flottant svg {
  width: 26px; height: 26px; fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round;
}

/* L'en-tete et la barre de saisie ne retrecissent JAMAIS. Quand le clavier
 * s'ouvre, la hauteur disponible fond, et un enfant de conteneur flexible
 * accepte par defaut d'etre comprime : l'avatar se retrouvait rogne par le
 * haut. Seule la zone des messages doit ceder la place. */
.entete-liste, .entete-fil, .barre-saisie, .barre-recherche { flex: 0 0 auto; }
.messages { flex: 1 1 auto; min-height: 0; }

/* ------------------------------------------------------------ MEDIAS */
#bouton-joindre { flex: 0 0 auto; align-self: flex-end; margin-bottom: 2px; }
#bouton-joindre svg { width: 23px; height: 23px; }

/* Une photo remplit sa bulle : pas de cadre, pas de marge -- c'est l'image
 * qui est le message. Hauteur bornee pour qu'une photo verticale ne pousse
 * pas le reste de la conversation hors de l'ecran. */
.bulle.media { padding: 0; overflow: hidden; background: var(--bulle-autre); }
.msg.moi .bulle.media { background: var(--bulle-autre); }
/* Une MINIATURE, pas la photo entiere. Une image pleine hauteur chasse la
 * conversation hors de l'ecran : on ne voit plus ce qui a ete dit autour.
 * Le plein ecran se demande d'un clic. */
.bulle.media img {
  display: block; cursor: zoom-in;
  width: 220px; max-width: 62vw; height: auto;
  max-height: 300px; object-fit: cover;
}
.media-attente {
  display: grid; place-items: center; gap: 8px;
  width: 220px; max-width: 62vw; min-height: 150px; color: var(--texte-doux);
  font-size: 12.5px; background: var(--accent-doux);
}
.media-attente .rond { width: 26px; height: 26px; border-width: 2.5px; }

.fichier {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 8px 10px 12px; color: inherit; min-width: 240px;
}
.fichier .corps-fichier { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.actions-fichier { display: flex; gap: 2px; flex: 0 0 auto; }
.actions-fichier button {
  font: inherit; cursor: pointer; background: transparent; border: 0;
  color: var(--texte-doux); width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
}
.actions-fichier button:hover { background: var(--trait); color: var(--texte); }
.actions-fichier svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.fichier .vignette {
  width: 38px; height: 38px; border-radius: 9px; flex: 0 0 auto;
  display: grid; place-items: center; background: var(--accent-doux);
}
.fichier .vignette svg { width: 19px; height: 19px; fill: none;
  stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.fichier .nom-fichier { font-weight: 600; font-size: 14px; word-break: break-all; }
.fichier .poids { font-size: 12px; opacity: .75; }

/* Une photo ouverte en grand, sur fond sombre. */
.visionneuse {
  position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,.92);
  display: grid; place-items: center; padding: 16px; cursor: zoom-out;
}
.visionneuse img { max-width: 100%; max-height: 100%; }

/* ------------------------------------------------- PHOTO EN GRAND */
/* Modele des messageries usuelles, et il tient en trois partis pris :
 *   - une BARRE en haut, pas des boutons flottants poses sur la photo ;
 *   - la fermeture est une fleche RETOUR a gauche, le geste attendu, pas une
 *     croix (premiere version : elle etait hors du groupe de boutons, donc
 *     sans style du tout -- un rond blanc vide) ;
 *   - l'image occupe TOUT le reste, bord a bord. Sans ca on voit du vide
 *     autour et ca ne ressemble pas a du plein ecran.
 */
.visionneuse {
  display: flex; flex-direction: column;
  /* align-items: stretch EXPLICITE. La regle generale .voile pose
   * place-items: center, qui s'applique aussi en flex : la barre ne faisait
   * alors que la largeur de son contenu, centree -- fleche, nom et boutons
   * se retrouvaient tasses au milieu au lieu de tenir les deux bords.
   * (Vu par le user le 26/09.) */
  align-items: stretch;
  background: #000; padding: 0; cursor: default;
}
.visionneuse-barre {
  display: flex; align-items: center; gap: 2px; flex: 0 0 auto;
  width: 100%;
  padding: 8px 8px 8px 2px;
  padding-top: calc(8px + env(safe-area-inset-top));
  background: rgba(0,0,0,.92); color: #fff;
}
.visionneuse-barre .vis-titre {
  /* flex: 1 1 0 pour absorber TOUT l'espace libre : c'est lui qui repousse
   * les deux boutons d'action contre le bord droit. */
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  margin-left: 6px; margin-right: 8px;
}
.visionneuse-barre .vis-titre strong {
  font-size: 15.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.visionneuse-barre .vis-titre span { font-size: 12.5px; color: rgba(255,255,255,.66); }
.visionneuse button {
  font: inherit; cursor: pointer; background: transparent; border: 0;
  color: #fff; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center; flex: 0 0 auto;
}
.visionneuse button:hover { background: rgba(255,255,255,.16); }
.visionneuse svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.vis-image {
  flex: 1 1 auto; min-height: 0; width: 100%;
  display: grid; place-items: center; overflow: hidden;
}
.vis-image img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* --------------------------------------------------------- REPONSES */
/* Le message cite, au-dessus de la saisie. Le trait vertical colore est la
 * convention de toutes les messageries : on comprend sans legende. */
.barre-reponse {
  display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
  padding: 8px 10px 8px 12px; background: var(--fond-liste);
  border-top: 1px solid var(--trait);
}
.reponse-trait { width: 3px; align-self: stretch; border-radius: 2px; background: var(--accent); }
.reponse-corps { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.reponse-corps strong { font-size: 13px; color: var(--accent); }
.reponse-corps span {
  font-size: 13px; color: var(--texte-doux);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La citation DANS une bulle. */
.citation {
  display: flex; gap: 8px; margin: 0 0 6px; padding: 6px 8px;
  border-radius: 8px; background: rgba(0,0,0,.07); font-size: 13px;
  cursor: pointer;
}
.msg.moi .citation { background: rgba(255,255,255,.16); }
.citation .trait { width: 3px; border-radius: 2px; background: currentColor; opacity: .55; }
.citation .texte { min-width: 0; display: flex; flex-direction: column; }
.citation .qui { font-weight: 600; opacity: .9; }
.citation .quoi { opacity: .75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Le message glisse vers la droite pendant qu'on tire dessus. */
.msg { transition: transform .18s ease; }
.msg.glisse { transition: none; }

/* --------------------------------------------------------- REACTIONS */
.reactions { display: flex; flex-wrap: wrap; gap: 4px; margin: 3px 4px 0; }
.msg.moi .reactions { justify-content: flex-end; }
.reaction {
  display: flex; align-items: center; gap: 4px; cursor: pointer;
  font: inherit; font-size: 13px; line-height: 1;
  background: var(--fond); color: var(--texte);
  border: 1px solid var(--trait); border-radius: 12px; padding: 3px 8px;
}
.reaction.mienne { background: var(--accent-doux); border-color: var(--accent); }
.reaction .nb { font-size: 11.5px; color: var(--texte-doux); }

.choix-reaction {
  position: fixed; z-index: 70; display: flex; gap: 2px;
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 24px; padding: 6px; box-shadow: 0 10px 30px rgba(0,0,0,.22);
}
.choix-reaction button {
  font-size: 24px; line-height: 1; cursor: pointer;
  background: transparent; border: 0; border-radius: 50%;
  width: 44px; height: 44px; display: grid; place-items: center;
}
.choix-reaction button:hover { background: var(--trait); }

/* ---------------------------------------------------------- PROFIL */
.pastille-bouton { border: 0; cursor: pointer; padding: 0; font: inherit; }
.pastille-bouton:hover { filter: brightness(1.08); }
.pastille-grande { width: 96px; height: 96px; font-size: 34px; cursor: pointer; }
.profil-haut { display: flex; flex-direction: column; align-items: center; gap: 12px; }

/* ------------------------------------------- VIGNETTE D UNE CITATION */
/* Repondre a une photo en affichant le mot « Photo » fait perdre la seule
 * information qui compte : DE QUELLE photo on parle. */
.vignette-citee {
  width: 42px; height: 42px; flex: 0 0 auto;
  border-radius: 7px; object-fit: cover; background: var(--trait);
}
.citation .vignette-citee { width: 38px; height: 38px; margin-left: auto; }
.citation .texte { flex: 1; }

/* ------------------------------------------------------- RECADRAGE */
.recadrage .cadre { position: relative; align-self: center; }
.recadrage .toile {
  width: min(280px, 68vw); height: min(280px, 68vw);
  display: block; border-radius: 12px; touch-action: none; cursor: grab;
}
/* Le masque rond montre ce qui sera reellement garde : un avatar est
 * toujours affiche en cercle, autant cadrer sur ce qu'on verra. */
.recadrage .masque {
  position: absolute; inset: 0; pointer-events: none; border-radius: 12px;
  box-shadow: inset 0 0 0 999px rgba(0,0,0,.45);
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent 49.5%, #000 50%);
  mask: radial-gradient(circle at 50% 50%, transparent 49.5%, #000 50%);
}
.recadrage .zoom { width: 100%; accent-color: var(--accent); }

/* ----------------------------------------------------------- VOCAUX */
#bouton-micro { flex: 0 0 auto; align-self: flex-end; margin-bottom: 2px; }
#bouton-micro svg { width: 22px; height: 22px; }
.barre-vocal {
  display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
  padding: 8px 10px; background: var(--fond-liste);
  border-top: 1px solid var(--trait); font-size: 14px;
}
.barre-vocal .vocal-texte { flex: 1; color: var(--texte-doux); }
.barre-vocal .envoyer { color: var(--accent); }
.point-rouge {
  width: 10px; height: 10px; border-radius: 50%; background: var(--danger);
  animation: pulse 1.1s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }

/* Le lecteur d'un vocal recu. */
.lecteur {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px 9px 9px; min-width: 210px;
}
.lecteur button {
  width: 38px; height: 38px; border-radius: 50%; flex: 0 0 auto;
  border: 0; cursor: pointer; display: grid; place-items: center;
  background: var(--accent); color: #fff;
}
.msg.moi .lecteur button { background: rgba(255,255,255,.22); }
.lecteur svg { width: 17px; height: 17px; fill: currentColor; stroke: none; }
.lecteur .piste {
  flex: 1; height: 4px; border-radius: 2px; overflow: hidden;
  background: currentColor; opacity: .28;
}
.lecteur .avance { height: 100%; width: 0; background: currentColor; opacity: 1; }
.lecteur .temps { font-size: 12px; opacity: .8; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- PIED DE LA LISTE */
/* Occupe le bas de l'ecran quand il y a peu de conversations, et dit ce que
 * fait cette application -- plutot que de meubler avec du decor muet. */
.pied-liste {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  gap: 7px;
  /* La marge de droite reserve la place du bouton d'ecriture, qui flotte
   * par-dessus : sans elle, le texte passe dessous sur un ecran etroit. */
  padding: 12px 88px calc(12px + env(safe-area-inset-bottom)) 16px;
  font-size: 11.5px; color: var(--texte-doux); text-align: center;
}
@media (min-width: 761px) { .pied-liste { padding-right: 16px; } }
.pied-liste svg {
  width: 13px; height: 13px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* --------------------------------------------- ACCUSES ET FRAPPE */
/* Un seul crochet : parti du telephone. Deux : quelqu'un l'a ouvert.
 * C'est la question que tout le monde se pose -- « elle l'a vu ? » */
.meta .etat-envoi { margin-left: 5px; letter-spacing: -2px; }
.meta .etat-envoi.lu { color: var(--accent); }

/* Dans un groupe, la photo a cote du message : sans elle, trois personnes qui
 * se repondent deviennent illisibles. */
.msg.autre { flex-direction: row; align-items: flex-end; gap: 8px; }
.msg.autre .corps-msg { display: flex; flex-direction: column; min-width: 0; }
.pastille-msg {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 12px; font-weight: 600;
  color: #fff; background: var(--accent);
  background-size: cover; background-position: center; margin-bottom: 18px;
}
.pastille-msg.creux { background: none; }        /* place gardee, rien dessine */

.frappe { font-style: italic; }

.personne.notes { border: 1px solid var(--trait); margin-bottom: 4px; }

/* --------------------------------------------------- MISE A JOUR */
/* En bas de l'ecran, au-dessus de tout : une mise a jour se remarque, mais
 * elle ne doit pas prendre la place d'une conversation. */
.bandeau-maj {
  position: fixed; z-index: 80;
  left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--fond); color: var(--texte);
  border: 1px solid var(--trait); border-radius: 14px;
  padding: 13px 15px; box-shadow: 0 10px 30px rgba(0,0,0,.20);
}
.bandeau-maj > div:first-child { flex: 1; min-width: 180px; }
.bandeau-maj strong { display: block; font-size: 14.5px; }
.bandeau-maj p { margin: 2px 0 0; font-size: 13px; color: var(--texte-doux); }
.bandeau-maj-actions { display: flex; gap: 8px; margin-left: auto; }
.bandeau-maj-actions button {
  font: inherit; font-weight: 600; font-size: 14px; cursor: pointer;
  border: 0; border-radius: 10px; padding: 9px 16px;
  background: var(--accent); color: #fff; min-width: 96px;
}
.bandeau-maj-actions button:hover { background: var(--accent-sombre); }
.bandeau-maj-actions button:disabled { opacity: .65; cursor: progress; }
.bandeau-maj-actions .secondaire {
  background: transparent; color: var(--texte-doux); min-width: 0;
}
.bandeau-maj-actions .secondaire:hover { background: var(--trait); color: var(--texte); }

/* Un depart de conversation ne se reprend pas : le bouton doit etre rouge,
 * pas violet comme une validation ordinaire. */
.dialogue-boutons .danger { background: var(--danger, #c62828); }
.dialogue-boutons .danger:hover { background: #a81f1f; }

/* Le doigt est pose : la ligne reagit tout de suite, sinon on ne sait pas si
 * l'appui long a commence. */
.conversation.presse { background: var(--accent-doux); }

.inviter-actions { display: flex; gap: 10px; justify-content: center; margin-top: 12px; }
#inviter-saisie { display: flex; flex-direction: column; gap: 14px; }
#inviter-code { font-size: 18px; }

/* L'invitation s'ouvre DEPUIS le profil : elle doit passer au-dessus de lui.
 * A niveau egal, c'est l'ordre de la page qui tranche -- et le profil est
 * declare plus bas, donc il gagnait et masquait l'invitation. */
#dialogue-inviter { z-index: 60; }

/* Une invitation en attente : elle se distingue sans crier, et son apercu
 * dit quoi faire. */
.conversation.invitation .apercu { color: var(--accent); font-weight: 600; }

/* L'invitation a installer l'application, dans la liste. Visible sans etre
 * criarde : elle doit se remarquer une fois, pas tous les jours. */
.bandeau-app {
  display: flex; align-items: center; gap: 10px;
  margin: 10px 14px 0; padding: 11px 13px;
  background: var(--accent-doux); border-radius: 12px;
  font-size: 13px; line-height: 1.4; color: var(--texte);
}
.bandeau-app button {
  font: inherit; font-weight: 600; white-space: nowrap; cursor: pointer;
  border: 0; border-radius: 9px; padding: 8px 14px;
  background: var(--accent); color: #fff;
}

/* L'accueil de quelqu'un qui arrive par son invitation. */
.accueil-texte { margin: 0; font-size: 14px; line-height: 1.55; color: var(--texte-doux); }
.accueil-suite { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--texte-doux); }
#ecran-accueil button[type="button"]:not(.lien) {
  font: inherit; font-weight: 600; font-size: 15px; cursor: pointer;
  border: 0; border-radius: 12px; padding: 14px;
  background: var(--accent); color: #fff;
}
