/* ============================================================================
   FLUVO — couche « NET » (19/09/2026)
   Le langage visuel de l'application : plat, calme, mat. Depuis le 08/10/2026
   la coque (rail, liste, conversation) est dans `classique.css`, chargée en dernier. La couleur reste celle de Fluvo :
   reprendre le vert et le papier peint de WhatsApp serait copier son
   identité, pas s'en inspirer.

   Chargée après style.css, densite.css, mobile.css et sobre.css ; seules
   palettes.css (couleurs) et coffre.css viennent après.
   Elle remplace `verre.css` (supprimé le 19/09/2026) : les composants nés avec
   la refonte du 15/09 (réglages en onglets, accueil, arrivée des messages)
   n'ont de style QU'ICI.

   LES TROIS RÈGLES DE CETTE COUCHE
   1. 🔴 Aucune matière : pas de `backdrop-filter`, pas de halo, pas de dégradé,
      pas de grain. Une surface est un aplat, et sa limite est un filet d'1 px.
      C'est ce qui rend le texte lisible sans voile de contraste et ce qui fait
      tenir le défilement sur un GPU de téléphone.
   2. 🔴 Les profondeurs viennent du FILET et de la toile. Les modules du
      studio ont une ombre courte (`--st-relief`) ; seules les surfaces qui
      FLOTTENT vraiment (menu, modale, actions au survol) en ont une longue.
   3. 🔴 On n'anime que `transform` et `opacity`, jamais plus de 200 ms. Aucune
      animation infinie : le fond ne bouge plus.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. JETONS
   Posés sur :root SANS !important : un thème personnel injecte ses 33 variables
   en !important, et ces jetons-ci n'en font pas partie — ils doivent survivre.
   --------------------------------------------------------------------------- */
:root {
  --t-micro: 100ms;   /* survol, pression */
  --t-std: 160ms;     /* changement d'état */
  --t-entree: 200ms;  /* apparition */
  --e-sortie: cubic-bezier(.22, .78, .16, 1);

  /* Profondeur : deux marches, et elles ne servent qu'à ce qui flotte. */
  --p1: 0 1px 1px rgba(11, 20, 26, .13);
  --p2: 0 2px 5px rgba(11, 20, 26, .18);
  --p3: 0 12px 34px -8px rgba(11, 20, 26, .30);

  /* Surfaces déduites du thème actif, pour que les thèmes anciens et personnels
     restent affichables : une surface est le fond légèrement tiré vers le texte. */
  --n-surf: color-mix(in srgb, var(--bg) 94%, var(--txt) 6%);
  --n-fil: var(--bg);
  --n-champ: color-mix(in srgb, var(--bg) 90%, var(--txt) 10%);
  --n-filet: var(--bord);
  --n-sel: color-mix(in srgb, var(--bg) 90%, var(--txt) 10%);

  /* Encre sur MA bulle. Jamais --txt2/--txt3 (calibrés pour le fond), jamais
     d'`opacity` : une couleur déclarée, auditable. */
  --n-moi: var(--moi-txt);
  --n-moi-2: color-mix(in srgb, var(--moi-txt) 62%, transparent);
  --sur-accent: #ffffff;
}

/* Les trois thèmes « Net » déclarent leurs surfaces au lieu de les déduire :
   le blanc pur d'un panneau ne se calcule pas depuis un fond gris. */

/* 🔴 Même règle que sobre.css : `--opaque` — fond des menus et des modales —
   dérive du FOND du thème actif, jamais de `body[data-theme]`. Un thème
   personnel rend `data-theme` faux et donnerait des menus clairs sur une
   application sombre. */
:root, body[data-theme] { --opaque: var(--n-surf); }

/* ---------------------------------------------------------------------------
   2. LE FOND — il ne se passe plus rien derrière
   🔴 `style.css:138` pose `filter: blur(90px)` et une taille fixe sur
   `body::before`, et `sobre.css` lui remet de l'opacité : cesser de déclarer ne
   suffit pas, il faut éteindre les trois halos explicitement.
   --------------------------------------------------------------------------- */
body::before, body::after, #racine::before { display: none !important; }
body { background: var(--n-fil); }

/* ---------------------------------------------------------------------------
   3. OSSATURE — le studio : trois modules posés sur une toile mate
   Rail (dock), liste et conversation sont des surfaces distinctes, arrondies,
   séparées par la toile. Géométrie et couleurs de la coque : classique.css.
   --------------------------------------------------------------------------- */
#rail, #panneau, #vue {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
#rail { z-index: 3; }

/* ---------------------------------------------------------------------------
   4. RAIL
   L'onglet actif se marque par un aplat discret et un filet de 3 px à gauche —
   pas par un dégradé lumineux.
   --------------------------------------------------------------------------- */
.rail-item {
  position: relative;
  border-radius: 10px;
  color: var(--txt2);
  transition: background-color var(--t-micro) var(--e-sortie), color var(--t-micro) var(--e-sortie);
}
.rail-item::before { display: none; }
.rail-item:hover { background: var(--survol); color: var(--txt); }
.rail-item.on { background: var(--n-sel); color: var(--accent); box-shadow: none; }
.rail-item.on .rl { color: var(--accent); }
.rail-item:active { transform: none; }
#logo-rail { transition: none; }
#logo-rail:hover { transform: none; }

/* Réseaux sans logo : une pastille à l'initiale, à plat. */
.rail-item .ri.logo-rail {
  width: 26px; height: 26px; border-radius: 8px;
  display: grid; place-items: center;
  color: #fff; font-size: 13px; font-weight: 700; line-height: 1;
  box-shadow: none;
}
.rail-item .rl {
  white-space: normal; overflow: hidden; overflow-wrap: normal; word-break: normal;
  -webkit-hyphens: auto; hyphens: auto;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  text-overflow: clip; max-width: 66px; line-height: 1.12; letter-spacing: -.01em;
}
@media (max-width: 760px) {
  #rail .rail-item.dossier { display: none !important; }
  .rail-item .rl { -webkit-line-clamp: 1; white-space: nowrap; text-overflow: ellipsis; display: block; }
}

