/* ═══════════════════════════════════════════════════════════════════════════
   LISA LAB — Finitions
   Chargée après main.css et responsive.css, dont elle ne reprend rien.

   ── Pourquoi un fichier à part ────────────────────────────────────────────
   main.css est encodé en Windows-1252 et porte un mojibake ancien dans ses
   séparateurs de commentaires : toute réécriture globale l'abîmerait un peu
   plus. Ce fichier-ci est en UTF-8 propre et ne contient que ce qui manquait,
   jamais une redéfinition de ce qui existe déjà. Les variables de couleur,
   de rayon et d'ombre restent celles de main.css : rien n'est redéclaré ici,
   pour qu'un changement de teinte continue de n'avoir qu'un seul endroit.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Le focus au clavier ────────────────────────────────────────────────────
   Les champs de saisie avaient leur anneau, pas les boutons ni les onglets.
   Un opérateur qui tabule dans la barre d'outils ne voyait donc pas où il se
   trouvait, et c'est une façon banale de déclencher la mauvaise action : au
   laboratoire on a souvent une main prise et on navigue au clavier.

   `:focus-visible` et non `:focus` : l'anneau n'apparaît qu'à la navigation
   clavier. Un bouton cliqué à la souris ne garde pas une bague autour de lui,
   ce qui avait fait retirer les outlines au départ.                        */
.btn:focus-visible,
.btn-bandeau:focus-visible,
.btn-cloche:focus-visible,
.btn-deplier:focus-visible,
.nav-tab:focus-visible,
.bloc-repliable > summary:focus-visible,
.details-discret summary:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* Le conteneur visé par le lien d'évitement reçoit le focus pour que la
   lecture d'écran reprenne au bon endroit, mais l'entourer d'un anneau
   reviendrait à cercler toute la page. */
#contenu:focus, #contenu:focus-visible { outline: none; }

/* Sur le bandeau ardoise, le turquoise des boutons se détache mal du fond
   sombre : l'anneau y passe en clair pour rester visible. */
.bandeau .btn-bandeau:focus-visible,
.bandeau .btn-cloche:focus-visible,
.bandeau a:focus-visible {
  outline-color: var(--color-accent);
}

/* Les cases à cocher d'une liste de destinataires sont petites et nombreuses.
   Leur focus doit être franc, sous peine de cocher la mauvaise ligne. */
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}

/* ── Accès direct au contenu ───────────────────────────────────────────────
   Le lien n'apparaît qu'au clavier, au premier Tab. Sans lui, atteindre le
   tableau d'un écran suppose de traverser toute la barre d'onglets à chaque
   changement de page.                                                      */
.lien-evitement {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  padding: 10px 16px;
  background: var(--color-surface); color: var(--color-text);
  border: 2px solid var(--color-primary); border-radius: var(--radius);
  font-size: 13px; font-weight: 600;
}
.lien-evitement:focus {
  left: 12px; top: 10px; text-decoration: none;
}

/* ── Les trois familles de la barre d'onglets ──────────────────────────────
   La barre alignait sur un même rang des choses de natures différentes : des
   écrans que l'on consulte, deux entrées qui ouvrent un acte — un essai, un
   certificat — et le réglage de l'outil. Rien ne les séparait, et le regard
   devait relire les libellés pour retrouver l'entrée cherchée.

   Trois familles, donc, et trois marques de natures différentes :

   — les écrans courants gardent l'apparence d'origine, qui reste la norme ;
   — les actes ferment la liste, précédés d'un filet et cernés d'un contour
     qui les rapproche d'un bouton ;
   — l'administration se détache à droite et prend la forme d'une étiquette
     de réglage : petites capitales espacées.

   Aucune de ces marques n'est une couleur seule. Un écart de teinte ne se
   voit pas d'un œil daltonien et s'efface en niveaux de gris : la place, le
   filet et la casse du libellé portent donc la distinction à eux seuls, la
   teinte ne faisant que l'accompagner. Les droits qui masquent ces onglets
   sont ailleurs — appliquerDroits() dans js/app.js — et n'ont pas bougé.   */

/* Les actes. Le contour remplace 1 px du remplissage pour que la hauteur du
   rang ne change pas : un onglet plus haut que ses voisins décalerait toute
   la ligne de base de la barre. */
.nav-tab--acte {
  position: relative;
  padding: 5px 13px;
  border: 1px solid var(--color-border);
  color: var(--color-text);
  margin-left: 15px;
}
.nav-tab--acte.active { border-color: var(--color-primary); }

/* Le filet qui ouvre la famille. Il est porté par le premier acte encore
   visible, et non par un élément dédié : « Nouvel essai » disparaît pour qui
   n'a pas le droit de créer un dossier, et un séparateur posé en dur serait
   alors resté seul au bord de la barre. */
.nav-tab--acte::before {
  content: "";
  position: absolute; left: -8px; top: 2px; bottom: 2px;
  border-left: 1px solid var(--color-border);
}
.nav-tab--acte:not(.hidden) ~ .nav-tab--acte { margin-left: 4px; }
.nav-tab--acte:not(.hidden) ~ .nav-tab--acte::before { content: none; }

/* L'administration. Le décalage à droite lui vient déjà de main.css ; ce qui
   s'ajoute ici est la forme du libellé, seule chose qui subsiste lorsque la
   barre se replie en colonne et que ce décalage n'a plus de sens.

   Aucune teinte n'est posée : le gris le plus clair de la palette tombe à
   3:1 sur fond blanc, ce qui ne passe pas sur un libellé de 11 px. L'onglet
   garde donc la couleur de ses voisins, et c'est la casse qui le distingue. */
.nav-tab--admin {
  font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em;
}

/* ── La même lecture, barre repliée ────────────────────────────────────────
   En dessous de 860 px la barre devient une liste verticale (responsive.css).
   Le filet des actes y passe à l'horizontale et le décalage à droite de
   l'administration s'annule : il ne reste que l'ordre, le contour et la
   casse — ce qui suffit, et c'est pourquoi la distinction ne tenait pas à la
   seule position.                                                          */
@media (max-width: 860px) {
  .nav-tab--acte { margin: 10px 0 0; }
  .nav-tab--acte::before {
    left: 6px; right: 6px; top: -6px; bottom: auto;
    border-left: 0; border-top: 1px solid var(--color-border);
  }
  .nav-tab--acte:not(.hidden) ~ .nav-tab--acte { margin-top: 0; margin-left: 0; }

  /* Pas de filet ici : l'écart seul détache l'administration du bas de la
     liste, et reprendre le filet des actes brouillerait les deux familles. */
  .nav-tab--admin { margin-top: 10px; }
}

/* ── Les chiffres s'alignent ───────────────────────────────────────────────
   Dans les polices système, les chiffres n'ont pas tous la même largeur : un
   1 est plus étroit qu'un 8. Sur une colonne de doses, de dates ou de numéros
   de série, les unités ne tombent donc pas les unes sous les autres et l'œil
   ne peut plus comparer deux lignes d'un coup. `tabular-nums` leur rend une
   chasse fixe. C'était déjà fait sur .cellule-num, isolément.              */
.table td,
.table th,
.stat-value,
.badge-statut,
.deadline-ok, .deadline-warning, .deadline-danger,
.frise-libelle,
.code-appairage {
  font-variant-numeric: tabular-nums;
}

/* ── Le mouvement, pour qui ne le supporte pas ─────────────────────────────
   La page de connexion respectait déjà ce réglage du système ; l'application
   non, et son chevron de rafraîchissement tournait sans fin. Un mouvement
   permanent dans le champ de vision est pénible, et pour certains il rend
   l'écran inutilisable.                                                    */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Sélection de texte ────────────────────────────────────────────────────
   Le surlignage par défaut du navigateur est un bleu qui n'appartient à
   personne. Celui-ci reste assez pâle pour qu'un numéro de lot recopié à la
   main se lise encore pendant qu'il est sélectionné.                       */
::selection { background: var(--color-primary-fd); color: var(--color-text); }

/* ── Impression ────────────────────────────────────────────────────────────
   Un écran de l'application finit régulièrement sur le bureau de quelqu'un.
   Sans ces règles, l'impression sortait le bandeau ardoise en aplat, les
   onglets, les boutons d'action, et des tableaux dont les filets
   disparaissaient — le papier ne disait plus ce que disait l'écran.

   Rien ici ne touche aux documents du laboratoire : le rapport et le contrat
   ont leurs propres gabarits, composés côté serveur, et ne passent pas par
   cette feuille.                                                           */
@media print {
  /* Ce qui ne sert qu'à naviguer ne s'imprime pas. */
  .bandeau, .barre-nav, .btn-menu,
  .filters-bar, .page-header-actions,
  .btn, .btn-bandeau, .btn-cloche, .btn-deplier,
  .modal, .modal-backdrop, .panneau-taches, .lien-evitement {
    display: none !important;
  }

  body {
    background: #fff !important;
    color: #000 !important;
    font-size: 11pt;
  }

  .tab-content { display: none !important; }
  .tab-content.active { display: block !important; }

  /* Les aplats de couleur ne survivent pas à l'impression par défaut. Sur un
     tableau de bord ce n'est qu'esthétique ; sur le planning des essais, la
     hachure qui distingue une date prévue d'une date relevée porte du sens,
     et la perdre ferait lire une projection comme un enregistrement. */
  .badge-statut, .frise-barre, .frise-fenetre, .frise-echeance,
  .stat-card, .table th,
  .graphe, .graphe *, .pilotage-repartition, .pilotage-part,
  .pastille-secteur, .pastille-etape, .pilotage-pastille-couleur {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Pilotage. Les sous-onglets servent à choisir une vue, pas à la lire : sur
     le papier ils n'offrent plus rien. Seule la vue dépliée s'imprime — les
     deux autres portent la classe « hidden » —, et c'est le titre rendu en
     tête de chaque vue qui dit au lecteur laquelle il a sous les yeux.
     Les commandes de correction disparaissent avec les autres boutons. */
  .sous-onglets, .pilotage-periode-bar, .pilotage-edition,
  .pilotage-select-secteur { display: none !important; }

  /* Un graphique dont les barres et les aires sortiraient en blanc ne dirait
     plus rien ; et coupé en deux par un saut de page, il dirait pire. */
  .pilotage-bloc, .pilotage-graphe, .pilotage-vedette { break-inside: avoid; }
  .pilotage-graphe { overflow: visible !important; }
  .graphe { min-width: 0 !important; }

  /* Les filets du tableau sont la seule chose qui en tient les colonnes. */
  .table, .table th, .table td {
    border: 1px solid #999 !important;
    background: #fff !important;
  }
  .table th { font-weight: 700; }

  /* Une ligne coupée en deux par un saut de page se relit mal, et une
     en-tête de tableau qui reste seule en bas de feuille ne sert à rien. */
  tr, .stat-card, .bloc-repliable, .frise-ligne { break-inside: avoid; }
  thead { display: table-header-group; }
  h2, h3 { break-after: avoid; }

  .stats-strip { display: grid !important; }
  .table-wrapper, .table-wrapper--scroll {
    overflow: visible !important; max-height: none !important;
  }

  /* Un bloc replié resterait fermé sur le papier, et personne ne pourrait
     l'ouvrir. */
  details { display: block !important; }
  details > *:not(summary) { display: block !important; }

  /* L'adresse d'un lien se perd à l'impression ; celles de l'application sont
     internes et sans intérêt sur papier, on ne les ajoute donc pas — mais le
     lien doit cesser de se faire passer pour cliquable. */
  a { color: #000 !important; text-decoration: none !important; }
}

/* ── Ce qu'un filtre laisse voir ───────────────────────────────────────────
   La ligne qui suit la barre de filtres dit combien de dossiers sont montrés
   et sur combien. Elle existe parce qu'un tableau filtré et un tableau vide
   se ressemblaient trait pour trait : les dossiers paraissaient perdus là où
   un critère les masquait simplement. Elle doit donc se lire sans effort,
   mais ne pas peser plus que le tableau qu'elle annonce.               */
.resume-filtre {
  margin: -6px 0 10px;
  font-size: 12px;
  min-height: 1.4em;       /* la place est tenue : sans filtre, le tableau ne
                              remonte pas d'une ligne à chaque frappe */
}
.resume-filtre .btn { margin-left: 6px; vertical-align: baseline; }

/* ── Barres de défilement ──────────────────────────────────────────────────
   Discrètes, pour que les tableaux denses n'aient pas l'air encadrés de gris.
   Réglage purement cosmétique : le défilement reste celui du système.      */
.table-wrapper::-webkit-scrollbar,
.table-wrapper--scroll::-webkit-scrollbar,
.frise-cadre::-webkit-scrollbar { height: 9px; width: 9px; }
.table-wrapper::-webkit-scrollbar-thumb,
.table-wrapper--scroll::-webkit-scrollbar-thumb,
.frise-cadre::-webkit-scrollbar-thumb {
  background: var(--color-border); border-radius: 5px;
}
.table-wrapper::-webkit-scrollbar-thumb:hover,
.table-wrapper--scroll::-webkit-scrollbar-thumb:hover,
.frise-cadre::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-3);
}
.table-wrapper::-webkit-scrollbar-track,
.table-wrapper--scroll::-webkit-scrollbar-track,
.frise-cadre::-webkit-scrollbar-track { background: transparent; }

/* ── Numérotation des factures ────────────────────────────────────────────
   Le numéro s'affiche en chasse fixe : CPU2026-001 et CPU2026-0O1 doivent
   se distinguer à l'œil avant d'être confirmés.

   ── Réparation, 12/10/2026 ─────────────────────────────────────────────
   Ce bloc était tronqué : la fin de onze lignes avait disparu — le `/` qui
   fermait le commentaire ci-dessus, et les `{`, `;` et `}` des six règles
   qui suivent. Un commentaire non fermé fait avaler au navigateur TOUT ce
   qui vient après, jusqu'à la fin du fichier : les six règles ne
   s'appliquaient donc pas, et l'écran de numérotation des factures sortait
   sans encadré, sans chasse fixe et sans pastille de verrou.

   Rien n'est ajouté ni changé ici : seuls les caractères manquants sont
   remis. Les valeurs sont celles qui subsistaient sur les lignes.        */
.serie-facture {
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  padding: 14px 16px; margin: 12px 0; background: var(--color-surface);
}
.serie-facture-titre { font-weight: 600; margin-bottom: 6px; }
.numero-facture { font-family: var(--font-mono, monospace); letter-spacing: .02em; }
.numero-apercu { margin: 10px 0; padding: 8px 10px; border-radius: var(--radius);
  background: var(--color-bg); }
.verrou-facture { display: inline-block; padding: 2px 8px; border-radius: 10px;
  font-size: 12px; font-weight: 600; }
.verrou-facture--ouvert { background: #f0fdf4; color: var(--color-success); }
.verrou-facture--ferme  { background: #fef2f2; color: var(--color-danger); }

/* ══════════════════════════════════════════════════════════════════════════
   Suivi de prospection — les listes de travail et le tableau des affaires
   ══════════════════════════════════════════════════════════════════════════

   L'écran ouvrait sur six cartes de statistiques : un taux de réussite, un
   délai moyen, un compte de conquêtes. Des chiffres de trimestre, posés là où
   doit se trouver le travail du jour. Ils sont descendus en pied de page, et
   la place est rendue à cinq listes de travail dont chaque nombre est un
   filtre : on le clique, le tableau s'y réduit.

   Rien ici ne redéclare une variable de main.css, et aucune teinte ne porte
   seule : la pile choisie se reconnaît à son filet épaissi autant qu'à son
   fond, et l'état d'une affaire est écrit en toutes lettres sous le chiffre
   qui le colore.                                                           */

.piles-suivi {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-bottom: 16px;
}

/* Un bouton, et non une carte cliquable : le parcours au clavier doit
   l'atteindre, et un lecteur d'écran annoncer qu'il est enfoncé. */
.pile-suivi {
  flex: 1 1 160px; min-width: 150px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 13px; text-align: left; cursor: pointer;
  font-family: inherit;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border);
  border-radius: var(--radius);
}
.pile-suivi:hover { border-color: var(--color-text-3); }
.pile-suivi:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

.pile-suivi-nombre {
  font-size: 24px; font-weight: 700; line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}
.pile-suivi-libelle {
  font-size: 12.5px; font-weight: 600; color: var(--color-text-2);
}
.pile-suivi-note {
  font-size: 11px; line-height: 1.3; color: var(--color-text-3);
}

/* La pile ouverte. Le filet de gauche passe au turquoise ET s'épaissit : sur
   une impression en niveaux de gris, c'est l'épaisseur qui subsiste. */
.pile-suivi--active {
  background: var(--color-primary-fd);
  border-color: var(--color-primary);
  border-left-width: 5px;
  padding-left: 11px;
}
.pile-suivi--active .pile-suivi-nombre { color: var(--color-primary-h); }
.pile-suivi--active .pile-suivi-libelle { color: var(--color-primary-h); }

/* Une pile vide reste à sa place — savoir qu'aucune offre n'attend d'être
   adressée est une information — mais son chiffre cesse d'appeler l'œil. */
.pile-suivi--vide .pile-suivi-nombre {
  color: var(--color-text-3); font-weight: 600;
}

/* Barre repliée : deux piles par rang, et la cinquième reste à sa demi-largeur
   plutôt que de s'étaler sur toute la ligne — un chiffre seul en pleine
   largeur se lit comme un total. */
@media (max-width: 900px) {
  .pile-suivi { flex: 0 1 calc(50% - 5px); }
}

/* ── Le tableau des affaires ───────────────────────────────────────────────
   Deux lignes par cellule : la valeur, puis ce qui la qualifie. C'est ce qui
   permet de tenir sept colonnes sans rien abréger.                        */
.table-suivi td { padding: 9px 14px; }

/* Sept colonnes ne se compriment pas. En deçà, le cadre défile — ce que
   .table-wrapper sait déjà faire — plutôt que d'empiler trois mots par
   cellule et de rendre les lignes incomparables. */
.table-suivi { min-width: 940px; }
.table-suivi th.cellule-num, .table-suivi td.cellule-num { text-align: right; }
.ligne-affaire { cursor: pointer; }

.ligne-sous {
  display: block; margin-top: 2px;
  font-size: 11.5px; line-height: 1.3; color: var(--color-text-3);
}

/* La référence est le seul élément focalisable de la ligne : cliquer n'importe
   où ouvre la fiche à la souris, et la tabulation suit les références. */
/* Un bouton centre son texte : `text-align` le ramène au fil de la cellule
   quand un nom long passe sur deux lignes. */
.lien-affaire {
  padding: 0; background: none; border: none;
  font-family: inherit; font-size: inherit; font-weight: 600;
  font-variant-numeric: tabular-nums; text-align: start;
  color: var(--color-text); cursor: pointer;
}
.lien-affaire:hover {
  color: var(--color-primary-h); text-decoration: underline;
}
.lien-affaire:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
  border-radius: var(--radius);
}