/* ---------------------------------------------------------------------------
   5. PANNEAU ET LISTE
   En-tête et recherche sont des barres pleines : rien ne passe dessous, donc
   rien à flouter.
   --------------------------------------------------------------------------- */
#panneau > .h {
  position: sticky; top: 0; z-index: 4;
  background: var(--n-surf);
  border-bottom: none;
  box-shadow: none;
  border-radius: 0;
  padding: 10px 16px;
}
#panneau .rech {
  position: sticky; top: var(--h-entete, 54px); z-index: 3;
  background: var(--n-surf);
  box-shadow: none; border-radius: 0;
  padding: 4px 12px 8px;
}
#panneau .rech input {
  background: var(--n-champ); border: 1px solid transparent;
  border-radius: 999px; padding: 9px 14px; font-size: 14px;
}
#panneau .rech input:focus { border-color: var(--accent); outline: none; }
#panneau .h #b-ecrire { margin-left: auto; }

.liste { padding: 0; scroll-behavior: auto; }

/* Une ligne pleine largeur, séparée de la suivante par un filet qui commence
   après l'avatar — c'est ce décalage qui fait lire la colonne comme une liste
   et non comme une pile de cartes. */
.chat {
  border-radius: 0;
  position: relative;
  margin: 0;
  padding: 9px 16px;
  gap: 13px;
  transition: background-color var(--t-micro) var(--e-sortie);
}
.chat::before { display: none; }
.chat::after {
  content: ""; position: absolute; left: 72px; right: 0; bottom: 0;
  height: 1px; background: var(--n-filet);
}
.chat:last-child::after { display: none; }
.chat:hover { background: var(--survol); }
.chat.on { background: var(--n-sel); box-shadow: none; }
.chat:active { transform: none; }
.chat .av { border-radius: 50%; }
.chat:hover .av { border-radius: 50%; }
.chat.nonlu::after { background: var(--n-filet); }
.chat.nonlu .nom { font-weight: 650; }
.chat.nonlu .badge { background: var(--accent); color: var(--sur-accent); font-weight: 600; }
.chat .avw .logo-res { position: absolute; right: -3px; bottom: -3px; }
.chat .avw .badge-fusion .logo-res { position: static; }
.logo-res { box-shadow: 0 0 0 2px var(--n-surf); }
.chat.on .logo-res { box-shadow: 0 0 0 2px var(--n-sel); }
.chat .epingle { font-size: 11px; opacity: .75; margin-right: 4px; line-height: 1; }
.chat .brouillon { color: var(--dan); font-weight: 600; }
.chat .apercu.est-brouillon { font-style: italic; color: var(--txt2); }
.chat:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
.chat .txt, .chat .l1 .nom { min-width: 0; }

/* Barre de filtres : des onglets soulignés, pas des pilules. */
.barre { padding: 0 12px; }
.filtre-res, .barre button { border-radius: 999px; }

/* ---------------------------------------------------------------------------
   6. LE FIL — l'écran le plus regardé
   Fond uni, bulles à faible rayon, une ombre d'un pixel. Pas de papier peint :
   celui de WhatsApp est à lui.
   --------------------------------------------------------------------------- */
#vue > header.h {
  position: sticky; top: 0; z-index: 4;
  background: var(--n-surf);
  border-bottom: 1px solid var(--n-filet);
  box-shadow: none; border-radius: 0;
}
.fil { max-width: none; margin-inline: 0; width: 100%; padding: 12px 5% 10px; gap: 2px; }
@media (max-width: 1100px) { .fil { padding: 12px 4% 10px; } }
@media (max-width: 760px) { .fil { padding: 10px 10px 8px; } }

.msg {
  border-radius: 8px;
  background: var(--bulle);
  /* 🔴 `--bulle-txt` n'existe QUE si une couleur de bulle a été choisie dans les
     réglages : le repli sur `--txt` est le cas normal. Sans cette variable, une
     bulle claire choisie en thème sombre recevait du texte clair. */
  color: var(--bulle-txt, var(--txt));
  box-shadow: var(--p1);
  border: none;
}
/* La première bulle d'une série porte le bec ; les suivantes sont franches. */
.msg:not(.suite) { border-top-left-radius: 2px; }
.msg.suite { border-radius: 8px; margin-top: 2px; }

.msg.moi {
  background: var(--bulle-moi);
  color: var(--n-moi);
  border-radius: 8px;
  box-shadow: var(--p1);
}
.msg.moi:not(.suite) { border-top-left-radius: 8px; border-top-right-radius: 2px; }
.msg.moi.suite { border-radius: 8px; }

/* 🔴 L'heure et les coches vivent DANS la bulle, en bas à droite, et ne
   descendent jamais des couleurs du fond : mesure du 11/09/2026, l'horodatage
   de mes propres messages tombait à 1,36:1 en clair. Une couleur déclarée. */
.msg .coche, .msg time, .msg .h { color: var(--txt3); opacity: 1; }
.msg.moi, .msg.moi .exp { color: var(--n-moi); }
.msg.moi .h,
.msg.moi .coche,
.msg.moi .exp,
.msg.moi time,
.msg.moi .cite .qui { color: var(--n-moi-2); opacity: 1; }
.msg .coche { margin-left: 8px; }

.msg.mentionne { box-shadow: var(--p1), inset 3px 0 0 var(--accent); }
.msg.encours { opacity: .65; }
.msg.echec { box-shadow: inset 0 0 0 1px var(--dan); }
.msg.echec .h span[role="button"] { color: var(--dan); font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }

/* L'auteur, dans un groupe : une ligne colorée au-dessus du texte. */
.msg .exp { font-weight: 600; font-size: 12.5px; }