@media print {
  /* Les piles s'impriment : elles disent ce qui attend un geste, et c'est la
     raison d'emporter cette feuille. Les boutons de la barre de filtres, eux,
     disparaissent avec les autres. */
  .pile-suivi {
    break-inside: avoid;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .lien-affaire { color: #000 !important; }
}
.com-dernier-envoi { white-space: nowrap; color: var(--text-secondary, #666); }

/* ── Prospection : l'état de chaque ligne ─────────────────────────────────
   Une teinte par état, posée en filet à gauche de la ligne et sur la
   pastille. La teinte ne porte jamais seule : la pastille dit l'état en
   toutes lettres et le précède d'une forme propre à chacun. Filets à 3:1
   au moins sur blanc, texte des pastilles à 4,5:1 au moins sur leur fond
   (contrôlés par scripts/verif-fiche-prospect.js). */
.etat-a-aborder         { --etat-bord: #64748b; --etat-fond: #f1f5f9; --etat-texte: #334155; }
.etat-approche          { --etat-bord: #0e7490; --etat-fond: #ecfeff; --etat-texte: #155e75; }
.etat-qualifie          { --etat-bord: #1d4ed8; --etat-fond: #eff6ff; --etat-texte: #1e40af; }
.etat-contrat-a-envoyer { --etat-bord: #6d28d9; --etat-fond: #f5f3ff; --etat-texte: #5b21b6; }
.etat-contrat-envoye    { --etat-bord: #b45309; --etat-fond: #fffbeb; --etat-texte: #92400e; }
.etat-signe             { --etat-bord: #15803d; --etat-fond: #f0fdf4; --etat-texte: #166534; }
.etat-clos              { --etat-bord: #6b7280; --etat-fond: #f3f4f6; --etat-texte: #374151; }
.etat-ecarte            { --etat-bord: #78716c; --etat-fond: #fafaf9; --etat-texte: #44403c; }

.ligne-etat > td:first-child { box-shadow: inset 5px 0 0 var(--etat-bord); padding-left: 14px; }
.ligne-etat.etat-clos > td { color: var(--color-text-2); }

.pastille-etat {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px 2px 7px; border-radius: 999px;
  border: 1px solid var(--etat-bord);
  background: var(--etat-fond); color: var(--etat-texte);
  font-size: 12px; font-weight: 600; line-height: 1.5; white-space: nowrap;
}
.pastille-etat-forme { font-size: 11px; line-height: 1; }

.legende-etats {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin: 0 0 12px; padding: 0; list-style: none;
}
.legende-etats li { display: inline-flex; align-items: center; gap: 6px; }
.legende-etats-note { font-size: 11.5px; color: var(--color-text-2); }

.table-prospects { min-width: 1040px; }
.table-prospects th, .table-prospects td { padding-left: 10px; padding-right: 10px; }
.table-prospects td { vertical-align: top; }
.table-prospects td:first-child { padding-left: 14px; }
.table-prospects td:nth-child(2) { min-width: 190px; }
.table-prospects td:last-child { width: 1%; }

.puce-charge {
  display: inline-block; min-width: 34px; padding: 3px 7px;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-surface); color: var(--color-text);
  font: inherit; font-size: 12.5px; font-weight: 700; letter-spacing: .04em;
  text-align: center; cursor: pointer;
}
.puce-charge:hover { border-color: var(--color-primary); }
.puce-charge--figee { cursor: default; color: var(--color-text-2); }
.puce-charge:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

.saisie-ligne { display: inline-flex; align-items: center; gap: 4px; }
.input-initiales { width: 64px; text-transform: uppercase; }
.input-date-ligne { width: 140px; }

.actions-ligne { display: flex; flex-wrap: nowrap; gap: 6px; }
.actions-ligne--fiche { display: block; margin: 8px 0 16px; }
.actions-ligne--fiche .actions-ligne { flex-wrap: wrap; }

.bandeau-migration { margin-bottom: 12px; }

/* ── La fiche prospect : la ligne d'avancement ─────────────────────────── */
.jalons-fiche {
  margin: 4px 0 14px; padding: 10px 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  background: var(--color-surface);
}
.jalons-entete { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.jalons-compte { font-size: 12.5px; color: var(--color-text-2); }
.jalons-prospect {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0; padding: 0; list-style: none; counter-reset: none;
}
.jalon {
  display: flex; align-items: flex-start; gap: 6px;
  flex: 1 1 140px; min-width: 130px; padding: 6px 8px;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-bg, #f8fafc);
}
.jalon--fait { border-color: #15803d; background: #f0fdf4; }
.jalon--fait .jalon-marque { color: #166534; }
.jalon--attente { border-style: dashed; }
.jalon--facultatif.jalon--attente { opacity: .85; }
.jalon-marque { font-weight: 700; font-size: 14px; line-height: 1.3; color: var(--color-text-2); }
.jalon-texte { display: flex; flex-direction: column; min-width: 0; }
.jalon-libelle { font-size: 12.5px; font-weight: 600; color: var(--color-text); }
.jalon-option { font-weight: 400; color: var(--color-text-2); }
.jalon-date { font-size: 11.5px; color: var(--color-text-2); }
.jalon-detail {
  font-size: 11px; color: var(--color-text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.suivi-entete { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.suivi-entete h3 { margin: 0; }
.suivi-saisies {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0 16px; align-items: start;
  padding: 10px 12px; border: 1px solid var(--color-border); border-radius: var(--radius);
}
.suivi-saisies .form-actions { grid-column: 1 / -1; margin-top: 0; }
.suivi-constat { margin: 6px 0 0; font-size: 13px; }
.suivi-fige { grid-column: 1 / -1; margin: 0; font-size: 12.5px; }
.table-dossier th { width: 200px; text-align: left; }
.table-journal td { vertical-align: top; }
.journal-champ { font-family: var(--font-mono, monospace); font-size: 12px; }
.approche-ajout { margin: 0 0 12px; }

@media (prefers-reduced-motion: reduce) {
  .puce-charge, .actions-ligne .btn, .jalon, .infobulle-action { transition: none; }
}

@media print {
  .ligne-etat > td:first-child, .pastille-etat, .jalon--fait {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .actions-ligne, .legende-etats-note, .suivi-saisies .form-actions { display: none; }
}

/* ── Prospection : les affaires écartées ─────────────────────────────────
   La pastille d'une affaire écartée est en tirets : l'écart se lit à la
   forme comme au mot, et pas seulement à une teinte proche de « clos ». */
.pastille-etat.etat-ecarte { border-style: dashed; }
.ligne-etat.etat-ecarte > td { color: var(--color-text-2); }
.actions-ligne--fiche .bouton-ecart { margin-left: 4px; }
.mot-reprise { font-weight: 600; color: #155e75; }
.bandeau-ecart { margin: 8px 0; }

/* ── Prospection : la colonne État sur deux lignes ───────────────────────
   L'étape, puis son rang : chaque morceau d'un seul tenant, pour que la
   coupure tombe entre eux et jamais au milieu de « étape 1 sur 5 ». */
.etat-etape-libelle, .etat-etape-rang { display: block; white-space: nowrap; }

/* ── Prospection : les actions à pictogramme ─────────────────────────────
   Carrés de 32 px, côte à côte et sans retour : chaque action garde sa place
   d'une ligne à l'autre. Le nom se lit dans l'infobulle, au survol comme au
   focus clavier. Sans objet, le bouton reste à sa place, en tirets et
   estompé ; l'infobulle en donne la raison. */
.bouton-icone {
  flex: 0 0 auto; justify-content: center;
  min-width: 32px; height: 32px; padding: 0 8px;
}
.bouton-icone .icone-action { flex: 0 0 auto; }
.bouton-icone[aria-disabled="true"] { border-style: dashed; cursor: not-allowed; }
.bouton-icone[aria-disabled="true"] > * { opacity: .5; }
.bouton-icone-libelle { white-space: nowrap; }
.actions-ligne--fiche .bouton-icone { height: auto; min-height: 32px; padding: 4px 10px; }

.infobulle-action {
  position: fixed; z-index: 2000; top: 0; left: 0;
  max-width: 260px; padding: 6px 10px;
  border-radius: var(--radius); background: #1e293b; color: #fff;
  font-size: 12px; line-height: 1.35; text-align: left;
  box-shadow: 0 4px 14px rgba(15, 23, 42, .25);
  pointer-events: none; opacity: 0; visibility: hidden;
  transition: opacity .12s ease;
}
.infobulle-action.visible { opacity: 1; visibility: visible; }
.infobulle-action strong { display: block; font-weight: 600; }
.infobulle-action span { display: block; margin-top: 2px; color: #cbd5e1; }
.infobulle-action::after {
  content: ""; position: absolute; left: var(--fleche, 50%); top: 100%;
  margin-left: -5px; border: 5px solid transparent; border-top-color: #1e293b;
}
.infobulle-action.dessous::after {
  top: auto; bottom: 100%; border-top-color: transparent; border-bottom-color: #1e293b;
}

/* ── Prospection : le cahier de bord ─────────────────────────────────────
   Sur la ligne du tableau, le dernier commentaire tient en deux lignes ; le
   texte entier est dans l'infobulle. */
.ligne-commentaire {
  max-width: 34em; margin-top: 4px; color: var(--color-text-2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
.ligne-commentaire-entete { font-weight: 600; color: var(--color-text-2); }

.jalon-cahier { margin-top: 3px; font-size: 11.5px; font-weight: 600; color: #155e75; }

.cahier {
  margin: 4px 0 16px; padding: 10px 12px;
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
}
.cahier h4 { margin: 0 0 2px; }
.cahier-aide { margin: 0 0 8px; font-size: 12.5px; }
.cahier-saisie {
  display: grid; grid-template-columns: minmax(150px, 220px) 1fr;
  gap: 0 12px; align-items: start;
}
.cahier-saisie .form-actions { grid-column: 1 / -1; margin-top: 0; }
.cahier-saisie textarea { resize: vertical; font: inherit; }
.cahier-liste { margin: 10px 0 0; padding: 0; list-style: none; }
.cahier-ligne { padding: 8px 0; border-top: 1px solid var(--color-border); }
.cahier-entete { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.cahier-jalon {
  padding: 1px 8px; border-radius: 999px; background: #ecfeff; color: #155e75;
  font-size: 12px; font-weight: 600;
}
.cahier-signature { font-size: 12px; color: var(--color-text-2); }
.cahier-gestes { margin-left: auto; display: inline-flex; gap: 4px; }
.cahier-texte { margin: 4px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }

@media (max-width: 640px) {
  .cahier-saisie { grid-template-columns: 1fr; }
}

@media print {
  .infobulle-action, .cahier-saisie, .cahier-gestes, .jalon-cahier { display: none; }
}

/* ── Prospection : l'alerte des réponses au mail de première approche ────
   En tête de l'onglet. Une ligne par réponse : qui, depuis quand, et les
   deux gestes. Le filet de gauche et le chiffre portent l'alerte ; le texte
   la dit en entier, sans dépendre de la teinte. */
.alerte-reponses {
  margin: 0 0 16px; padding: 14px 16px 10px;
  background: var(--color-surface);
  border: 1px solid #b7e6e1; border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 4px 14px rgba(15, 156, 145, .08);
}
.alerte-reponses-entete { display: flex; align-items: flex-start; gap: 12px; }
.alerte-reponses-signe {
  flex: 0 0 auto; min-width: 34px; height: 34px; padding: 0 8px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--color-primary); color: #fff;
  font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.alerte-reponses-titre { margin: 0; font-size: 15.5px; line-height: 1.3; }
.alerte-reponses-titre:focus { outline: none; }
.alerte-reponses-titre:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.alerte-reponses-aide { margin: 2px 0 0; font-size: 12.5px; color: var(--color-text-2); }

.alerte-reponses-liste { margin: 10px 0 0; padding: 0; list-style: none; }
.alerte-reponse {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) 150px 250px;
  align-items: center; gap: 4px 16px;
  padding: 9px 0; border-top: 1px solid var(--color-border);
}
.alerte-reponse-qui { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.alerte-reponse-nom { font-weight: 600; font-size: 14px; }
.alerte-reponse-detail {
  font-size: 12.5px; color: var(--color-text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alerte-reponse-anomalie { font-size: 12.5px; font-weight: 600; color: var(--color-danger); }
.alerte-reponse--anomalie::before {
  content: ""; position: absolute; left: -10px; top: 9px; bottom: 9px;
  width: 3px; border-radius: 2px; background: var(--color-danger);
}

.alerte-reponse-quand { display: flex; flex-direction: column; gap: 1px; font-size: 12px; }
.alerte-reponse-depuis { font-weight: 600; color: var(--color-primary-h); }
.alerte-reponse-quand time { color: var(--color-text-2); white-space: nowrap; }
.alerte-reponse-quand--vieille .alerte-reponse-depuis { color: var(--color-warning); }

.alerte-reponse-gestes { display: flex; gap: 6px; justify-content: flex-end; white-space: nowrap; }

.alerte-reponses-reste { border-top: 1px solid var(--color-border); }
.alerte-reponses-reste > summary {
  padding: 8px 0 2px; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--color-primary-h);
}
.alerte-reponses-reste > summary:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 4px;
}
.alerte-reponses-reste[open] > summary { padding-bottom: 0; }

@media (max-width: 760px) {
  .alerte-reponse { grid-template-columns: 1fr; }
  .alerte-reponse--anomalie::before { left: -8px; }
  .alerte-reponse-quand { flex-direction: row; gap: 8px; }
  .alerte-reponse-gestes { justify-content: flex-start; }
}

/* La pastille de l'onglet bat deux fois quand une réponse arrive. */
@media (prefers-reduced-motion: no-preference) {
  .nav-pastille--neuve { animation: pastille-arrivee 1.2s ease-out 2; }
}
@keyframes pastille-arrivee {
  0%   { box-shadow: 0 0 0 0 rgba(15, 156, 145, .55); }
  100% { box-shadow: 0 0 0 7px rgba(15, 156, 145, 0); }
}

@media print {
  .alerte-reponse-gestes { display: none; }
}

/* ── Courriels de la fiche prospect : échange et contrat pour relecture ── */
.mail-prospect .modal-panel { max-width: 860px; }
.mail-prospect-de {
  margin: 0 0 14px; padding: 9px 12px; border-radius: 8px;
  background: var(--color-primary-fd); color: var(--color-text-2, #3d4a57); font-size: 13px;
}
.mail-prospect-piece {
  margin: 0 0 16px; padding: 14px 16px; border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-primary); border-radius: 8px; background: #fff;
}
.mail-prospect-piece-titre { display: flex; gap: 12px; align-items: center; }
.mail-prospect-pdf {
  flex: none; width: 38px; height: 46px; border-radius: 5px; display: grid; place-items: center;
  background: #fdecec; color: #b42318; font: 700 11px/1 system-ui, sans-serif; letter-spacing: .04em;
}
.mail-prospect-relectures {
  margin: 12px 0 0; padding: 10px 12px; border-radius: 6px; background: #f6f8fa; font-size: 13px;
}
.mail-prospect-relectures ul { margin: 6px 0 0; padding-left: 18px; }
.mail-prospect-relectures li { margin: 2px 0; }
.mail-prospect-piece .form-aide { margin: 10px 0 0; }
.mail-prospect-table { margin-bottom: 8px; }
.mail-prospect-table .mp-col-case { width: 36px; }
.mail-prospect-table .mp-col-copie { width: 64px; text-align: center; }
.mail-prospect-table td:last-child { text-align: center; }
.mail-prospect-ajout {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) auto; gap: 8px;
  align-items: center; margin: 0 0 18px;
}
.mail-prospect-zone { min-height: 220px; line-height: 1.55; font-family: inherit; resize: vertical; }
.mail-prospect-cadre {
  width: 100%; height: 600px; border: 1px solid var(--color-border); border-radius: 8px; background: #f6f6f6;
}
@media (max-width: 760px) {
  .mail-prospect-ajout { grid-template-columns: 1fr; }
}

/* ── Déclarations du centre, dans le suivi commercial de la fiche ─────────── */
.declarations { margin: 20px 0 4px; }
.declarations h4 { display: flex; align-items: center; gap: 8px; }
.declarations-compte {
  min-width: 20px; padding: 0 6px; border-radius: 999px; background: var(--color-primary-fd);
  color: var(--color-primary-h); font-size: 12px; font-weight: 700; line-height: 20px; text-align: center;
}
.declarations-liste {
  list-style: none; margin: 0; padding: 0; border: 1px solid var(--color-border);
  border-radius: 8px; background: var(--color-surface);
}
.declaration {
  display: grid; grid-template-columns: 170px minmax(0, 1fr) auto; align-items: center;
  gap: 4px 16px; padding: 10px 14px;
}
.declaration + .declaration { border-top: 1px solid var(--color-border); }
.declaration-tete { display: flex; flex-direction: column; gap: 2px; font-size: 13px; font-variant-numeric: tabular-nums; }
.declaration-recente {
  align-self: flex-start; padding: 0 7px; border-radius: 999px; background: #ecfeff; color: #155e75;
  font-size: 11px; font-weight: 600; line-height: 18px;
}
.declaration-corps { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.declaration-quoi { font-weight: 600; font-size: 14px; }
.declaration-qui, .declaration-etat { font-size: 12px; color: var(--color-text-2); overflow-wrap: anywhere; }
.declaration-etat--attente { color: var(--color-warning); font-weight: 600; }
@media (max-width: 760px) {
  .declaration { grid-template-columns: minmax(0, 1fr) auto; }
  .declaration-tete { grid-column: 1 / -1; flex-direction: row; align-items: center; gap: 8px; }
}
@media print {
  .declaration-relire { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LA FICHE DE PROSPECTION : DESSIN ET ERGONOMIE
   ═══════════════════════════════════════════════════════════════════════════

   Tout ce qui suit habille la grande modale de la fiche d'établissement —
   coiffe, frise des jalons, barre de rubriques, volet « Suivi commercial ».
   Rien n'y est retiré de l'écran : ce sont des règles de forme, et les seuls
   ajouts de balisage sont des conteneurs, des compteurs et des mentions.

   ── Pourquoi tout est préfixé « .fiche-dessin » ─────────────────────────
   La balise <style> d'index.html est déclarée APRÈS les feuilles liées :
   à poids égal, elle gagne. `.fiche-dessin`, posée sur #client-body, donne
   le point de spécificité qui manque pour reprendre la main sans toucher
   une ligne de cette balise ni de main.css.

   ── Les encarts d'ESSAI ne sont pas concernés ───────────────────────────
   Le panneau sombre de la frise des étapes d'essai, les écrans de pilotage
   et de planning sont validés : aucun sélecteur d'ici ne les atteint.       */

:root {
  /* Le turquoise de la maison, assombri juste assez pour que du texte blanc
     dessus ET lui-même sur --color-primary-fd passent 4,5:1. --color-primary
     (#0f9c91) portait du blanc à 3,4:1 seulement, et --color-primary-h sur
     son propre fond pâle tombait à 4,45:1 — sous la barre, de peu, mais
     sous la barre. Mesuré par scripts/verif-ergonomie-fiche.js.            */
  --fiche-accent: #0a6a62;
}

/* ── La modale : la croix, et le titre qui ne défile pas ─────────────────
   Le titre et la croix sont dans .modal-header, hors du cadre défilant
   (.modal-body porte overflow-y) : ils restent donc visibles tout du long,
   et il n'y a rien à rendre collant pour cela. Ce qui manquait à la croix
   était une cible digne du nom, un nom accessible, et un anneau de focus. */
.modal-panel .modal-close {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; min-width: 32px; min-height: 32px;
  border-radius: var(--radius); line-height: 1;
  color: var(--color-text-2);
}
.modal-panel .modal-close:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
.modal-panel--xl .modal-header h3 { min-width: 0; overflow-wrap: anywhere; }

/* ── Le contraste, dans toute la fiche ──────────────────────────────────
   Mesuré sur le rendu par scripts/verif-ergonomie-fiche.js, volet par volet.
   Quatre teintes de la maison passaient sous 4,5:1 sur du texte qu'on lit
   vraiment, et non sur des ornements :

     --color-text-3 (#8494a5)  3,1:1 sur blanc, 2,9:1 sur le gris des
                               en-têtes de tableau — il porte .text-muted,
                               .form-aide, les <th> et les sous-lignes ;
     --color-primary (#0f9c91) 3,4:1 sous du blanc, sur tous les boutons
                               « Enregistrer » et les crans d'avancement ;
     --color-warning (#b76b05) 4,1:1 sur blanc, sur « À prendre en compte » ;
     le vert de .badge-success 4,4:1 sur son propre fond pâle.

   Elles sont relevées ICI et non dans main.css, qui ne se réécrit pas, ni
   globalement : repeindre tout le CRM n'était pas le chantier. La bonne
   réparation est de monter ces variables dans la palette de la maison —
   c'est dit dans le rapport, ce n'est pas fait ici.                        */
.fiche-dessin {
  --color-text-3: #5c6b7c;   /* 5,4:1 sur blanc · 5,0:1 sur #f4f6f8 */
}
.fiche-dessin .btn-primary {
  background: var(--fiche-accent); border-color: var(--fiche-accent);
}
.fiche-dessin .btn-primary:hover { background: #085851; border-color: #085851; }
.fiche-dessin .declaration-etat--attente { color: #8a5204; }
.fiche-dessin .badge-success { color: #0f6b47; }
.fiche-dessin .badge-warning { color: #7d4a04; }

/* Les ancres de défilement se posent sous la barre de rubriques collante. */
.fiche-dessin { scroll-padding-top: 58px; }

/* ── La coiffe : trois faits, dans un panneau et non en l'air ────────────
   État commercial, mode de règlement, engagement tarifaire : ils flottaient
   au-dessus de la barre d'onglets sans cadre, et l'œil ne savait pas s'ils
   appartenaient au titre ou à la suite. Même panneau que le reste.         */
.fiche-dessin .fiche-coiffe {
  display: flex; flex-wrap: wrap; gap: 8px 30px;
  margin: 0 0 10px; padding: 9px 15px 10px;
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  background: var(--color-surface);
}
.fiche-dessin .fiche-coiffe .form-field { min-width: 190px; }
.fiche-dessin .fiche-coiffe .form-field > span:first-child {
  display: block; font-size: 10.5px; font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--color-text-2);
}
/* Le retrait de 6 px est posé en style d'attribut par public/js/clients.js,
   sur trois champs. `!important` est le seul moyen de le resserrer sans
   réécrire trois gabarits pour trois pixels. */
.fiche-dessin .fiche-coiffe .form-field > div { padding-top: 2px !important; }

/* ── La barre des rubriques : dix entrées ────────────────────────────────
   Dix entrées s'enroulaient sur deux rangs dès 1024 px, et l'onglet actif se
   perdait dans le tas. Un seul rang qui défile, l'actif marqué par le filet
   ET par le poids du trait, et la barre reste au bord haut du cadre
   défilant : on sait toujours quelle rubrique on lit.

   Les flèches ← → naviguent (public/js/clients.js) ; la tabulation continue
   d'atteindre chaque onglet, aucun n'est retiré du parcours.               */
/* Le retrait haut et le `top` négatif ne sont pas décoratifs. Le bloc collant
   se cale sur la boîte de CONTENU du cadre défilant, c'est-à-dire 20 px sous
   son bord visible : à `top: 0`, une ligne de texte défilait au-dessus de la
   barre dans cette bande de remplissage. Le `top: -20px` remonte la barre
   jusqu'au bord, et ses 20 px de remplissage haut remettent les onglets là
   où ils étaient. La marge basse de la frise paie ces 20 px. */
.fiche-dessin .sous-onglets-cadre {
  position: sticky; top: -20px; z-index: 5;
  margin: 0 -20px 16px; padding: 20px 20px 0;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  box-shadow: 0 7px 9px -9px rgba(15, 23, 42, .5);
}
.fiche-dessin .sous-onglets--fiche {
  flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
  margin: 0; border-bottom: 0; scrollbar-width: thin;
}
.fiche-dessin .sous-onglets--fiche .sous-onglet {
  flex: 0 0 auto; margin-bottom: 0; padding: 9px 13px;
  border-bottom: 2px solid transparent; border-radius: var(--radius) var(--radius) 0 0;
}
.fiche-dessin .sous-onglets--fiche .sous-onglet.actif {
  color: var(--fiche-accent); border-bottom-color: var(--fiche-accent);
}
.fiche-dessin .sous-onglets--fiche .sous-onglet:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: -2px;
}

/* ── La frise des jalons : une piste, et non huit cartouches ─────────────
   Huit cartouches à deux ou trois rangs prenaient près de 200 px avant
   qu'on ait lu une ligne de la fiche. Les huit mêmes jalons tiennent sur un
   rang : un repère posé sur un filet, et dessous exactement ce qui s'y
   trouvait — libellé, « (facultatif) », date, provenance, détail, « À dater »,
   bouton du cahier.

   L'entête dit en plus l'avancement d'un coup d'œil. La teinte ne porte
   jamais seule : ✓ / ○ pour l'état, le mot « prochain jalon » pour l'attente,
   et aria-current="step" pour le lecteur d'écran.                          */
.fiche-dessin .jalons-fiche { margin: 0; padding: 9px 14px 10px; }
.fiche-dessin .jalons-entete {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 5px 12px; margin-bottom: 2px;
}
.fiche-dessin .jalons-compte { font-variant-numeric: tabular-nums; }
.jalons-jauge {
  flex: 0 1 170px; height: 6px; border-radius: 999px;
  background: var(--color-border); overflow: hidden;
}
.jalons-jauge-part {
  display: block; height: 100%; border-radius: 999px;
  background: var(--fiche-accent);
}
.jalons-prochain { font-size: 12.5px; color: var(--color-text-2); }
.jalons-prochain strong { color: var(--color-text); font-weight: 600; }
.jalons-ecrits {
  font-size: 12px; color: var(--color-text-2);
  font-variant-numeric: tabular-nums;
}
.jalons-bascule { margin-left: auto; font-size: 12px; font-weight: 600; }

.fiche-dessin .jalons-prospect {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: minmax(138px, 1fr);
  gap: 0; margin: 0; padding: 7px 0 0;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
}
.fiche-dessin .jalon {
  display: block; position: relative; flex: none; min-width: 0;
  padding: 21px 8px 0; border: 0; border-radius: 0; background: none;
  scroll-snap-align: start;
}
.jalon-filet {
  position: absolute; top: 9px; left: 0; right: 0; height: 2px;
  background: var(--color-border);
}
.fiche-dessin .jalon:first-child .jalon-filet { left: 50%; }
.fiche-dessin .jalon:last-child .jalon-filet { right: 50%; }
.fiche-dessin .jalon--fait .jalon-filet { background: var(--color-success); }
.fiche-dessin .jalon-marque {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--color-border); background: var(--color-surface);
  font-size: 11px; line-height: 1; color: var(--color-text-2);
}
.fiche-dessin .jalon--fait .jalon-marque {
  border-color: var(--color-success); background: #f0fdf4; color: #166534;
}
.fiche-dessin .jalon--attente .jalon-marque { border-style: dashed; }
.fiche-dessin .jalon--prochain .jalon-marque {
  border-style: solid; border-color: var(--fiche-accent);
  box-shadow: 0 0 0 3px var(--color-primary-fd);
}
.fiche-dessin .jalon-texte {
  align-items: center; text-align: center; gap: 0;
}
.fiche-dessin .jalon-libelle { font-size: 11.5px; line-height: 1.2; }
.fiche-dessin .jalon--prochain .jalon-libelle { font-weight: 700; }
.fiche-dessin .jalon-option { font-size: 10.5px; }
.fiche-dessin .jalon-date {
  font-size: 10.5px; line-height: 1.25; font-variant-numeric: tabular-nums;
}
/* Le détail tient sur deux lignes au lieu d'être coupé net à la première ;
   son infobulle `title` rend le texte entier dans les deux cas.            */
.fiche-dessin .jalon-detail {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  white-space: normal; text-overflow: clip;
  font-size: 10.5px; line-height: 1.25;
}
.fiche-dessin .jalon-cahier { margin-top: 3px; font-size: 11px; }
.fiche-dessin .jalon-cahier--garni { text-decoration: underline dotted; }
.fiche-dessin .jalon--facultatif.jalon--attente { opacity: 1; }
.fiche-dessin .jalon-dater:focus-visible,
.fiche-dessin .jalon-cahier:focus-visible,
.jalons-bascule:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
  border-radius: var(--radius);
}

/* Repliée, la piste laisse l'entête : le compte, la jauge, le prochain jalon
   et le nombre d'écrits restent sous les yeux, et le bouton dit « Déplier ».
   Rien n'est perdu, et sur papier la piste ressort de toute façon.         */
.jalons-fiche--pliee .jalons-prospect { display: none; }
.jalons-fiche--pliee .jalons-entete { margin-bottom: 0; }

/* ── Quatre blocs, une seule grammaire ──────────────────────────────────
   L'en-tête d'affaire, les gestes, le cahier, les saisies et l'avancement se
   suivaient avec quatre dessins différents : bordé, nu, bordé, nu. Un seul
   panneau, un seul titre, une seule phrase d'aide, un seul rythme.         */
.fiche-dessin .suivi-entete {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  margin: 0 0 12px; padding: 0 0 8px;
  border-bottom: 2px solid var(--color-border);
}
.fiche-dessin .suivi-entete h3 { font-size: 17px; letter-spacing: -.01em; }

/* ── Des blocs à plat, et non des cartes ────────────────────────────────
   Un panneau par bloc avait été essayé : la grammaire devenait bien unique,
   mais les quatre cadres ajoutaient à eux seuls une centaine de pixels de
   hauteur, et le volet s'allongeait de ce que la frise venait de rendre.
   Or la densité verticale était la première plainte. L'unité se fait donc
   par le titre, le filet et le rythme — pas par la boîte : un filet de
   séparation, un titre identique, un intervalle identique. Le seul cadre
   gardé est celui de la saisie du cahier, qu'il faut justement désigner. */
.fiche-dessin .bloc-suivi {
  margin: 0 0 10px; padding: 0 0 10px;
  border-bottom: 1px solid var(--color-border);
}
.fiche-dessin .bloc-suivi:last-of-type { border-bottom: 0; }
.fiche-dessin .bloc-titre,
.fiche-dessin .declarations h4 {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 2px; font-size: 13.5px; font-weight: 600;
  letter-spacing: 0; text-transform: none; color: var(--color-text);
}
.fiche-dessin .bloc-titre::before,
.fiche-dessin .declarations h4::before {
  content: ""; flex: 0 0 auto; width: 3px; height: 14px;
  border-radius: 2px; background: var(--fiche-accent);
}
/* Les deux titres qui coiffent un tableau, lequel porte déjà son propre
   cadre : ils n'ont pas de panneau à eux, seulement le même filet.         */
.fiche-dessin .bloc-titre--nu { margin: 18px 0 8px; }
.fiche-dessin .bloc-compte,
.fiche-dessin .declarations-compte {
  min-width: 20px; padding: 0 7px; border-radius: 999px;
  background: #ecfeff; color: #155e75;
  font-size: 11.5px; font-weight: 700; line-height: 19px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.fiche-dessin .bloc-aide {
  margin: 0 0 7px; font-size: 12px; line-height: 1.4;
  color: var(--color-text-2);
}
.fiche-dessin .bloc-boutons { display: flex; flex-wrap: wrap; gap: 8px; }

/* ── Les gestes de l'affaire : lequel est à faire ────────────────────────
   Sept boutons du même poids ne disaient pas lequel était le geste du
   moment, et un bouton gris ne disait pas POURQUOI il l'était sans qu'on
   aille le survoler. Celui que l'avancement réclame porte la teinte pleine
   et le mot « à faire » ; les six autres gardent leur place et leur ordre.
   Un geste sans objet dit sa raison sous son nom, en clair.                */
.fiche-dessin .actions-ligne--fiche { margin: 0; }
.fiche-dessin .actions-ligne--fiche .actions-ligne {
  flex-wrap: wrap; gap: 8px; align-items: stretch;
}
.fiche-dessin .actions-ligne--fiche .bouton-icone {
  display: grid; grid-template-columns: 16px minmax(0, 1fr);
  gap: 1px 9px; align-items: start; justify-items: start;
  height: auto; min-height: 34px; max-width: 262px;
  padding: 7px 11px; white-space: normal; text-align: left;
}
.fiche-dessin .actions-ligne--fiche .bouton-icone .icone-action {
  grid-row: 1; grid-column: 1; margin-top: 2px;
}
.fiche-dessin .actions-ligne--fiche .bouton-icone-libelle {
  grid-column: 2; white-space: normal; font-weight: 600; line-height: 1.3;
}
/* La raison tient sur une ligne : sa version entière reste dans l'infobulle
   et dans le nom accessible du bouton, de sorte que rien n'est perdu même
   si la largeur vient à la couper. */
.fiche-dessin .actions-ligne--fiche .bouton-icone-raison {
  grid-column: 2; max-width: 100%; font-size: 11.5px; font-weight: 400;
  line-height: 1.3; color: var(--color-text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fiche-dessin .actions-ligne--fiche .bouton-icone-marque {
  grid-column: 2; font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase;
}
.fiche-dessin .bouton-icone--geste {
  background: var(--fiche-accent); border-color: var(--fiche-accent);
  color: #fff;
}
.fiche-dessin .bouton-icone--geste:hover {
  background: #085851; border-color: #085851;
}
/* Un geste sans objet reste lisible : le `opacity: .5` de la ligne du
   tableau rabattait sa raison à 3:1, sous la barre AA. Ici il est remplacé
   par une teinte sourde pleine et le trait en tirets, qui disent la même
   chose sans effacer le texte.                                             */
.fiche-dessin .bouton-icone[aria-disabled="true"] {
  background: var(--color-bg); color: var(--color-text-2);
}
.fiche-dessin .bouton-icone[aria-disabled="true"] > * { opacity: 1; }
.fiche-dessin .bouton-icone:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
.fiche-dessin .actions-ligne--fiche .bouton-ecart { margin-left: auto; }

/* ── Le cahier de bord : la saisie saute aux yeux ────────────────────────
   C'est là que s'écrit où en est chaque négociation. Le champ est donc posé
   sur un fond qui le désigne, haut de trois lignes, et son bouton ne se
   cherche pas.                                                             */
.fiche-dessin .cahier { margin: 0 0 10px; padding: 0 0 10px; }
.fiche-dessin .cahier-aide { margin: 0 0 7px; }
.fiche-dessin .cahier-saisie {
  grid-template-columns: minmax(150px, 210px) minmax(0, 1fr);
  gap: 0 14px; margin: 0 0 4px; padding: 10px;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-bg);
}
.fiche-dessin .cahier-saisie textarea {
  min-height: 70px; background: var(--color-surface); line-height: 1.5;
}
/* La limite de longueur partage la ligne du bouton : seule, elle coûtait
   une ligne de plus sans rien dire de plus. */
.fiche-dessin .cahier-saisie-pied {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 6px 14px; margin-top: 7px;
}
.fiche-dessin .cahier-liste { margin-top: 10px; }
.fiche-dessin .cahier-ligne { padding: 8px 0; }
.fiche-dessin .cahier-ligne:first-child { border-top: 0; padding-top: 4px; }
.fiche-dessin .cahier-texte { line-height: 1.5; }

/* ── Ce que le CRM ne sait pas seul ─────────────────────────────────────
   Le cadre est désormais celui du bloc : le formulaire n'a plus besoin du
   sien, qui faisait un cadre dans un cadre.                                */
.fiche-dessin .suivi-saisies { padding: 0; border: 0; gap: 0 18px; }
.fiche-dessin .suivi-saisies .form-group { margin-bottom: 0; }
/* Les trois intitulés se posent au-dessus de leur champ. « Chargé
   d'affaires » se rangeait à gauche du sien, parce que son champ d'initiales
   est court : les trois saisies ne partageaient alors aucune ligne de base. */
.fiche-dessin .suivi-saisies .form-group > label { display: block; }
.fiche-dessin .suivi-saisies .input-initiales { width: 5.5em; }
/* Le bouton prend la quatrième colonne au lieu d'une ligne à lui seul :
   il s'aligne sur le bas des champs, et le bloc perd 38 px de vide. */
.fiche-dessin .suivi-saisies .form-actions {
  grid-column: auto; margin: 0; align-self: end; justify-content: flex-start;
}
.fiche-dessin .suivi-fige { margin-top: 8px; }

/* ── « Le dossier » : des libellés qu'on lit ─────────────────────────────
   Les libellés étaient en petites capitales gris clair : #8494a5 sur le gris
   de l'en-tête de tableau ne donne que 2,9:1, sous la barre AA, et les
   capitales ralentissent la lecture d'un mot comme « INSTALLATIONS VISÉES ».
   Casse normale, teinte montée à 6,4:1, et de la place pour la valeur.     */
.fiche-dessin .table-dossier { margin: 0 0 10px; }
.fiche-dessin .table-dossier th {
  width: 210px; text-align: left; vertical-align: top;
  padding: 7px 12px; font-size: 12.5px; font-weight: 600;
  text-transform: none; letter-spacing: 0;
  color: var(--color-text-2); background: var(--color-bg);
}
.fiche-dessin .table-dossier td {
  padding: 7px 12px; font-size: 13px; color: var(--color-text);
  overflow-wrap: anywhere;
}

/* ── Les contrats de l'affaire, et les affaires précédentes ──────────────
   L'état du contrat devient un jeton : « brouillon » perdu au fil d'une
   cellule se lisait comme une donnée de plus. Le tableau garde ses six
   colonnes, ses `scope="col"` et son prix à droite.                        */
.fiche-dessin .table-contrats-affaire { margin: 0 0 4px; }
.fiche-dessin .table-contrats-affaire .cellule-ref { font-weight: 600; }
.fiche-dessin .table-contrats-affaire td.cellule-num,
.fiche-dessin .table-contrats-affaire th.cellule-num { text-align: right; }
.jeton-statut {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: #ecfeff; color: #155e75;
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
}

.fiche-dessin .declarations { margin: 12px 0 10px; }
.fiche-dessin .declarations-liste { margin-top: 8px; }

.fiche-dessin .suivi-autres {
  margin: 14px 0 2px; padding: 11px 15px;
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  background: var(--color-surface);
}
.fiche-dessin .suivi-autres summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--color-text);
}
.fiche-dessin .suivi-autres summary:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
  border-radius: var(--radius);
}
.fiche-dessin .suivi-autres ul {
  margin: 9px 0 0; padding-left: 18px;
  font-size: 13px; color: var(--color-text-2);
}
.fiche-dessin .suivi-autres li { margin: 3px 0; }

/* ── L'écran du portable ────────────────────────────────────────────────
   La fiche devenait un ruban de plus de deux mille pixels. La piste des
   jalons défile au doigt sur un rang au lieu d'empiler huit cartouches, les
   gestes prennent toute la largeur, et « Le dossier » resserre ses
   libellés — en restant un tableau, pour garder ses en-têtes de ligne.     */
@media (max-width: 760px) {
  /* Des colonnes plus larges font MOINS haut : un libellé de quatre mots
     tient sur deux lignes à 152 px et sur quatre à 120 px. */
  .fiche-dessin .jalons-prospect { grid-auto-columns: minmax(152px, 152px); }
  .fiche-dessin .jalons-entete { gap: 3px 10px; }
  .jalons-jauge { flex: 1 1 56px; }
  .jalons-prochain, .jalons-ecrits { font-size: 11.5px; }
  .jalons-bascule { margin-left: 0; }
  /* Un libellé, un intitulé et une zone de texte sur trois colonnes de
     130 px ne laissent la place à aucun des trois. */
  .fiche-dessin .cahier-saisie { grid-template-columns: minmax(0, 1fr); }
  .fiche-dessin .suivi-saisies { grid-template-columns: minmax(0, 1fr); }
  .fiche-dessin .cahier-saisie textarea { min-height: 62px; }
  /* Chaque geste prend la largeur du pouce. Son nom et sa raison restent
     écrits : c'est précisément sur un petit écran qu'on n'a pas de survol
     pour aller les chercher. Le creux, lui, se resserre.                   */
  .fiche-dessin .actions-ligne--fiche .bouton-icone {
    max-width: none; width: 100%; min-height: 0; padding: 6px 10px;
  }
  .fiche-dessin .actions-ligne--fiche .actions-ligne { gap: 6px; }
  .fiche-dessin .actions-ligne--fiche .bouton-ecart { margin-left: 0; }
  .fiche-dessin .bloc-suivi, .fiche-dessin .cahier { margin-bottom: 10px; padding-bottom: 10px; }
  .fiche-dessin .cahier-ligne { padding: 7px 0; }
  .fiche-dessin .suivi-autres { padding: 9px 12px; }
  .fiche-dessin .table-dossier th { width: 42%; padding: 8px 10px; }
  .fiche-dessin .table-dossier td { padding: 8px 10px; }
  .fiche-dessin .fiche-coiffe { gap: 8px 20px; }
  .fiche-dessin .sous-onglets-cadre {
    top: -14px; margin: 0 -14px 14px; padding: 14px 14px 0;
  }
}

/* Pas de bloc « prefers-reduced-motion » ici : la maison en porte déjà un,
   plus haut dans cette même feuille, qui coupe animations et transitions sur
   `*, *::before, *::after` en `!important`. Un bloc de plus pour les pièces
   neuves a été écrit puis retiré — mesuré sur le rendu, il n'avait aucun
   effet, la règle générale gagnant de toute façon. La suite de contrôle
   vérifie donc la règle générale, et non une redite inutile.               */

/* Sur le papier, tout sort : la piste même repliée, les rubriques même
   fermées. La barre collante redevient immobile, et les raisons des gestes
   s'effacent avec les gestes eux-mêmes, que .actions-ligne masque déjà.    */
@media print {
  .fiche-dessin .sous-onglets-cadre { position: static; box-shadow: none; }
  .fiche-dessin .jalons-fiche--pliee .jalons-prospect { display: grid; }
  .fiche-dessin .jalons-prospect { overflow: visible; }
  .fiche-dessin .jalons-bascule { display: none; }
  .fiche-dessin .suivi-autres > ul { display: block; }
  .fiche-dessin .jalon--fait .jalon-marque,
  .fiche-dessin .jalon--fait .jalon-filet,
  .fiche-dessin .jalons-jauge-part,
  .fiche-dessin .bloc-compte,
  .jeton-statut {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
}

/* ══ RELIEF — 16/10/2026 ═══════════════════════════════════════════════════
   « tout est blanc sur blanc ». Le fond de page et les cartes étaient à deux
   doigts l'un de l'autre et les filets invisibles. Le fond et la bordure ont
   été descendus dans main.css ; ici on donne de l'ombre aux surfaces et une
   bande aux en-têtes de tableau. Mêmes couleurs, même charte : du relief. */
.stat-card, .form-section, .client-card, .bloc-repliable, .table,
.section, .encart, .modal-panel, .panneau, .carte {
  box-shadow: 0 1px 2px rgba(16, 32, 48, .06), 0 2px 8px rgba(16, 32, 48, .05);
}
.modal-panel { box-shadow: 0 18px 48px rgba(11, 23, 36, .32); }

.table thead th {
  background: #eef2f7;
  border-bottom: 2px solid var(--color-border);
}
.table tbody tr + tr { border-top: 1px solid #e3e9f0; }
.table tbody tr:hover { background: #f3f7fb; }

.barre-nav { box-shadow: 0 2px 6px rgba(16, 32, 48, .07); }
.stat-card:hover, .client-card:hover {
  box-shadow: 0 2px 4px rgba(16, 32, 48, .09), 0 6px 16px rgba(16, 32, 48, .09);
}

/* ══ BANDEAUX ET FILETS AUX COULEURS DE LISA LAB — 16/10/2026 ══════════════
   Demande du propriétaire : les séparations horizontales plus marquées, plus
   épaisses, en dégradé aux couleurs de la page de connexion, et les bandeaux
   de titre des onglets et des fiches de même. L''ardoise et le turquoise sont
   repris tels quels de connexion.css ; rien n''est inventé. */
:root {
  --filet-lisa: linear-gradient(90deg, #0f9c91 0%, #2de0ce 22%, #4f93f0 62%, rgba(79,147,240,0) 100%);
  --bandeau-lisa: linear-gradient(100deg, #0b1724 0%, #16293f 58%, #1d3550 100%);
}

/* Les titres de section et de fiche deviennent de vrais bandeaux. */
:is(.section, .form-section, .bloc-repliable, .panneau) > :is(h3, .section-titre):first-child,
.suivi-entete, .fiche-dessin .bloc-titre, .modal-header, .modal-panel > header {
  background: var(--bandeau-lisa);
  color: #fff;
  margin: -1px -1px 14px;
  padding: 11px 16px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-bottom: 3px solid transparent;
  border-image: var(--filet-lisa) 1;
  box-shadow: inset 0 -1px 0 rgba(255,255,255,.08);
}
:is(.suivi-entete, .modal-header) :is(h3, h4, .text-secondary, span) { color: #fff; }
.suivi-entete .text-secondary, .modal-header .text-secondary { color: #b9cbdd; }

/* Les sous-titres gardent leur encre, mais prennent le filet. */
:is(.section, .form-section, .fiche-dessin, .suivi-prospect) h4 {
  padding-bottom: 6px; margin-bottom: 10px;
  border-bottom: 3px solid transparent;
  border-image: var(--filet-lisa) 1;
}

/* Séparations horizontales : épaisses et dégradées, plus des filets gris. */
hr, .separateur {
  height: 3px; border: 0; margin: 18px 0;
  background: var(--filet-lisa);
}
.table thead th {
  border-bottom: 3px solid transparent;
  border-image: var(--filet-lisa) 1;
}
.barre-nav { border-bottom: 3px solid transparent; border-image: var(--filet-lisa) 1; }
.sous-onglets, .volets-fiche, .onglets-fiche {
  border-bottom: 3px solid transparent; border-image: var(--filet-lisa) 1;
}

/* ══ PLUS DE TURQUOISE — 16/10/2026 ════════════════════════════════════════
   « ça manque de turquoise, je trouve ça très bleu foncé ». Le bandeau reprend
   maintenant la composition exacte de l''en-tête de l''espace client : le halo
   radial ardoise clair, le dégradé de nuit à 150°, et le liseré turquoise en
   pied. Les séparations de section, elles, s''allègent : un filet fin et clair
   au lieu du dégradé épais, qui restait réservé aux bandeaux. */
:is(.section, .form-section, .bloc-repliable, .panneau) > :is(h3, .section-titre):first-child,
.suivi-entete, .fiche-dessin .bloc-titre, .modal-header, .modal-panel > header {
  background:
    radial-gradient(900px 420px at 12% -40%, #1d3550 0%, transparent 60%),
    linear-gradient(150deg, #0b1724 0%, #102033 58%, #16293f 100%);
  border-bottom: 2px solid rgba(45, 224, 206, .45);
  border-image: none;
  box-shadow: inset 0 -1px 0 rgba(45, 224, 206, .18);
}

/* Le repère turquoise de l''espace client, repris tel quel : un bâtonnet
   dégradé devant chaque titre. C''est lui qui apporte la couleur. */
:is(.section, .form-section, .bloc-repliable, .panneau) > :is(h3, .section-titre):first-child::before,
.suivi-entete::before, .fiche-dessin .bloc-titre::before, .modal-header::before {
  content: ''; flex: 0 0 auto; display: inline-block; vertical-align: middle;
  width: 4px; height: 18px; margin-right: 10px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}
.suivi-entete, .fiche-dessin .bloc-titre, .modal-header { display: flex; align-items: center; gap: 0; flex-wrap: wrap; }

/* Les sous-titres et les séparations : léger, pas de dégradé épais. */
:is(.section, .form-section, .fiche-dessin, .suivi-prospect) h4 {
  border-bottom: 1px solid #cfd9e4;
  border-image: none;
  box-shadow: 0 1px 0 rgba(45, 224, 206, .35);
}
hr, .separateur {
  height: 1px; background: #cfd9e4;
  box-shadow: 0 1px 0 rgba(45, 224, 206, .30);
  margin: 16px 0;
}
.table thead th {
  border-bottom: 2px solid transparent;
  border-image: linear-gradient(90deg, #12a89b 0%, #2de0ce 30%, #4f93f0 75%, rgba(79,147,240,0) 100%) 1;
}
.barre-nav, .sous-onglets, .volets-fiche, .onglets-fiche {
  border-bottom: 2px solid transparent;
  border-image: linear-gradient(90deg, #12a89b 0%, #2de0ce 30%, #4f93f0 75%, rgba(79,147,240,0) 100%) 1;
}

/* ══ CORRECTIF DE PRIORITÉ — 16/10/2026 ════════════════════════════════════
   Les bandeaux ne sortaient pas, pour deux raisons : index.html porte un bloc
   <style> APRÈS le lien vers cette feuille, donc ses règles gagnaient à égalité
   de spécificité ; et le sélecteur exigeait un h3 en PREMIER enfant, alors
   qu''un div de message le précède dans le volet de suivi. Spécificité montée
   et first-child retiré. */
body .modal-panel > .modal-header,
body .section > h3, body .form-section > h3, body .bloc-repliable > h3,
body .panneau > h3, body .section > .section-titre,
body .suivi-entete, body .fiche-dessin .bloc-titre {
  background:
    radial-gradient(900px 420px at 12% -40%, #1d3550 0%, transparent 60%),
    linear-gradient(150deg, #0b1724 0%, #102033 58%, #16293f 100%) !important;
  color: #fff !important;
  display: flex !important; align-items: center; flex-wrap: wrap; gap: 0;
  margin: -1px -1px 14px !important;
  padding: 11px 16px !important;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
  border-bottom: 2px solid rgba(45, 224, 206, .55) !important;
  border-image: none !important;
  box-shadow: inset 0 -1px 0 rgba(45, 224, 206, .18);
}
body .modal-panel > .modal-header > :is(h3, h4),
body .suivi-entete > :is(h3, h4) { color: #fff !important; margin: 0; }
body .suivi-entete .text-secondary,
body .modal-panel > .modal-header .text-secondary { color: #b9cbdd !important; }
body .modal-panel > .modal-header .modal-close { color: #d7e3ef !important; margin-left: auto; }

body .modal-panel > .modal-header::before,
body .section > h3::before, body .form-section > h3::before,
body .bloc-repliable > h3::before, body .panneau > h3::before,
body .section > .section-titre::before,
body .suivi-entete::before, body .fiche-dessin .bloc-titre::before {
  content: ''; flex: 0 0 auto;
  width: 4px; height: 18px; margin-right: 10px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}

body .table thead th {
  border-bottom: 2px solid transparent !important;
  border-image: linear-gradient(90deg, #12a89b 0%, #2de0ce 30%, #4f93f0 75%, rgba(79,147,240,0) 100%) 1 !important;
}
body .barre-nav, body .sous-onglets {
  border-bottom: 2px solid transparent !important;
  border-image: linear-gradient(90deg, #12a89b 0%, #2de0ce 30%, #4f93f0 75%, rgba(79,147,240,0) 100%) 1 !important;
}

/* ══ BANDEAUX DE SECTION ALLÉGÉS — 16/10/2026 ══════════════════════════════
   Le bandeau de nom garde l''ardoise ; les titres de section, eux, la
   répétaient à chaque bloc et écrasaient la fiche. Fond pâle aux mêmes
   teintes, titre en ardoise foncée, bâtonnet turquoise conservé. */
body .section > h3, body .form-section > h3, body .bloc-repliable > h3,
body .panneau > h3, body .section > .section-titre,
body .fiche-dessin .bloc-titre {
  background: linear-gradient(120deg, #eaf4f3 0%, #eef2f7 55%, #e9eef5 100%) !important;
  color: #16293f !important;
  padding: 9px 14px !important;
  border-bottom: 1px solid rgba(18, 168, 155, .35) !important;
  box-shadow: none !important;
}
body .section > h3::before, body .form-section > h3::before,
body .bloc-repliable > h3::before, body .panneau > h3::before,
body .section > .section-titre::before,
body .fiche-dessin .bloc-titre::before { height: 15px; }

/* ══ TROIS DEGRÉS DE TITRE — 16/10/2026 ════════════════════════════════════
   Le nom de la fiche garde l''ardoise pleine : il est l''identité de l''écran.
   L''affaire en est un enfant et non un pair — même famille, un cran plus
   clair. Les sous-sections passent au gris moyen, plus soutenu que les
   encadrés qu''elles coiffent, faute de quoi le titre flotte au-dessus de son
   propre contenu. */

/* Degré 2 — le bandeau d''affaire */
body .suivi-entete {
  background: linear-gradient(150deg, #23394f 0%, #2b4660 60%, #33506e 100%) !important;
  border-bottom: 2px solid rgba(45, 224, 206, .40) !important;
  padding: 9px 15px !important;
}

/* Degré 3 — les titres de bloc et de section */
body .section > h3, body .form-section > h3, body .bloc-repliable > h3,
body .panneau > h3, body .section > .section-titre,
body .fiche-dessin .bloc-titre, body .fiche-dessin h4.bloc-titre {
  background: linear-gradient(120deg, #c7d2de 0%, #cbd4df 55%, #c3cedb 100%) !important;
  color: #13243a !important;
  border-bottom: 1px solid rgba(18, 168, 155, .45) !important;
}

/* ══ ÉCART ENTRE LES DEGRÉS — 16/10/2026 ═══════════════════════════════════
   Le deuxième degré ne se distinguait pas du premier à l''œil nu : il remonte
   nettement vers l''ardoise claire. Le troisième ne se détachait pas des
   encarts : il descend d''un ton franc. */
body .suivi-entete {
  background: linear-gradient(150deg, #3b566f 0%, #46657f 60%, #51738e 100%) !important;
}
body .section > h3, body .form-section > h3, body .bloc-repliable > h3,
body .panneau > h3, body .section > .section-titre,
body .fiche-dessin .bloc-titre, body .fiche-dessin h4.bloc-titre {
  background: linear-gradient(120deg, #aebbc9 0%, #b3bfcc 55%, #a8b5c4 100%) !important;
  border-bottom: 1px solid rgba(18, 168, 155, .55) !important;
}

/* ══ LES TROIS DEGRÉS SUR TOUTES LES FICHES — 16/10/2026 ═══════════════════
   Le degré 1 était déjà général, tous les écrans partageant .modal-header.
   Le gris des titres de bloc, lui, ne mordait que sur la fiche de prospection
   parce qu''il était accroché à .fiche-dessin. Il s''étend aux noms de blocs
   des autres écrans : le pilotage, les sous-titres de fiche et les h4 nus des
   sections. Les h4 portant un style en ligne sont écartés : ce sont des
   surtitres en petites capitales, qu''un bandeau défigurerait, et leur style
   l''emporterait de toute façon sur cette feuille. bloc-titre--nu est écarté
   aussi : le suffixe dit qu''il se veut sans bandeau. */
body .bloc-titre:not(.bloc-titre--nu),
body .pilotage-bloc-titre,
body .sous-titre,
body .archive-sous-titre,
body :is(.section, .form-section, .bloc-repliable, .panneau, .modal-body) > h4:not([style]):not(.bloc-titre--nu) {
  background: linear-gradient(120deg, #aebbc9 0%, #b3bfcc 55%, #a8b5c4 100%) !important;
  color: #13243a !important;
  display: flex !important; align-items: center; flex-wrap: wrap;
  margin: 16px -1px 12px !important;
  padding: 9px 14px !important;
  border-bottom: 1px solid rgba(18, 168, 155, .55) !important;
  border-image: none !important;
  box-shadow: none !important;
}
body .bloc-titre:not(.bloc-titre--nu)::before,
body .pilotage-bloc-titre::before,
body .sous-titre::before,
body .archive-sous-titre::before,
body :is(.section, .form-section, .bloc-repliable, .panneau, .modal-body) > h4:not([style]):not(.bloc-titre--nu)::before {
  content: ''; flex: 0 0 auto;
  width: 4px; height: 15px; margin-right: 10px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}

/* ══ LES ONGLETS SORTENT DU BLANC — 16/10/2026 ═════════════════════════════
   La barre d''onglets, le titre de chaque onglet et les fiches miniatures
   étaient en noir sur blanc, indistinguables les uns des autres. */

/* La barre d''onglets, aux couleurs de la page de connexion */
body .barre-nav {
  background:
    radial-gradient(900px 420px at 10% -60%, #1d3550 0%, transparent 60%),
    linear-gradient(150deg, #0b1724 0%, #102033 58%, #16293f 100%) !important;
  padding: 0 6px !important;
  border-bottom: 2px solid transparent !important;
  border-image: linear-gradient(90deg, #12a89b 0%, #2de0ce 30%, #4f93f0 75%, rgba(79,147,240,0) 100%) 1 !important;
}
body .barre-nav .nav-tab {
  color: #b9cbdd !important;
  border: 0 !important; border-radius: 0 !important;
  background: transparent !important;
  box-shadow: inset 0 -3px 0 transparent;
}
body .barre-nav .nav-tab:hover {
  color: #fff !important;
  background: rgba(45, 224, 206, .10) !important;
  box-shadow: inset 0 -3px 0 rgba(45, 224, 206, .45);
}
body .barre-nav .nav-tab.active {
  color: #fff !important;
  background: rgba(45, 224, 206, .16) !important;
  box-shadow: inset 0 -3px 0 #2de0ce;
}

/* Le titre de l''onglet, au même rang que le nom d''une fiche */
body .tab-content h2, body .tab-content .form-title {
  background:
    radial-gradient(900px 420px at 12% -40%, #1d3550 0%, transparent 60%),
    linear-gradient(150deg, #0b1724 0%, #102033 58%, #16293f 100%) !important;
  color: #fff !important;
  display: flex !important; align-items: center;
  margin: 0 0 4px !important; padding: 11px 16px !important;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
  border-bottom: 2px solid rgba(45, 224, 206, .55) !important;
}
body .tab-content h2::before, body .tab-content .form-title::before {
  content: ''; flex: 0 0 auto;
  width: 4px; height: 18px; margin-right: 10px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}

/* Les fiches miniatures : une arête turquoise et un en-tête qui se voit */
body .client-card {
  border: 1px solid #b4c0cf !important;
  border-left: 4px solid #12a89b !important;
  background: #fff !important;
}
body .client-card:hover {
  border-left-color: #2de0ce !important;
  box-shadow: 0 6px 18px rgba(11, 23, 36, .16) !important;
}
body .client-card .client-card-header {
  background: linear-gradient(120deg, #e6edf4 0%, #eef2f7 100%) !important;
  margin: -1px -1px 10px !important; padding: 9px 12px !important;
  border-bottom: 1px solid rgba(18, 168, 155, .40) !important;
}
body .client-card .client-card-num { color: #0a6b63 !important; font-weight: 700; }
body .client-card .client-card-nom { color: #0b1724 !important; }
body .client-card .client-card-ville { color: #526171 !important; }

/* ══ LE BANDEAU D''ONGLET PREND TOUTE LA LARGEUR — 16/10/2026 ══════════════
   Le bandeau était posé sur le h2, qui est un élément de flexbox dans
   page-header : il se rétractait donc à la longueur du titre et ne tombait
   pas d''aplomb avec le texte de résumé ni avec les champs en dessous. Il
   passe sur le conteneur, qui tient déjà le titre, le résumé et le bouton
   d''action — lequel se trouve ainsi intégré au bandeau, comme demandé. */
body .tab-content h2 {
  background: none !important; color: #fff !important;
  margin: 0 !important; padding: 0 !important;
  border: 0 !important; border-radius: 0 !important;
}
body .tab-content h2::before { content: none !important; }

body .tab-content .page-header, body .tab-content .form-title {
  background:
    radial-gradient(900px 420px at 12% -40%, #1d3550 0%, transparent 60%),
    linear-gradient(150deg, #0b1724 0%, #102033 58%, #16293f 100%) !important;
  color: #fff !important;
  display: flex !important; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  width: 100%; box-sizing: border-box;
  margin: 0 0 14px !important; padding: 12px 16px !important;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
  border-bottom: 2px solid rgba(45, 224, 206, .55) !important;
}
body .tab-content .page-header::before, body .tab-content .form-title::before {
  content: ''; flex: 0 0 auto;
  width: 4px; height: 30px; margin-right: 4px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}
body .tab-content .page-header > div:first-of-type { flex: 1 1 auto; min-width: 0; }
body .tab-content .page-header .text-secondary { color: #b9cbdd !important; margin: 2px 0 0 !important; }

/* Les boutons d''action remontés dans le bandeau : lisibles sur l''ardoise */
body .tab-content .page-header .btn {
  border: 1px solid rgba(45, 224, 206, .55) !important;
  color: #eafaf8 !important;
  background: rgba(45, 224, 206, .14) !important;
}
body .tab-content .page-header .btn:hover {
  background: rgba(45, 224, 206, .26) !important;
  border-color: #2de0ce !important;
}
body .tab-content .page-header .btn-primary {
  background: linear-gradient(150deg, #12a89b, #0a6b63) !important;
  border-color: #2de0ce !important; color: #fff !important;
}
body .tab-content .page-header .btn-primary:hover {
  background: linear-gradient(150deg, #2de0ce, #12a89b) !important; color: #0b1724 !important;
}

/* ══ LES TITRES D''ENCART NE CHEVAUCHENT PLUS LEUR CADRE — 16/10/2026 ═══════
   Les titres des encarts de formulaire sont des <legend> de <fieldset>, et un
   legend se pose NATIVEMENT à cheval sur la bordure : c''est son dessin par
   défaut, pas un défaut de feuille. On le sort du cadre et on lui donne le
   gris moyen du troisième degré. */
body fieldset.form-section { padding-top: 0 !important; }
body fieldset.form-section > legend {
  float: left; width: 100%;               /* sort le legend du tracé de bordure */
  box-sizing: border-box;
  background: linear-gradient(120deg, #aebbc9 0%, #b3bfcc 55%, #a8b5c4 100%) !important;
  color: #13243a !important;
  display: flex !important; align-items: center;
  margin: 0 0 14px !important; padding: 9px 14px !important;
  border-bottom: 1px solid rgba(18, 168, 155, .55) !important;
}
body fieldset.form-section > legend::before {
  content: ''; flex: 0 0 auto;
  width: 4px; height: 15px; margin-right: 10px; border-radius: 2px;
  background: linear-gradient(180deg, #2de0ce, #12a89b);
}
body fieldset.form-section > legend + * { clear: both; }


/* ══ L'ÉTAT SE LIT SUR LE PICTOGRAMME — 17/10/2026 ════════════════════════
   La rangée de gestes disait ce que chaque bouton fait et s'il est possible.
   Elle ne disait pas si c'était DÉJÀ FAIT : on rouvrait la fiche pour
   l'apprendre. Quatre teintes l'annoncent désormais, et le mot les
   accompagne toujours — voir `boutonAction` dans js/prospection.js, où le mot
   entre dans le nom accessible et dans l'infobulle.

   ── Pourquoi des aplats si pâles ─────────────────────────────────────────
   La rangée porte déjà une teinte PLEINE pour le geste du moment
   (`bouton-icone--geste`, l'accent de la fiche sur fond blanc). Sept boutons
   vivement colorés ne distinguent plus rien : « déjà fait » est donc un lavis,
   et le geste du moment reste le seul élément qui saute aux yeux. Les trois
   états de signature sont un cran au-dessus — ils portent une progression,
   non un simple constat — mais restent des lavis.

   ── Pourquoi `:not(.bouton-icone--geste)` ────────────────────────────────
   Un même bouton peut être à la fois le geste réclamé et porteur d'un état :
   « Mettre en signature » l'est tant que le contrat n'est pas revenu signé.
   La teinte de l'état s'efface alors devant celle du geste, qui l'emporte ;
   le MOT, lui, reste dans le nom accessible et dans l'infobulle, de sorte que
   rien n'est perdu.

   ── Pourquoi ce poids de sélecteur ──────────────────────────────────────
   `.fiche-dessin .bouton-icone[aria-disabled="true"]` pose déjà un fond dans
   la fiche, et « Mettre en signature » est précisément désactivé une fois la
   demande partie. Les règles d'état doublent donc `.bouton-icone` pour passer
   devant lui, et rendent aux enfants leur opacité pleine : un lavis sous un
   texte à 50 % tomberait sous la barre AA.

   Les encres sont celles de la maison ; les aplats sont ceux que main.css
   emploie déjà pour les mêmes sens (ambre de l'attente, cyan de l'en-cours,
   vert de l'acquis).                                                       */
.bouton-icone.bouton-icone--fait:not(.bouton-icone--geste) {
  background: var(--color-primary-fd);
  border-color: var(--color-border);
  color: var(--color-text-2);
}
.bouton-icone.bouton-icone--signe-adresse:not(.bouton-icone--geste) {
  background: #fffbeb; border-color: var(--color-warning); color: var(--color-warning);
}
.bouton-icone.bouton-icone--signe-client:not(.bouton-icone--geste) {
  background: #ecfeff; border-color: var(--color-primary); color: var(--color-primary);
}
.bouton-icone.bouton-icone--signe-tous:not(.bouton-icone--geste) {
  background: #f0fdf4; border-color: var(--color-success); color: var(--color-success);
}
.bouton-icone.bouton-icone--fait:not(.bouton-icone--geste) > *,
.bouton-icone.bouton-icone--signe-adresse:not(.bouton-icone--geste) > *,
.bouton-icone.bouton-icone--signe-client:not(.bouton-icone--geste) > *,
.bouton-icone.bouton-icone--signe-tous:not(.bouton-icone--geste) > * {
  opacity: 1;
}
/* Le mot de l'état reprend l'encre du bouton : il ne redit pas la teinte,
   il la double en lettres. Dans la fiche seulement — sur la ligne du tableau
   il n'y a pas la place, et l'infobulle le porte. */
.fiche-dessin .actions-ligne--fiche .bouton-icone--fait .bouton-icone-marque,
.fiche-dessin .actions-ligne--fiche .bouton-icone--signe-adresse .bouton-icone-marque,
.fiche-dessin .actions-ligne--fiche .bouton-icone--signe-client .bouton-icone-marque,
.fiche-dessin .actions-ligne--fiche .bouton-icone--signe-tous .bouton-icone-marque {
  color: inherit; letter-spacing: .05em;
}

/* Le bandeau des signatures revenues pendant notre absence. Il emprunte la
   barre d'alerte du tableau de bord ; seule la liste qu'il porte est à
   dessiner, et elle suit celle des réponses au formulaire. */
.signatures-recues-liste {
  list-style: none; margin: 4px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 4px 18px;
}
.signatures-recues-liste li {
  display: flex; align-items: baseline; gap: 7px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   LE CHAT INTERNE DU LABORATOIRE

   Ajouté en FIN de feuille, et rien n'est modifié au-dessus : ce bloc doit
   pouvoir être retiré sans laisser de trace ailleurs. Tout y est préfixé
   « chat- », et aucune règle ne se pose sur une classe existante.

   ── Pourquoi ici et non dans une feuille à part ──────────────────────────
   `main.css` est encodé en Windows-1252 et porte un mojibake ancien : il ne
   doit pas être réécrit en bloc. Cette feuille-ci est la feuille des
   finitions, elle est en UTF-8 propre, et elle est déjà chargée par
   `index.html` comme par le service worker. Une feuille de plus aurait
   demandé une ligne dans la coquille hors connexion pour trente règles.

   ── La géométrie est celle de Lisa, délibérément ─────────────────────────
   Le propriétaire a demandé que le chat « s'ouvre comme Lisa visuellement ».
   La boîte reprend donc exactement sa boîte : même coin, 22 pixels de marge,
   380 × 560 au plus, même rayon, même ombre, même bascule sur
   `data-ouverte`. Les valeurs sont RECOPIÉES et non empruntées à `lisa.css` :
   deux écrans qui partageraient les mêmes sélecteurs finiraient par se gêner
   le jour où l'un des deux bougerait. Lisa est un modèle, pas une dépendance.

   Seul le bouton d'appel se décale — 54 pixels plus haut que celui de Lisa,
   sinon les deux se poseraient l'un sur l'autre. Les boîtes, elles, occupent
   bien le même coin : c'est ce qui était demandé, et la dernière ouverte
   passe devant (902 contre 901).
   ═══════════════════════════════════════════════════════════════════════════ */

#chat-appel {
  position: fixed;
  right: 22px;
  bottom: 76px;
  z-index: 900;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--color-border);
  border-radius: 24px;
  background: var(--color-surface);
  box-shadow: var(--shadow);
  font: 500 14px/1 system-ui, sans-serif;
  color: var(--color-text);
  cursor: pointer;
}
#chat-appel:hover { background: var(--color-bg); }
#chat-appel:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

/* La pastille dit qu'il y a du non-lu avant même qu'on ouvre la boîte, et le
   nombre le dit en chiffres : la couleur ne porte jamais seule. */
#chat-appel .chat-pastille {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-text-3);
}
#chat-appel[data-nonlus="oui"] .chat-pastille { background: var(--color-primary); }
#chat-appel .chat-compte {
  min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--color-primary); color: #fff;
  font-size: 11.5px; font-weight: 700; line-height: 19px; text-align: center;
  font-variant-numeric: tabular-nums;
}

#chat-boite {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 902;
  display: none;
  flex-direction: column;
  width: min(380px, calc(100vw - 32px));
  height: min(560px, calc(100vh - 44px));
  border: 1px solid var(--color-border);
  border-radius: 14px;
  background: var(--color-surface);
  box-shadow: 0 10px 34px rgba(16, 24, 40, .18);
  font: 14px/1.5 system-ui, sans-serif;
  color: var(--color-text);
  overflow: hidden;
}
#chat-boite[data-ouverte="oui"] { display: flex; }

.chat-entete {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--color-border);
}
.chat-entete h3 {
  margin: 0; font-size: 15px; font-weight: 600;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-entete .chat-vide { flex: 1; }
.chat-retour, .chat-fermer {
  flex: none; border: 0; background: none; padding: 2px 4px;
  font-size: 19px; line-height: 1; color: var(--color-text-2); cursor: pointer;
}
.chat-fermer { font-size: 22px; }
.chat-retour:hover, .chat-fermer:hover { color: var(--color-text); }
.chat-retour:focus-visible, .chat-fermer:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
  border-radius: var(--radius);
}

#chat-etat {
  margin: 0; padding: 8px 14px;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  font-size: 12.5px; color: var(--color-text-2);
}
#chat-etat[hidden] { display: none; }

.chat-corps { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#chat-accueil, #chat-conversation {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
}
#chat-accueil[hidden], #chat-conversation[hidden] { display: none; }

/* ── À qui l'on écrit ─────────────────────────────────────────────────────
   Le menu est en HAUT et non caché derrière un bouton « nouveau » : ouvrir
   une conversation est le geste ordinaire de cet écran, pas une exception.  */
.chat-ouvrir {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--color-border);
}
.chat-ouvrir label {
  flex: none; font-size: 12.5px; font-weight: 600; color: var(--color-text-2);
}
#chat-vers {
  flex: 1; min-width: 0;
  padding: 7px 9px;
  border: 1px solid var(--color-border-champ);
  border-radius: 9px;
  background: var(--color-surface);
  font: inherit; font-size: 13px; color: var(--color-text);
}

#chat-fils { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; }

/* Une conversation par ligne : le titre, l'heure, l'aperçu, et le compte des
   non-lus. Les deux nombres sont en chasse fixe — on compare deux lignes
   d'un coup d'œil, pas en comptant. */
.chat-fil-ligne {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 8px;
  width: 100%;
  margin-bottom: 4px;
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-surface);
  font: inherit; text-align: left; cursor: pointer;
}
.chat-fil-ligne:hover { background: var(--color-bg); }
.chat-fil-ligne:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
.chat-fil-titre {
  font-size: 13px; font-weight: 600; color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-fil-date {
  font-size: 11.5px; color: var(--color-text-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.chat-fil-apercu {
  grid-column: 1;
  font-size: 12px; color: var(--color-text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-fil-compte {
  grid-column: 2; justify-self: end; align-self: center;
  min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--color-primary); color: #fff;
  font-size: 11.5px; font-weight: 700; line-height: 19px; text-align: center;
  font-variant-numeric: tabular-nums;
}
/* Un direct et un groupe ne se confondent pas : le filet de gauche le dit
   sans un mot de plus, et le titre reste le même pour la lecture d'écran. */
.chat-fil-ligne[data-genre="direct"] { border-left: 3px solid var(--color-primary); }
.chat-fil-ligne[data-genre="groupe"] { border-left: 3px solid var(--color-info); }

.chat-vide-mot {
  margin: 10px 12px; font-size: 12.5px; line-height: 1.5;
  color: var(--color-text-2);
}

/* ── La conversation ──────────────────────────────────────────────────── */

#chat-messages {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 10px;
}

.chat-message { max-width: 90%; }
.chat-message[data-mien="oui"] { align-self: flex-end; }
.chat-message header {
  display: flex; align-items: baseline; gap: 8px;
  margin-bottom: 2px;
  font-size: 11.5px; color: var(--color-text-3);
}
.chat-message-auteur { font-weight: 600; color: var(--color-text-2); }
.chat-message-heure { font-variant-numeric: tabular-nums; }
.chat-message-texte {
  margin: 0; padding: 8px 11px; border-radius: 11px;
  background: var(--color-bg);
  font-size: 13.5px; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-message[data-mien="oui"] .chat-message-texte {
  background: var(--color-primary-fd);
}
/* « Corrigé » se lit sous le message. Le texte d'origine, lui, ne descend
   jamais du serveur : on ne promet donc nulle part de pouvoir le relire. */
.chat-message-marque {
  margin: 2px 0 0; font-size: 11px; font-style: italic;
  color: var(--color-text-3);
  font-variant-numeric: tabular-nums;
}
/* Un message retiré laisse sa trace et non un trou : la mention prend la
   place du texte, en filet pointillé pour qu'on voie qu'il y avait là
   quelque chose. */
.chat-message-retire {
  margin: 0; padding: 7px 11px;
  border: 1px dashed var(--color-border);
  border-radius: 11px;
  background: var(--color-surface);
  font-size: 12.5px; font-style: italic; color: var(--color-text-3);
}

.chat-message-gestes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.chat-geste {
  padding: 3px 9px;
  border: 1px solid var(--color-border);
  border-radius: 20px;
  background: var(--color-surface);
  font: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--color-text-2); cursor: pointer;
}
.chat-geste:hover { border-color: var(--color-primary); color: var(--color-primary-h); }
.chat-geste:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

.chat-correction { display: flex; flex-direction: column; gap: 6px; }
.chat-correction textarea {
  width: 100%; box-sizing: border-box; resize: vertical;
  padding: 8px 10px;
  border: 1px solid var(--color-border-champ);
  border-radius: 9px;
  font: inherit; font-size: 13.5px; color: var(--color-text);
}

/* ── Le pied : la portée, puis le champ ───────────────────────────────────
   LA PORTÉE EST AU-DESSUS DU CHAMP, EN CLAIR.

   Tout participant écrit aux quatre groupes, mais ne lit que ceux dont il
   fait partie : le DAF peut écrire au trio des responsables sans jamais y
   voir les réponses. Sans un mot à cet endroit précis, il croit avoir ouvert
   un échange. Ce n'est donc ni une infobulle — que personne ne survole — ni
   un repli : c'est une ligne de texte, toujours affichée pendant qu'on écrit,
   et portée par `role="status"` pour être annoncée à qui ne la regarde pas.

   Deux teintes, et aucune n'est une alarme : un envoi sans retour n'est pas
   une erreur, c'est l'arbitrage du propriétaire. L'ambre dit « sachez-le »,
   le gris dit « rien à signaler ».                                         */
.chat-pied {
  border-top: 1px solid var(--color-border);
  padding: 10px 12px;
}
.chat-pied[hidden] { display: none; }

#chat-portee {
  margin: 0 0 8px;
  padding: 7px 10px;
  border: 1px solid var(--color-border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--color-bg);
  font-size: 12px; line-height: 1.45;
  color: var(--color-text-2);
}
#chat-portee[data-sorte="sans-retour"] {
  border-color: var(--color-warning);
  background: #fffbeb;
  color: #7a4a05;
}
#chat-portee[data-sorte="membre"],
#chat-portee[data-sorte="direct"] {
  border-left-color: var(--color-primary);
}

.chat-saisie { display: flex; gap: 8px; align-items: flex-end; }
.chat-saisie textarea {
  flex: 1; min-width: 0; resize: none;
  padding: 9px 11px;
  border: 1px solid var(--color-border-champ);
  border-radius: 9px;
  font: inherit; font-size: 13.5px; color: var(--color-text);
}
.chat-saisie button {
  flex: none;
  padding: 9px 14px;
  border: 1px solid var(--color-primary);
  border-radius: 9px;
  background: var(--color-primary); color: #fff;
  font: inherit; font-weight: 600; cursor: pointer;
}
.chat-saisie button:hover { background: var(--color-primary-h); }
.chat-saisie button:disabled {
  border-color: var(--color-border); background: var(--color-bg);
  color: var(--color-text-2); cursor: not-allowed;
}
.chat-saisie button:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

.chat-reste {
  margin: 6px 0 0; font-size: 11.5px; color: var(--color-text-2);
  font-variant-numeric: tabular-nums;
}
.chat-reste[hidden] { display: none; }

/* L'étiquette que seule la lecture d'écran entend. Le champ a toujours un
   nom — « Votre message à Tout le monde » —, et ce nom change avec le
   destinataire : au clavier seul, on doit savoir à qui l'on écrit sans
   remonter lire l'en-tête. */
.chat-invisible {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

/* Sur un écran étroit, la boîte prend toute la largeur utile : à 380 pixels
   fixes elle déborderait, et le champ de saisie passerait hors de l'écran. */
@media (max-width: 480px) {
  #chat-boite { right: 12px; left: 12px; width: auto; bottom: 12px; }
  #chat-appel { right: 12px; bottom: 70px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LE CHAT — LES PIÈCES, LE TAG D'ÉCHANGES, L'APPEL

   Même discipline que le bloc ci-dessus : tout est préfixé « chat- », rien
   n'est posé sur une classe existante, et aucune ressource n'est appelée de
   l'extérieur. Les quelques règles qui REPRENNENT une déclaration d'au-dessus
   — le placement en grille d'une ligne de conversation — sont ici et non
   là-haut : ce bloc s'ajoute en fin de feuille et ne réécrit pas ce qui y
   était déjà.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Le tag d'échanges ────────────────────────────────────────────────────
   DEUX NOMBRES SUR LA MÊME LIGNE, ET ILS NE DISENT PAS LA MÊME CHOSE.

   « echanges » est le volume de ce qui s'est écrit dans le fil, retirés et
   masqués compris. « non_lus » est ce qui reste à lire, à la vue de cette
   personne-ci. Les confondre ferait croire à cinquante messages en attente.

   Quatre différences les séparent, et aucune ne travaille seule : la
   POSITION — le volume à gauche sur sa propre ligne, le non-lu à droite ; la
   FORME — l'un cerné et clair, l'autre plein ; les LETTRES — les initiales de
   l'autre partie, que la pastille du non-lu n'a jamais ; et le MOT, qui nomme
   ce qui est compté. Qui ne distingue pas les teintes garde les trois
   autres.                                                                   */
.chat-fil-titre   { grid-row: 1; grid-column: 1; }
.chat-fil-date    { grid-row: 1; grid-column: 2; }
.chat-fil-apercu  { grid-row: 2; grid-column: 1; }
.chat-fil-compte  { grid-row: 2; grid-column: 2; }
.chat-fil-echanges {
  grid-row: 3; grid-column: 1; justify-self: start;
  display: inline-flex; align-items: center; gap: 5px;
  margin-top: 3px;
  padding: 1px 8px 1px 3px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  font-size: 10.5px; color: var(--color-text-2);
}
.chat-fil-echanges[data-sorte="sans"] { padding-left: 8px; }
.chat-fil-initiales {
  padding: 0 5px; border-radius: 999px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  font-weight: 700; letter-spacing: .04em; line-height: 16px;
  color: var(--color-text-2);
}
.chat-fil-echanges-n {
  font-weight: 700; color: var(--color-text);
  font-variant-numeric: tabular-nums;
}
.chat-fil-echanges-mot { color: var(--color-text-3); }

/* La même chose en clair, une fois le fil ouvert : le jeton de la liste est
   trop court pour dire ce qu'il compte, et cette précision ne doit pas
   n'exister que pour la lecture d'écran. */
.chat-echanges {
  display: flex; align-items: center; gap: 7px;
  margin: 0; padding: 7px 14px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg);
}
.chat-echanges[hidden] { display: none; }
.chat-echanges-mot { font-size: 11.5px; color: var(--color-text-2); }

/* ── Les boutons d'appel, dans l'en-tête ──────────────────────────────── */
.chat-appels { flex: none; display: inline-flex; gap: 6px; }
.chat-appels[hidden] { display: none; }
.chat-appel-bouton {
  padding: 3px 9px;
  border: 1px solid var(--color-border);
  border-radius: 20px;
  background: var(--color-surface);
  font: inherit; font-size: 11.5px; font-weight: 600;
  color: var(--color-text-2); cursor: pointer;
}
.chat-appel-bouton:hover {
  border-color: var(--color-primary); color: var(--color-primary-h);
}
.chat-appel-bouton:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}

/* ── Une pièce dans la conversation ──────────────────────────────────── */
.chat-piece { margin: 0 0 4px; }
.chat-piece-vignette {
  display: block; padding: 0;
  border: 1px solid var(--color-border);
  border-radius: 11px;
  background: var(--color-bg);
  overflow: hidden; cursor: zoom-in;
}
.chat-piece-vignette img {
  display: block; max-width: 100%; max-height: 180px;
  width: auto; height: auto;
}
.chat-piece-vignette:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
/* Le son et la vidéo se lisent SUR PLACE : le lecteur est posé dans le fil,
   et non dans une fenêtre qui en sortirait. */
.chat-piece-lecteur {
  display: block; width: 100%; max-width: 260px;
  border-radius: 11px;
}
video.chat-piece-lecteur { max-height: 200px; background: var(--ardoise-900); }
.chat-piece-lecteur:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
.chat-piece-pied {
  display: flex; align-items: baseline; gap: 8px;
  margin: 3px 0 0; font-size: 11px; color: var(--color-text-3);
}
.chat-piece-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-piece-poids {
  flex: none; font-variant-numeric: tabular-nums;
}
/* Le refus du serveur se lit SOUS la pièce qu'il concerne, mot pour mot :
   la pièce absente, le message retiré et le fil qui ne nous est pas adressé
   ne se répondent pas de la même façon. */
.chat-piece-refus {
  margin: 4px 0 0; padding: 6px 9px;
  border: 1px solid var(--color-danger);
  border-radius: var(--radius);
  background: var(--color-surface);
  font-size: 11.5px; line-height: 1.4; color: var(--color-danger);
}
.chat-piece-refus[hidden] { display: none; }

/* ── Le pied : la pièce choisie, l'avancement, la prise en cours ──────── */
.chat-piece-attente, .chat-envoi, .chat-captation {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px; padding: 6px 9px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg);
  font-size: 11.5px; color: var(--color-text-2);
}
.chat-piece-attente[hidden], .chat-envoi[hidden], .chat-captation[hidden] {
  display: none;
}
.chat-piece-genre {
  flex: none; font-weight: 700; color: var(--color-text-2);
}
.chat-piece-attente .chat-piece-nom { flex: 1; min-width: 0; }
.chat-piece-attente .chat-geste, .chat-envoi .chat-geste,
.chat-captation .chat-geste { flex: none; }
.chat-envoi progress {
  flex: 1; min-width: 0; height: 7px;
}
.chat-envoi-part {
  flex: none; font-variant-numeric: tabular-nums; font-weight: 600;
}
/* La prise en cours se voit : un micro ouvert qu'on ne remarque pas est la
   seule faute que cet écran ne pourrait pas rattraper. */
.chat-captation {
  border-color: var(--color-danger);
  background: var(--color-surface);
  color: var(--color-danger);
}
.chat-captation-mot {
  flex: 1; min-width: 0; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.chat-outils { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.chat-outils .chat-geste[hidden] { display: none; }
.chat-outils .chat-geste:disabled {
  border-color: var(--color-border); color: var(--color-text-3);
  cursor: not-allowed;
}

/* Le glisser-déposer. Le liseré tient toute la boîte : on vise le chat, pas
   une cible de trente pixels qu'il faudrait chercher. */
#chat-boite[data-depot="oui"] {
  outline: 2px dashed var(--color-primary);
  outline-offset: -4px;
}

/* ── La pièce agrandie ───────────────────────────────────────────────────
   DANS la boîte, et non sur la page entière : le chat n'a pas à prendre
   l'écran du tableau de bord pour montrer une photo, et Échap la referme
   avant la conversation.                                                  */
.chat-loupe {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column;
  background: var(--color-surface);
}
.chat-loupe[hidden] { display: none; }
.chat-loupe-tete {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--color-border);
}
.chat-loupe-nom {
  flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-loupe-corps {
  flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 10px; background: var(--color-bg); overflow: auto;
}
.chat-loupe-corps img { max-width: 100%; max-height: 100%; }

/* Rien de ce bloc ne bouge, en mouvement réduit comme ailleurs : il n'y a
   aucune transition à éteindre. La règle est écrite pour que l'ajout d'une
   animation ici échoue au contrôle plutôt que de passer inaperçu. */
@media (prefers-reduced-motion: reduce) {
  .chat-piece, .chat-piece-vignette, .chat-piece-lecteur,
  .chat-piece-attente, .chat-envoi, .chat-captation,
  .chat-fil-echanges, .chat-appel-bouton, .chat-loupe {
    transition-duration: 0s !important;
    animation-duration: 0s !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LE CHAT — SUPPRIMER PAR CASES, ET VOIR CE QU'ON FILME

   Troisième et dernier bloc du chat, et même discipline que les deux
   précédents : ajouté en FIN de feuille, rien n'est modifié au-dessus, tout
   est préfixé « chat- », aucune règle ne se pose sur une classe qui ne soit
   pas de ce chantier, et aucune ressource n'est appelée de l'extérieur. Les
   teintes sont celles de `main.css`, pas une n'est inventée.

   ── Ce que ce bloc habille, et ce qu'il laisse derrière ───────────────────

   Les deux boutons que chaque message portait — « Corriger » et « Retirer » —
   ont quitté la ligne. Le retrait est passé dans un MODE qu'une corbeille
   ouvre depuis la ligne du bas ; la correction, elle, est supprimée, et
   `public/js/chatInterne.js` consigne à l'endroit du bouton qu'elle reste
   possible au serveur et n'est plus atteignable d'ici.

   La règle `.chat-correction` du premier bloc habillait le champ de ce
   bouton. Elle n'a plus de sujet dans le document, et elle est laissée telle
   quelle : ces blocs s'ajoutent, ils ne réécrivent pas ce qui était là.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── La corbeille, au bout de la ligne des outils ────────────────────────
   `margin-left: auto` plutôt qu'un ordre : la ligne porte trois boutons dont
   deux peuvent manquer — le vocal et la vidéo ne paraissent que si le
   navigateur sait produire un format que le serveur accepte —, et la
   corbeille doit fermer la marche dans les quatre cas.                     */
.chat-corbeille {
  margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 4px 10px;
}
.chat-corbeille svg { display: block; }
/* Le mode ouvert se voit sur le bouton qui l'a ouvert. La donnée qui le porte
   est `aria-pressed`, celle-là même que la lecture d'écran annonce : un seul
   état, et non un second posé à côté qui pourrait en diverger. */
.chat-corbeille[aria-pressed="true"] {
  border-color: var(--color-danger);
  color: var(--color-danger);
  background: var(--color-surface);
}

/* ── La barre du mode, et le bouton qui n'existe qu'avec lui ───────────────
   Elle reprend la forme des trois bandeaux du pied — pièce en attente, envoi,
   prise en cours —, et l'encre d'alerte de la prise : supprimer n'est pas un
   geste ordinaire. Sa hauteur est prise sur la LISTE DES MESSAGES, seul
   élément élastique de la colonne, et jamais sur le champ de saisie.       */
.chat-selection {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px; padding: 6px 9px;
  border: 1px solid var(--color-danger);
  border-radius: var(--radius);
  background: var(--color-surface);
  font-size: 11.5px; color: var(--color-danger);
}
.chat-selection[hidden] { display: none; }
.chat-selection-mot { flex: 1; min-width: 0; font-weight: 600; }
.chat-selection .chat-geste { flex: none; }
.chat-selection .chat-geste:disabled {
  border-color: var(--color-border); color: var(--color-text-3);
  cursor: not-allowed;
}

/* ── La case, en tête du message ──────────────────────────────────────────
   Une VRAIE case à cocher, et non un bouton déguisé : elle s'atteint à la
   barre d'espace, elle s'annonce « case à cocher, non cochée », et son nom
   dit de quel message il s'agit. Rien de tout cela ne se refait à la main.

   Le message coché porte en plus un liseré, parce que la case est petite et
   que l'on relit sa sélection d'un coup d'œil avant d'appuyer. L'état vient
   d'une donnée posée par le script et non de la seule couleur.             */
.chat-message-case {
  flex: none;
  width: 14px; height: 14px; margin: 0 2px 0 0;
  accent-color: var(--color-danger);
  cursor: pointer;
}
.chat-message-case:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
.chat-message[data-coche="oui"] {
  outline: 2px solid var(--color-danger);
  outline-offset: 3px;
  border-radius: 12px;
}

/* ── L'aperçu de ce qu'on filme ───────────────────────────────────────────
   LA HAUTEUR EST FIXE, ET C'EST TOUT L'ENJEU.

   La boîte fait 380 pixels de large et sa hauteur est bornée par
   `boites.css` : elle ne grandit pas d'un pixel quand l'aperçu paraît.
   Celui-ci prend donc sa place sur la LISTE DES MESSAGES, seul élément
   élastique de la colonne — `.chat-corps` et `#chat-conversation` sont en
   `flex: 1; min-height: 0` —, et le champ de saisie ne bouge pas.

   Une hauteur en proportion de la largeur — 16/9 sur les 356 pixels utiles —
   en ferait deux cents et mangerait la moitié du fil, et elle varierait avec
   la largeur de la boîte. Elle est donc écrite en pixels, et l'image est
   RECADRÉE plutôt que déformée : on vérifie son cadrage, on ne mesure pas
   des proportions.                                                         */
.chat-apercu {
  position: relative;
  margin-bottom: 8px;
  border: 1px solid var(--color-danger);
  border-radius: var(--radius);
  background: var(--ardoise-900);
  overflow: hidden;
}
.chat-apercu[hidden] { display: none; }
.chat-apercu-flux {
  display: block;
  width: 100%; height: 124px;
  object-fit: cover;
  background: var(--ardoise-900);
}
.chat-apercu-flux[hidden] { display: none; }
/* Pas d'image, pas de rectangle noir : la phrase prend toute la place, sur le
   fond clair des autres messages et non sur l'ardoise de l'aperçu. */
.chat-apercu-mot {
  margin: 0; padding: 14px 12px;
  background: var(--color-surface);
  font-size: 11.5px; line-height: 1.45; color: var(--color-danger);
}
.chat-apercu-mot[hidden] { display: none; }
/* Le chronomètre sur l'image : les yeux sont sur le cadrage, pas sur la barre
   d'état. Fond plein et non transparent — une image claire mangerait un
   chiffre posé dessus. */
.chat-apercu-duree {
  position: absolute; right: 6px; bottom: 6px;
  padding: 1px 8px; border-radius: 999px;
  background: var(--ardoise-900); color: #fff;
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Rien de ce bloc ne bouge non plus. La règle est écrite pour que l'ajout
   d'une animation ici échoue au contrôle plutôt que de passer inaperçu. */
@media (prefers-reduced-motion: reduce) {
  .chat-corbeille, .chat-selection, .chat-message-case,
  .chat-apercu, .chat-apercu-flux, .chat-apercu-duree {
    transition-duration: 0s !important;
    animation-duration: 0s !important;
  }
}
/* ═══════════════════════════════════════════════════════════════════════════
   LE CHAT — UN SEUL NOMBRE PAR LIGNE DE FIL, ET UNE PASTILLE QU'ON VOIT

   Quatrième et dernier bloc du chat, même discipline que les trois autres :
   ajouté en FIN de feuille, rien n'est modifié au-dessus, tout est préfixé
   « chat- », aucune ressource n'est appelée de l'extérieur, et les teintes
   sont celles de `main.css`.

   ── CE BLOC REPREND UNE NOTE QUI, PLUS HAUT, DIT DÉSORMAIS LE CONTRAIRE ───

   Le bloc des lignes de fil porte une note sur les DEUX NOMBRES de la même
   ligne, et sur les quatre différences — position, forme, lettres, mot —
   qui les empêchaient de se prendre l'un pour l'autre. Elle n'a plus
   d'objet. Le propriétaire a tranché : « il faut afficher uniquement ce que
   je n'ai pas encore lu. » Le volume d'échange, qui comptait tout ce qui
   s'était écrit dans le fil, retirés et masqués compris, a quitté l'écran ;
   le seul nombre qui reste sur la ligne est celui des non-lus, et il n'a
   plus rien avec quoi être confondu.

   Cette note ne peut pas être rayée d'ici — ces blocs s'ajoutent, ils ne
   réécrivent pas ce qui est au-dessus. Elle est donc REPRISE ici, et c'est
   ce paragraphe-ci qui fait foi. Avec elle, trois règles perdent leur sujet :
   `.chat-fil-echanges`, `.chat-fil-echanges-n` et `.chat-fil-echanges-mot`.
   Plus rien ne porte ces classes ; elles sont laissées en place plutôt que
   retirées au milieu d'une feuille qui ne se réécrit pas, et leur effacement
   est un geste pour qui tient ce fichier.

   ── Le jeton d'initiales, qui ne compte plus rien ─────────────────────────

   Il était l'enfant du jeton d'échanges et tenait de lui sa taille de texte
   comme sa place dans la grille. Il est maintenant seul sur sa ligne, et
   porte donc lui-même ce que son parent lui donnait. Le reste de son aspect
   — la pilule claire, le filet, les lettres grasses — est déjà déclaré plus
   haut et ne change pas : c'est ce qui le distingue de la pastille pleine du
   non-lu, à droite.                                                        */
.chat-fil-initiales {
  grid-row: 3; grid-column: 1; justify-self: start;
  margin-top: 3px;
  font-size: 10.5px;
}

/* ── La pastille du lanceur : pourquoi elle ne se voyait pas ───────────────

   Le mécanisme n'a jamais manqué — `rendreLaPastille` pose le total des
   non-lus et `data-nonlus` sur le bouton à chaque relevé. C'est l'ŒIL qui ne
   trouvait rien, et pour deux raisons qui se cumulaient.

   LA PREMIÈRE est que le point d'état paraissait en PERMANENCE et ne disait
   son état que par sa teinte. Un témoin toujours allumé cesse d'être lu, et
   les deux teintes en cause — le bleu pâle du repos, l'éclat du non-lu — ont
   la même clarté à un centième près : posées sur le dégradé turquoise du
   lanceur, elles ne se distinguent que par la nuance, c'est-à-dire pas du
   tout pour qui ne distingue pas les teintes. Le remède est dans
   `js/chatInterne.js` : le point ne paraît plus du tout quand il n'y a rien
   à lire, de sorte que sa seule PRÉSENCE porte la nouvelle.

   LA SECONDE est un contraste, et elle n'appartient pas à cette feuille :
   les teintes du point et du compte sont fixées dans `css/boites.css`, qui
   est chargée après celle-ci et reprend donc la main. Ce qui est fait ici
   est ce que cette feuille peut faire sans contrarier l'autre : `boites.css`
   ne déclare aucune ombre sur le compte, et c'est par là qu'on détache la
   pastille de son fond, quelle que soit la couleur qu'on lui donne. Un
   anneau blanc, et une ombre portée courte pour que le blanc lui-même ne se
   perde pas sur un fond clair. La correction des TEINTES, elle, est à porter
   dans `boites.css` par qui en a la charge.                                */
#chat-appel .chat-compte {
  box-shadow: 0 0 0 1.5px #fff, 0 1px 3px rgba(11, 23, 36, .4);
}

/* Rien de ce bloc ne bouge non plus — même raison que les trois autres : la
   règle est écrite pour que l'ajout d'une animation ici échoue au contrôle
   plutôt que de passer inaperçu. */
@media (prefers-reduced-motion: reduce) {
  .chat-fil-initiales, #chat-appel .chat-compte {
    transition-duration: 0s !important;
    animation-duration: 0s !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   L'AVATAR DU COMPTE — bandeau, liste des fils, messages, et son dépôt
   ══════════════════════════════════════════════════════════════════════════

   Tout est ici et rien dans `main.css`, bien que la pastille du bandeau y
   soit définie : cette feuille est chargée APRÈS, elle suffit donc à
   compléter `.compte-pastille` sans y toucher. `main.css` porte des séquences
   d'encodage abîmées qu'on préserve octet pour octet ; ne pas l'ouvrir est la
   façon la plus sûre de ne pas les abîmer davantage.

   LA RÈGLE, partout : l'image REMPLACE l'initiale, elle ne s'y ajoute pas.
   Deux pastilles côte à côte diraient deux personnes. C'est le balisage qui
   la tient — `js/app.js` et `pastille()` dans `js/chatInterne.js` ne posent
   jamais les deux —, et rien ici n'a à la rattraper.

   Les trois images partagent trois propriétés, et chacune répond à un défaut
   qu'on verrait sinon :

     · `object-fit: cover` — l'image envoyée est déjà un carré de 128 par 128,
       donc rien à recadrer en théorie. Mais un avatar posé avant ce lot, ou
       par un autre chemin, pourrait ne pas l'être : sans cela il paraîtrait
       étiré, ce qui se remarque immédiatement sur un visage ;
     · `display: block` — l'image est en ligne par défaut, et la ligne de base
       lui réserve alors deux ou trois pixels sous le bord. La pastille
       paraîtrait flotter au-dessus du texte qu'elle accompagne ;
     · un fond — une image transparente laisserait voir au travers, et une
       image qui tarde laisserait un trou là où il y avait des lettres.       */

/* ── La pastille du bandeau ────────────────────────────────────────────────
   Elle porte AUSSI `.compte-pastille`, donc sa taille, son cercle et son fond
   viennent de `main.css`. Il ne reste ici que ce qui ne vaut que pour une
   image. */
.compte-pastille-image {
  display: block;
  object-fit: cover;
  /* `main.css` pose `display: flex` sur la pastille, ce qui n'a pas de sens
     pour une image remplacée et en fait un conteneur vide de flux. Repassé en
     bloc ci-dessus ; le reste — 24 px, cercle, fond — est conservé tel quel. */
  flex: none;
}

/* ── La pastille d'un fil ──────────────────────────────────────────────────
   Elle porte aussi `.chat-fil-initiales`, donc sa place dans la grille de la
   ligne (rangée 3, colonne 1) et sa marge haute. Le `padding` horizontal du
   jeton de lettres, lui, élargirait l'image : il est annulé. */
.chat-fil-initiales-image {
  display: block;
  width: 18px; height: 18px;
  padding: 0;
  object-fit: cover;
  background: var(--color-bg);
}

/* ── La pastille d'un message ──────────────────────────────────────────────
   Nouvelle : l'en-tête d'un message ne portait jusqu'ici que le nom et
   l'heure. Elle est petite à dessein — on lit une conversation, pas un
   trombinoscope —, et `align-self` la décroche de la ligne de base que
   `.chat-message header` impose, sans quoi elle pousserait la ligne vers le
   bas de sa propre hauteur. */
.chat-message-pastille {
  flex: none; align-self: center;
  width: 17px; height: 17px;
  border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  font-size: 8.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--color-text-2);
  /* Les lettres d'un jeton de 17 px débordent dès trois caractères. Elles
     sont rognées plutôt que de déformer le cercle : deux lettres suffisent à
     reconnaître, et le nom complet est écrit juste à côté. */
  overflow: hidden;
}
.chat-message-pastille-image {
  display: block;
  object-fit: cover;
  border: 0;
}
/* Sur ses propres messages, qui sont alignés à droite, la pastille prend la
   teinte de la bulle : sans cela elle garderait le gris des autres et l'œil
   lirait un interlocuteur de plus dans la colonne de droite. */
.chat-message[data-mien="oui"] .chat-message-pastille {
  background: var(--color-primary-fd);
}

/* ── Le dépôt, en haut du chat ─────────────────────────────────────────────

   Le bouton EST la pastille : on voit sa photo — ou ses initiales — et l'on
   clique dessus pour en changer. Il tient dans l'en-tête à côté de la
   fermeture, qui est la place que le propriétaire a demandée.

   Le bouton de retrait ne paraît que s'il y a une photo à retirer. Il est
   posé EN CHEVAUCHEMENT du coin, et non à la suite : l'en-tête porte déjà le
   retour, le titre, les appels et la fermeture, et un sixième élément en
   ligne le ferait déborder sur un téléphone. */
.chat-avatar-bloc {
  position: relative;
  flex: none;
  display: inline-flex;
  line-height: 0;
}
.chat-avatar {
  flex: none;
  padding: 0; border: 0; background: none; cursor: pointer;
  line-height: 0;
  border-radius: 999px;
}
.chat-avatar:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px;
}
/* 34 px et non 24. Une photo de visage dans un disque de 24 px n'est plus un
   visage, c'est une tache de couleur : on ne reconnaît personne, et l'intérêt
   de déposer sa photo disparaît avec. Le monogramme, lui, y perdait ses
   déliés. L'en-tête du chat a la hauteur pour le porter. */
.chat-avatar-pastille {
  width: 34px; height: 34px;
  border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-primary); color: #fff;
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
  overflow: hidden;
}
.chat-avatar-pastille-image {
  display: block;
  object-fit: cover;
}
/* Le retrait de la photo a QUITTÉ le coin de la pastille.
   Il y était un disque de 16 px collé à la cible qu'on vise pour changer sa
   photo : on le ratait dans un sens comme dans l'autre, et le rater revenait
   à ouvrir un sélecteur de fichier dont on ne voulait pas. Il vit désormais
   dans le menu des réglages, à côté de la corbeille, là où sont déjà les
   gestes de cet écran. */
.chat-reglages-menu {
  display: flex; flex-direction: column; gap: 4px;
  margin: 6px 0 0; padding: 6px;
  border: 1px solid var(--color-border); border-radius: 8px;
  background: var(--color-surface);
}
.chat-reglages-menu[hidden] { display: none; }
.chat-reglages-menu .chat-geste { text-align: left; }
.chat-reglages[aria-expanded="true"] { color: var(--color-primary); }