/* Séparateur de jour et de réseau : une pastille centrée, façon « Aujourd'hui ». */
.jour span, .reseau-sep {
  background: var(--n-surf); color: var(--txt2);
  border-radius: 999px; box-shadow: var(--p1);
}
.reseau-sep { padding: 3px 12px; font-size: 11.5px; width: fit-content; margin: 12px auto 8px; }
.reseau-sep::before, .reseau-sep::after { content: none; }

/* ---------------------------------------------------------------------------
   7. COMPOSEUR — base ; la bande collée en bas est dans classique.css
   --------------------------------------------------------------------------- */
.saisie {
  margin: 0; border-radius: 0;
  background: var(--n-surf);
  border-top: 1px solid var(--n-filet);
  box-shadow: none;
  padding: 8px 12px;
  gap: 8px;
  align-items: flex-end;
}
.saisie:focus-within { box-shadow: none; }
.saisie textarea {
  background: var(--n-champ);
  border: none; border-radius: 20px;
  padding: 10px 14px;
}
.saisie textarea:focus { outline: none; }
.env {
  border-radius: 50%;
  background: var(--accent);
  color: var(--sur-accent);
  box-shadow: none;
  transition: filter var(--t-micro) var(--e-sortie);
}
.env:hover { filter: brightness(1.08); transform: none; }
.env:active { transform: scale(.94); }
.saisie .micro { color: var(--txt2); }
.saisie .micro.enregistre { color: #fff; background: var(--dan); border-radius: 50%; }

/* Pièce jointe et envoi programmé : des bandeaux dans la barre, pas des cartes. */
.prog-attente {
  display: flex; align-items: center; gap: 10px;
  margin: 0; padding: 8px 14px; border-radius: 0;
  background: var(--n-champ); box-shadow: none;
  border-top: 1px solid var(--n-filet);
  color: var(--txt2);
}
.prog-attente .pj-inf { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.prog-attente .pj-inf b { color: var(--accent); font-size: 12px; }
.prog-attente .pj-inf span { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pj-attente.envoi { opacity: .72; position: relative; overflow: hidden; }
.pj-attente.envoi::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--accent); transform-origin: 0 50%;
  animation: net-progres 1.2s linear infinite;
}
@keyframes net-progres { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.menu.prog { min-width: 220px; }
.menu.prog .titre { color: var(--txt3); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }

/* ---------------------------------------------------------------------------
   8. MENUS, FEUILLES, MODALES — les seules surfaces qui flottent
   --------------------------------------------------------------------------- */
.menu, .boite, .sugg, #galerie, #volet, #gglobale {
  background: var(--n-surf);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 1px solid var(--n-filet);
  box-shadow: var(--p3);
}
.menu, .boite { border-radius: 12px; }
.menu { max-width: calc(100vw - 16px); max-height: calc(100dvh - 16px); overflow-y: auto; }
.boite { animation: net-surgir var(--t-entree) var(--e-sortie) both; }
@keyframes net-surgir {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
/* 🔴 `.modal` est le FOND plein écran, `.boite` la carte : le fond reste un
   voile, sinon l'application disparaît derrière une grande carte opaque. */
.modal {
  background: rgba(11, 20, 26, .48);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: none; border-radius: 0; box-shadow: none;
  animation: net-fondu var(--t-std) var(--e-sortie) both;
}
@keyframes net-fondu { from { opacity: 0; } to { opacity: 1; } }

.btn {
  border-radius: 999px; font-weight: 600; box-shadow: none;
  background: var(--accent); color: var(--sur-accent); border: none;
}
.btn:hover { filter: brightness(1.06); }

/* ---------------------------------------------------------------------------
   9. ACCESSIBILITÉ
   Plus de voile de contraste à poser : les surfaces sont opaques, le contraste
   est celui qu'on a déclaré.
   --------------------------------------------------------------------------- */
#rail::after, .saisie::after, #vue header.h::after, #panneau > .h::after { content: none; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* 🔴 Les actions ne quittent jamais l'arbre d'accessibilité : `display: none`
   jusqu'au survol les retirait de la tabulation ET les supprimait au doigt,
   c'est-à-dire dans l'APK réellement distribué. On ne joue que sur l'opacité. */
.msg .actions, .chat .actions {
  display: flex; opacity: 0; pointer-events: none;
  transition: opacity var(--t-micro) var(--e-sortie);
}
.msg:hover .actions, .msg:focus-within .actions, .msg .actions:focus-within,
.chat:hover .actions, .chat:focus-within .actions { opacity: 1; pointer-events: auto; }

@media (hover: hover) {
  .chat .actions {
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    margin: 0; padding: 3px; gap: 2px; z-index: 2;
    border-radius: 10px;
    background: var(--n-surf);
    border: 1px solid var(--n-filet);
    box-shadow: var(--p2);
  }
  .chat .actions .act { background: transparent; }
  .chat .actions .act:hover { background: var(--accent); color: var(--sur-accent); }
}
@media (hover: none) {
  .msg .actions, .chat .actions { opacity: 1; pointer-events: auto; }
  .chat .actions { background: none; border: 0; box-shadow: none; padding: 0; margin-left: 2px; }
  .chat .actions .act { background: transparent; color: var(--txt3); width: 28px; height: 36px; }
  /* Pas les trois raccourcis sur chaque ligne : à 412 px ils mangent un tiers
     de la largeur. Seul le « ⋯ » reste, il ouvre le même menu. */
  .chat .actions .act:not(:last-child) { display: none; }
  .chat .date, .chat:hover .date { display: inline; }
}
.msg .actions { background: var(--n-surf); border: 1px solid var(--n-filet); box-shadow: var(--p2); border-radius: 10px; padding: 3px; }

/* ---------------------------------------------------------------------------
   10. MOBILE
   La WebView de l'APK affiche ce site : ces règles sont l'expérience réelle.
   --------------------------------------------------------------------------- */
@media (max-width: 820px) {
  .saisie {
    margin: 0;
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    border-radius: 0;
  }
  #rail {
    backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  }
  .rail-item, .barre button, .icone, .env { min-height: 44px; min-width: 44px; }
  .chat::after { left: 66px; }
}
@media (max-width: 760px) {
  #vue > header.h { gap: 2px; }
  #vue > header.h .titre { flex: 1 1 auto; min-width: 0; }
  #vue > header.h .titre h1 { font-size: 16.5px; }
  #vue > header.h .icone { min-width: 44px; min-height: 44px; width: 44px; height: 44px; margin-left: 0; }
  #vue > header.h .icone:first-of-type { margin-left: auto; }
  #vue > header.h .av { width: 34px; height: 34px; flex: none; }
  .saisie .outil-sondage, .saisie .outil-emoji { display: none !important; }
  .saisie .outils { gap: 0; }
  .saisie textarea { padding: 10px 14px; }
  .saisie textarea::placeholder { font-size: 15px; }
}

/* ---------------------------------------------------------------------------
   11. ARRIVÉE D'UN MESSAGE
   Seules les bulles marquées `.neuf` par la réconciliation s'animent (trois au
   plus par rendu) : `transform` et `opacity`, rien ne repasse par la mise en page.
   --------------------------------------------------------------------------- */
.msg.neuf { animation: net-arrivee var(--t-entree) var(--e-sortie) both; }
@keyframes net-arrivee {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   12. ÉTAT VIDE, ACCUEIL, « Afficher plus »
   --------------------------------------------------------------------------- */
.etat-vide .btn {
  margin-top: 14px; padding: 10px 18px; border-radius: 999px;
  background: var(--accent); color: var(--sur-accent);
  font-weight: 600; border: none; cursor: pointer; box-shadow: none; min-height: 44px;
}
.plus-liste { display: block; margin: 10px auto 18px; padding: 9px 16px; border-radius: 999px; font-size: 13px; }

.accueil { display: grid; place-items: center; padding: 32px; background: var(--n-fil); }
.accueil-carte {
  max-width: 400px; text-align: center; padding: 34px 30px 28px;
  border-radius: 12px;
  background: var(--n-surf);
  border: 1px solid var(--n-filet);
  box-shadow: none;
}
.accueil-ic {
  width: 56px; height: 56px; padding: 14px; box-sizing: border-box;
  border-radius: 16px; margin: 0 auto 16px; display: block;
  fill: none; stroke: #fff; stroke-width: 1.8; stroke-linejoin: round;
  background: var(--accent); box-shadow: none;
}
.accueil-titre { margin: 0 0 6px; color: var(--txt); font-size: 18px; font-weight: 700; letter-spacing: -.01em; }
.accueil-texte { margin: 0 0 18px; color: var(--txt2); font-size: 14px; }
.accueil-astuces {
  list-style: none; margin: 0; padding: 14px 0 0; border-top: 1px solid var(--n-filet);
  display: grid; gap: 8px; text-align: left; color: var(--txt2); font-size: 13px;
}
.accueil-astuces li { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.accueil kbd {
  font: 600 11.5px/1 var(--police, system-ui); color: var(--txt);
  padding: 4px 7px; border-radius: 6px; min-width: 14px; text-align: center;
  background: var(--n-champ); box-shadow: none;
}
@media (max-width: 760px) { .accueil-astuces { display: none; } }

/* ---------------------------------------------------------------------------
   13. RECHERCHE DANS LA CONVERSATION
   La barre se glisse sous l'en-tête et pousse le fil ; les résultats la
   prolongent sans couvrir le composeur, pour qu'on puisse répondre en lisant.
   --------------------------------------------------------------------------- */
.h .icone.actif { color: var(--accent); background: var(--n-sel); }
.cherche-fil { flex: none; display: flex; flex-direction: column; min-height: 0; }
.cherche-fil .bar {
  display: flex; align-items: center; gap: 10px;
  margin: 0; padding: 0 14px; height: 46px;
  background: var(--n-surf); border-bottom: 1px solid var(--n-filet); box-shadow: none;
}
.cherche-fil .bar > .ico { flex: none; color: var(--txt3); }
.cherche-fil .bar .ico svg { width: 16px; height: 16px; }
.cherche-fil .bar input {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  color: var(--txt); font: inherit; font-size: 14px;
}
.cherche-fil .bar input::-webkit-search-cancel-button { display: none; }
.cherche-fil .bar .cpt { color: var(--txt3); font-size: 12px; font-variant-numeric: tabular-nums; }
.cherche-fil .bar .x {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none;
  border: 0; border-radius: 6px; background: none; color: var(--txt3); cursor: pointer;
}
.cherche-fil .bar .x .ico svg { width: 15px; height: 15px; }
.cherche-fil .bar .x:hover { background: var(--survol); color: var(--txt); }
.cherche-fil .res { display: none; }
.cherche-fil .res.ouvert {
  display: block; overflow: auto; max-height: 40vh;
  margin: 0; padding: 4px 8px; border-radius: 0;
  background: var(--n-surf); border-bottom: 1px solid var(--n-filet); box-shadow: none;
}
.cherche-fil .res-vide { color: var(--txt3); font-size: 13px; padding: 14px 4px; }
.cherche-fil .res-msg {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  color: inherit; font: inherit; cursor: pointer;
  padding: 8px 10px; border-radius: 8px;
  transition: background var(--t-micro) var(--e-sortie);
}
.cherche-fil .res-msg:hover { background: var(--survol); }
.cherche-fil .res-msg .l1 { display: flex; align-items: baseline; gap: 8px; }
.cherche-fil .res-msg .qui { color: var(--accent); font-size: 12px; font-weight: 600; }
.cherche-fil .res-msg .quand { color: var(--txt3); font-size: 11px; margin-left: auto; }
.cherche-fil .res-msg .txt {
  color: var(--txt2); font-size: 13px; margin-top: 2px;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.cherche-fil .res-msg mark { background: color-mix(in srgb, var(--accent) 30%, transparent); color: var(--txt); border-radius: 3px; }

/* ---------------------------------------------------------------------------
   14. « ÉCRIRE À QUELQU'UN » — le carnet des passerelles
   --------------------------------------------------------------------------- */
.boite.ecrire { width: min(94vw, 520px); }
.boite.ecrire .emoji-rech { width: 100%; margin: 8px 0 4px; }
.carnet { max-height: min(56vh, 460px); overflow: auto; margin-top: 6px; }
.carnet .contact {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  border: 0; background: none; color: inherit; font: inherit; cursor: pointer;
  padding: 9px 10px; border-radius: 8px;
  transition: background var(--t-micro) var(--e-sortie);
}
.carnet .contact:hover { background: var(--survol); }
.carnet .contact .av {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700; font-size: 14px;
  background: var(--bg4); color: var(--txt2);
}
.carnet .contact .txt { flex: 1; min-width: 0; }
.carnet .contact .nom { color: var(--txt); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carnet .contact .sous { color: var(--txt3); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carnet .contact .etiq {
  flex: none; font-size: 11px; padding: 2px 8px; border-radius: 999px;
  color: var(--txt3); background: var(--n-champ);
}
.carnet .contact .etiq:not(:empty) { text-transform: uppercase; letter-spacing: .05em; }

/* ---------------------------------------------------------------------------
   15. RÉSEAUX CONNECTÉS ET FENÊTRE DE CONNEXION
   🔴 Un seul compte par réseau (la passerelle rend `TOO_MANY_LOGINS` au
   second) : « Connecter » n'apparaît que là où il peut aboutir.
   --------------------------------------------------------------------------- */
.reseau-ligne {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 4px; border-bottom: 1px solid var(--n-filet);
}
.reseau-ligne:last-child { border-bottom: 0; }
.reseau-ligne .pastille {
  width: 34px; height: 34px; flex: none; border-radius: 9px;
  display: grid; place-items: center; color: #fff; font-weight: 700; font-size: 15px;
}
.reseau-ligne .txt { flex: 1; min-width: 0; }
.reseau-ligne .nom { color: var(--txt); font-size: 14px; font-weight: 600; }
.reseau-ligne .sous { color: var(--txt3); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reseau-ligne .sous.ko { color: var(--warn); }
.reseau-ligne .etiq.ok {
  flex: none; font-size: 11px; padding: 2px 9px; border-radius: 999px;
  color: var(--ok); background: color-mix(in srgb, var(--ok) 16%, transparent);
}
.boite.connexion { width: min(94vw, 460px); }
.boite.connexion .corps { min-height: 120px; }
.boite.connexion .aide.ko { color: var(--dan); }
.boite.connexion .pied-cnx { margin-top: 14px; display: flex; justify-content: flex-end; }
.cnx-mode { display: block; width: 100%; text-align: left; margin-bottom: 8px; }
.cnx-mode .aide { display: block; font-size: 12px; opacity: .8; margin-top: 2px; }
.cnx-champ { display: block; margin: 10px 0; }
.cnx-champ > span:first-child { display: block; color: var(--txt2); font-size: 12px; margin-bottom: 4px; }
.cnx-champ input {
  width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: 8px;
  border: 1px solid var(--n-filet); background: var(--n-champ); color: var(--txt); font: inherit;
}
.cnx-champ .aide { display: block; font-size: 11px; margin-top: 3px; }
/* Le QR sur fond BLANC, toujours : un lecteur attend du noir sur du clair. */
.cnx-qr {
  display: grid; place-items: center; background: #fff;
  border-radius: 10px; padding: 12px; margin: 10px auto; width: fit-content;
}
.cnx-qr svg { width: 232px; height: 232px; display: block; }
.cnx-ok { color: var(--ok); font-weight: 600; font-size: 15px; padding: 18px 0; text-align: center; }

/* ---------------------------------------------------------------------------
   16. RÉGLAGES — une fenêtre en onglets
   --------------------------------------------------------------------------- */
.modal.reglages { padding: 24px; }
.modal.reglages > .boite {
  width: min(960px, 100%); max-width: none;
  height: min(760px, calc(100dvh - 48px)); max-height: none;
  padding: 0; display: flex; flex-direction: column; overflow: hidden;
}
.reglages-tete {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 18px 14px 24px; border-bottom: 1px solid var(--n-filet);
}
.reglages-tete h1 { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; color: var(--txt); }
.reglages-tete .icone { width: 38px; height: 38px; border-radius: 10px; }
.frg { flex: 1; min-height: 0; display: flex; }
.frg-nav {
  flex: 0 0 228px; display: flex; flex-direction: column; gap: 2px;
  padding: 12px 10px; overflow-y: auto; border-right: 1px solid var(--n-filet);
}
.frg-nav button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; border: 0; border-radius: 8px; background: none;
  color: var(--txt2); font: inherit; font-size: 13.5px; font-weight: 500; text-align: left;
  cursor: pointer; transition: background var(--t-micro) var(--e-sortie), color var(--t-micro) var(--e-sortie);
}
.frg-nav button:hover { background: var(--survol); color: var(--txt); }
.frg-nav button.on { color: var(--accent); font-weight: 600; background: var(--n-sel); box-shadow: none; }
.frg-nav .ic { flex: none; width: 20px; display: grid; place-items: center; font-size: 15px; line-height: 1; }
.frg-nav .ic.ico svg { width: 18px; height: 18px; }
.frg-nav button.on .ic { color: var(--accent); }
.frg-nav .lb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frg-corps { flex: 1; min-width: 0; overflow-y: auto; overflow-x: hidden; padding: 22px 28px 30px; overscroll-behavior: contain; }
.frg-sec[hidden] { display: none !important; }
.frg-sec > h2:first-child { margin: 0 0 14px; font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
.frg-sec > h2 ~ h2 { margin-top: 26px; }
.frg-sec > * { max-width: 100%; }
.frg-sec .aide { line-height: 1.55; }
.frg-sec .regle { border-radius: 10px; }
.regles-pied { margin-top: 14px; }

@media (max-width: 760px) {
  .modal.reglages { padding: 0 !important; }
  .modal.reglages > .boite {
    width: 100vw !important; height: 100dvh !important; max-height: none !important;
    border-radius: 0 !important; padding: 0 !important; border: 0 !important;
  }
  .reglages-tete { padding: calc(10px + env(safe-area-inset-top, 0px)) 12px 10px 18px; }
  .frg { flex-direction: column; }
  .frg-nav {
    flex: none; flex-direction: row; flex-wrap: nowrap !important; gap: 6px;
    padding: 10px 12px; overflow-x: auto; overflow-y: hidden;
    border-right: 0; border-bottom: 1px solid var(--n-filet);
    scrollbar-width: none;
  }
  .frg-nav::-webkit-scrollbar { display: none; }
  .frg-nav button {
    flex: none !important; width: auto; white-space: nowrap; justify-content: flex-start;
    padding: 8px 12px; border-radius: 999px; background: var(--n-champ); min-height: 38px;
  }
  .frg-corps { max-height: none !important; padding: 18px 16px calc(28px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------- Bulle d'actions de l'en-tête du fil ---------- */
/* 🔴 `min-width` remis à zéro : `.menu` en impose 220 px, et la bulle d'icônes
   s'étalait en barre vide sur la moitié de l'en-tête. */
.menu.bulle-act {
  min-width: 0; width: max-content; padding: 5px; display: flex; align-items: center; gap: 2px;
  border-radius: 999px;
}
.bulle-act .bact {
  width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  color: var(--txt2); background: none; border: 0; cursor: pointer; flex: 0 0 auto;
}
.bulle-act .bact svg { width: 19px; height: 19px; }
.bulle-act .bact:hover { background: var(--survol); color: var(--txt); }
/* Un état actif (archivée, en sourdine, épinglée) se lit sur l'icône : sans
   libellé, c'est le seul endroit où l'information peut se dire. */
.bulle-act .bact.actif { color: var(--accent); background: var(--bg4); }

/* La bulle du filtre par réseau : une rangée de logos, et dessous, en toutes
   lettres, ce qui n'a pas de logo (Communautés, dossiers). */
.menu.bulle-res { min-width: 0; width: max-content; padding: 6px; }
.menu.bulle-res .bulle-act { display: flex; align-items: center; gap: 2px; }
.bulle-res .bact { padding: 0; overflow: hidden; }
.bulle-res .bact img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; }
.bulle-res .bact .ini { font-size: 13px; font-weight: 700; }
/* 🔴 Le réseau retenu se marque par un ANNEAU, pas par la teinte du fond : un
   logo rond posé sur un rond coloré ne laissait rien voir du changement. */
.bulle-res .bact.actif { background: none; box-shadow: 0 0 0 2px var(--accent) inset; }
.bulle-res .sep { height: 1px; background: var(--bord); margin: 5px 2px; }

/* ---------- Séparations par mois et choix du mois ---------- */
/* Le titre de mois existait déjà dans la galerie générale ; il sert maintenant
   aussi dans celle d'une conversation, et de cible au saut. */
.gfil .gmois {
  font-size: 12.5px; font-weight: 700; color: var(--txt2);
  padding: 14px 4px 6px; position: sticky; top: 0; z-index: 2;
  background: var(--bg2);
}
.gfil .pile-med { display: flex; flex-direction: column; }
/* 🔴 Le mois visé s'éclaire deux secondes : après un défilement animé, rien ne
   disait où on venait d'arriver. */
.gmois.vise { color: var(--accent); }
.menu.bulle-mois { min-width: 0; width: max-content; max-width: min(92vw, 300px); padding: 6px; }
.bulle-mois .lmois {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: 8px; background: none; border: 0;
  color: var(--txt); cursor: pointer; text-align: left;
}
.bulle-mois .lmois:hover { background: var(--survol); }
.bulle-mois .lmois.choisi { color: var(--accent); font-weight: 600; }
.bulle-mois .lmois .n { flex: 1; }
.bulle-mois .lmois .nb { color: var(--txt3); font-size: 12px; font-variant-numeric: tabular-nums; }
.bulle-mois .lmois.raz { color: var(--txt2); border-top: 1px solid var(--bord); border-radius: 0; margin-top: 4px; }
.bulle-mois .aide-mois { color: var(--txt3); font-size: 11px; padding: 6px 10px 2px; line-height: 1.35; }

/* ---------- Aperçu vidéo dans une bulle ---------- */
/* 🔴 La bulle ne porte plus un <video> mais une <img> : les styles qui visaient
   `video` doivent viser `img` aussi, sinon l'aperçu débordait de la bulle. */
.msg .video-vign img {
  margin-top: 0; pointer-events: none; max-width: 100%;
  display: block; border-radius: inherit; object-fit: cover;
}
/* Aucune vignette disponible : un cadre sobre, au format de la vidéo, qui ne
   coûte rien à afficher. */
.msg .video-vign.sansapercu {
  background: var(--bg4); min-height: 120px; min-width: 180px;
}

/* Palier suivant de la galerie d'une conversation. */
#galerie .gplus { display: block; margin: 12px auto 4px; }
/* 🔴 Une vignette pas encore chargée ne doit RIEN écrire : sans `alt=""` le
   navigateur peint le nom du fichier, et la galerie se couvrait de
   « image.jpg » et d'identifiants à rallonge. La case reste un aplat. */
#galerie .vign img[alt=""] { background: var(--bg3); }

/* ---------- Choix du niveau de zoom (visionneuse) ---------- */
/* 🔴 Le niveau est un BOUTON, plus une simple étiquette : il ouvre la liste
   des niveaux. Il doit donc s'en voir un. */
#visio .zoomniv {
  background: none; border: 0; color: inherit; cursor: pointer; font: inherit;
  padding: 6px 8px; border-radius: 8px; min-width: 62px; font-variant-numeric: tabular-nums;
}
#visio .zoomniv:hover { background: rgba(255,255,255,.14); }
.menu.bulle-zoom { min-width: 0; width: max-content; padding: 6px; z-index: 120; }
.bulle-zoom button {
  display: block; width: 100%; text-align: left; padding: 7px 14px; border: 0;
  background: none; color: var(--txt); border-radius: 8px; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.bulle-zoom button:hover { background: var(--survol); }
.bulle-zoom button.choisi { color: var(--accent); font-weight: 700; }
.bulle-zoom button.raz { border-top: 1px solid var(--bord); border-radius: 0; margin-top: 4px; color: var(--txt2); }

/* Réglages → Premium : ce que l'abonnement contient. */
.prem-liste { margin: 0 0 12px; padding-left: 20px; color: var(--txt2); font-size: 13px; line-height: 1.7; }

/* Réglages : les anciens onglets sont devenus des sous-titres dans leur groupe. */
.frg-sec .frg-sous {
  margin: 18px 0 6px; font-size: 13px; font-weight: 700; color: var(--txt2);
  text-transform: uppercase; letter-spacing: .04em;
}
.frg-sec .frg-sous:first-child { margin-top: 2px; }

/* ---------------------------------------------------------------------------
   L'APERCU COTE DESTINATAIRE (22/09/2026)
   Une ligne au-dessus du champ, et seulement quand quelque chose tombera en
   route. Pas un panneau : sur telephone il n'y a pas la place, et sur grand
   ecran une phrase suffit aussi.
   --------------------------------------------------------------------------- */
.perte {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 10px 6px;
  padding: 6px 10px;
  border-radius: var(--rs, 8px);
  background: var(--n-champ);
  font-size: 12px;
  color: var(--txt2);
}
/* 🔴 `display: flex` ci-dessus battait l'attribut `hidden` : une barre vide restait sous le composeur. */
.perte[hidden] { display: none; }
.perte .perte-x { color: var(--accent); font-weight: 700; flex: none; }
.perte .perte-t { min-width: 0; }
.perte .lien { margin-left: auto; flex: none; }

/* ---------------------------------------------------------------------------
   LE COMPOSEUR UNIVERSEL (22/09/2026)
   Une ligne de faits au-dessus du champ : ou la personne repond, et quel
   reseau dort. 🔴 Des FAITS, pas un conseil — et rien du tout dans une
   conversation a un seul reseau.
   --------------------------------------------------------------------------- */
.canal {
  display: flex; align-items: center; gap: 8px;
  margin: 0 10px 4px; padding: 4px 10px;
  font-size: 11px; color: var(--txt2);
}
.canal .cn-pt { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.canal .cn-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.canal .lien { margin-left: auto; flex: none; }

/* ---------------------------------------------------------------------------
   LA FUSION REVELEE (22/09/2026)
   🔴 Elle disparait d'elle-meme quand tout est confirme : un ecran d'accueil
   qui reste apres avoir servi devient un meuble.
   --------------------------------------------------------------------------- */
.fusion-l {
  display: flex; align-items: center; gap: 9px;
  margin: 4px 8px; width: calc(100% - 16px); padding: 8px 12px;
  border: 1px dashed var(--accent); border-radius: var(--rs, 10px);
  background: none; font: inherit; color: var(--txt);
  font-size: 12px; cursor: pointer; text-align: left;
}
.fusion-l:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.fusion-l .fl-p {
  flex: none; min-width: 19px; height: 19px; border-radius: 10px;
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
  background: var(--accent); color: var(--n-fil);
}

.boite.fusion { max-width: 560px; width: min(560px, 94vw); }
.boite.fusion .bt { display: flex; align-items: center; gap: 8px; }
.boite.fusion .bt h3 { margin: 0; font-size: 16px; }
.boite.fusion .bt .x { margin-left: auto; }
.boite.fusion .fu-ch { display: flex; gap: 22px; margin: 10px 0 4px; }
.boite.fusion .fu-n { display: flex; flex-direction: column; }
.boite.fusion .fu-n b { font-size: 20px; line-height: 1.1; }
.boite.fusion .fu-n span { font-size: 10px; letter-spacing: .06em; color: var(--txt3); text-transform: uppercase; }
.boite.fusion .fu-l { max-height: 46vh; overflow: auto; margin-top: 4px; }
.boite.fusion .fu-c {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--bord);
}
.boite.fusion .fu-g { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.boite.fusion .fu-s { display: flex; align-items: center; gap: 7px; min-width: 0; }
.boite.fusion .fu-pt { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.boite.fusion .fu-nm { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boite.fusion .fu-r { font-size: 11px; color: var(--txt2); flex: none; }
.boite.fusion .fu-a { display: flex; gap: 6px; flex: none; }
.boite.fusion .lien.fort { font-weight: 700; }
@media (max-width: 560px) {
  /* 🔴 Telephone : une decision par ecran, deux boutons sous le pouce. */
  .boite.fusion .fu-c { flex-direction: column; align-items: stretch; gap: 8px; }
  .boite.fusion .fu-a { justify-content: space-between; }
  .boite.fusion .fu-a .lien { flex: 1; padding: 10px 0; text-align: center; }
}

/* ---------------------------------------------------------------------------
   PLUSIEURS COMPTES PAR RESEAU (22/09/2026)
   Une ligne par compte, en retrait sous son reseau. L'ecran n'en montrait
   qu'UN : le deuxieme existait dans la reponse du serveur et restait invisible.
   --------------------------------------------------------------------------- */
.reseau-compte {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 10px 6px 34px;
  border-bottom: 1px solid var(--bord);
}
.reseau-compte .rc-pt { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.reseau-compte .txt { min-width: 0; flex: 1; }
.reseau-compte .nom { font-size: 13px; }
.reseau-compte .sous { font-size: 11px; color: var(--txt2); }
.reseau-compte .sous.ko { color: var(--accent); }
.reseau-compte .lien { flex: none; }

/* ---------------------------------------------------------------------------
   « ACTIF DEPUIS » DANS LE CHOIX DU RESEAU (22/09/2026)
   🔴 Un FAIT date — dernier message ou derniere lecture — jamais « en ligne » :
   aucun reseau ne le dit. Et rien du tout si la personne n'a jamais rien fait
   sur ce reseau : on se tait plutot que d'ecrire « jamais ».
   --------------------------------------------------------------------------- */
.menu .t .act { display: block; font-size: 11px; color: var(--ok, var(--accent)); }
.menu .t .act.dort { color: var(--txt3); }

/* Les puces (communautés, choix) */
.frg .puce, .puce {
  border: 1px solid var(--bord);
  background: var(--n-surf);
  color: var(--txt);
  border-radius: var(--rs, 8px);
  padding: 7px 13px;
  font: 500 13px/1.2 var(--police, system-ui);
  cursor: pointer;
}
.puce:hover { background: var(--survol); }
.puce.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--txt); font-weight: 650; }

/* Une image qui n'a pas pu charger : un cadre qui le DIT, et propose de
   réessayer. 🔴 Sans lui, le navigateur dessinait sa propre icône cassée avec
   l'`alt` — le nom du fichier, « video.mp4 », en clair dans le fil (capture de
   Jérôme, 23/09/2026). L'échec est souvent passager : on ne constate pas, on
   propose de reprendre. */
.media-absent {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; min-height: 96px; max-width: min(320px, 100%);
  margin-top: 4px; padding: 14px 16px;
  border: 1px dashed var(--bord); border-radius: 10px;
  background: var(--n-champ, var(--bg3)); color: var(--txt2); cursor: pointer;
}
.media-absent .ico { opacity: .55; }
.media-absent .ma-t { font-size: 12.5px; }
.media-absent .ma-r {
  border: 1px solid var(--bord); background: var(--n-surf); color: var(--txt);
  border-radius: var(--rs, 8px); padding: 4px 10px; font-size: 12px; cursor: pointer;
}
.media-absent .ma-r:hover { background: var(--survol); }

/* --- Les réactions DANS LA MARGE, pas sous la bulle ----------------------- */
/* 🔴 Demande de Jérôme (23/09/2026) : « pour gagner de la place, mettre les
   réactions à côté du message ». Une pastille sous chaque message ajoute une
   ligne à chaque fois ; sur une conversation où l'on réagit souvent, c'est un
   tiers de la hauteur. La bulle occupe au plus 78 % de la largeur : la place
   existait déjà, elle n'était pas utilisée.
   🔴 Côté EXTÉRIEUR, comme le liseré de réseau : à droite d'un message reçu, à
   gauche des miens. Le côté dit déjà qui parle, les réactions ne doivent pas
   le contredire. */
#vue .fil .msg { position: relative; }
#vue .fil .msg > .reacts {
  position: absolute;
  /* 🔴 EN LIGNE, ET ANCRÉES EN BAS. En colonne, deux réactions remontaient
     au-dessus de la bulle et passaient par-dessus le séparateur de réseau —
     vu à la première capture. En ligne, elles restent dans la hauteur du
     message, qui est précisément la place qu'on cherchait à gagner. */
  bottom: 0;
  left: calc(100% + 6px);
  display: flex;
  flex-flow: row wrap;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 3px;
  margin: 0;
  /* 🔴 `max-content`, sinon la zone se rétrécit à UNE pastille. Un élément
     absolu positionné par `left` seul n'a plus d'espace disponible à droite du
     conteneur : sa largeur « shrink-to-fit » tombe à la plus petite possible,
     et les pastilles s'empilent — mesuré à 28 px de large pour 72 de haut,
     elles remontaient alors par-dessus le séparateur de réseau. */
  width: max-content;
  max-width: 20vw;
}
#vue .fil .msg.moi > .reacts {
  left: auto;
  right: calc(100% + 6px);
  justify-content: flex-end;
}
/* ⚠️ Sur téléphone la bulle prend presque toute la largeur : la marge n'existe
   plus. Les réactions y reprennent leur place sous le message — mieux vaut une
   ligne de plus qu'une pastille hors de l'écran. */
@media (max-width: 760px) {
  #vue .fil .msg > .reacts,
  #vue .fil .msg.moi > .reacts {
    position: static; flex-direction: row; flex-wrap: wrap;
    max-width: none; margin-top: 3px;
  }
}

/* La liste « Qui a réagi » */
.boite.reac-qui { min-width: 260px; max-width: 360px; }
/* ⚠️ L'en-tête ne se met pas en ligne toute seule pour cette boîte : la croix
   tombait sous le titre. */
.boite.reac-qui .bt { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.boite.reac-qui .bt h3 { margin: 0; }
.reac-qui .rq-l { display: flex; gap: 12px; align-items: flex-start; padding: 8px 2px;
  border-top: 1px solid var(--bord); }
.reac-qui .rq-l:first-of-type { border-top: 0; }
.reac-qui .rq-e { font-size: 20px; line-height: 1.2; min-width: 28px; }
.reac-qui .rq-n { display: flex; flex-direction: column; gap: 3px; }
.reac-qui .rq-p { color: var(--txt); font-size: 13.5px; }
.reac-qui .rq-p.moi { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------------------
   17-18. La coque « studio » (toile, dock, tuiles, barre du haut) est retirée
   le 13/10/2026 : la coque de l'application est désormais `classique.css`
   (deux colonnes bord à bord, rail d'icônes, barres vertes).
   --------------------------------------------------------------------------- */
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
.chat .date, .msg .h, .pastille-n, .chat .badge, .reseau-sep, .jour span { font-variant-numeric: tabular-nums; }
