
/* === badges === */
/* Badges — design system Syndic Ledger
   Cinq familles, une règle commune : LE LIBELLÉ PORTE L'INFORMATION,
   la teinte confirme. Les teintes suivent les rôles de correspondants
   (CS bleu / syndic ambre / tiers gris) partout où un état pointe
   vers un camp. */

/* ---- catégorie / provenance (travaux, sinistre, résident…) ---- */
.badge {
  font: 550 10px/1.4 var(--police-interface);
  text-transform: uppercase;
  letter-spacing: .05em;
  background: var(--surface-tonale);
  color: var(--encre-2);
  border-radius: 4px;
  padding: 2px 6px;
}

/* ---- état de dossier (5 états — § 1 d'idee-generale) ----
   La teinte dit chez qui est la balle : bleu = chez nous (agir),
   ambre = chez le syndic, gris = chez un tiers, neutre = nulle part. */
.badge-etat {
  font: 650 10px/1.4 var(--police-interface);
  text-transform: uppercase;
  letter-spacing: .05em;
  border-radius: 4px;
  padding: 2px 7px;
}
.badge-etat.etat-preparation { background: transparent; border: 1px solid var(--trait); color: var(--encre-2); }
.badge-etat.etat-attente-syndic { background: var(--role-syndic-fond); border: 1px solid var(--role-syndic-trait); color: var(--role-syndic-encre); }
.badge-etat.etat-attente-tiers { background: var(--role-tiers-fond); color: var(--role-tiers-encre); }
.badge-etat.etat-a-traiter { background: var(--accent-fond); color: var(--accent-encre); }
.badge-etat.etat-clos { background: transparent; border: 1px solid var(--trait); color: var(--encre-2); }
.badge-etat.etat-clos::before { content: "✓ "; }

/* ---- rôle d'un correspondant (vue fil, annuaire) ---- */
.badge-role {
  font: 550 10px/1.4 var(--police-interface);
  text-transform: uppercase;
  letter-spacing: .05em;
  border-radius: 4px;
  padding: 2px 6px;
}
.badge-role.role-cs { background: var(--role-cs-fond); color: var(--role-cs-encre); }
.badge-role.role-syndic { background: var(--role-syndic-fond); color: var(--role-syndic-encre); }
.badge-role.role-tiers { background: var(--role-tiers-fond); color: var(--role-tiers-encre); }

/* ---- statut de classement (registre Courrier) ----
   « À trier » est le seul statut qui appelle du travail : accent plein. */
.statut {
  font: 650 10px/1.4 var(--police-interface);
  text-transform: uppercase;
  letter-spacing: .05em;
  border-radius: 4px;
  padding: 2px 7px;
  display: inline-block;
}
.statut.st-atrier { background: var(--accent-action); color: var(--encre-inverse); }
.statut.st-verse { background: var(--surface-tonale); color: var(--encre-2); }
.statut.st-verse a { color: var(--accent-action); text-transform: none; letter-spacing: 0; }
.statut.st-ecarte { background: transparent; border: 1px solid var(--trait); color: var(--encre-2); }
.statut.st-archive { background: transparent; border: 1px dashed var(--trait-appuye); color: var(--encre-2); }

/* UN TROISIÈME CANAL : LA FORME (refonte du 2026-08-14).
   L'utilisateur premier du produit est daltonien, et la règle du projet est qu'aucune information
   ne passe par la seule couleur. Elle était déjà tenue : chaque statut porte son MOT écrit. Le
   glyphe ajoute un canal de plus, qui survit à ce que ni le mot ni la teinte ne survivent —
   une capture en noir et blanc, une simulation deutéranopie, un écran mal réglé, un coup d'œil
   trop rapide pour lire.

   TROIS FORMES DISTINCTES ET NON TROIS TEINTES : ● plein pour ce qui appelle du travail, ✓ pour
   ce qui est classé, – pour ce qui a été mis de côté. Elles se distinguent par leur SILHOUETTE,
   pas par leur remplissage — c'est ce qui les rend lisibles réduites à 10 px.

   EN ::before, ET C'EST LA RAISON POUR LAQUELLE CE N'EST PAS DU MARKUP : le contenu généré n'entre
   pas dans l'arbre d'accessibilité de la même façon qu'un caractère du texte. Un lecteur d'écran
   annonce « versé », jamais « coche versé » — le mot reste le seul texte, le glyphe reste un
   signal visuel. Écrire « ✓ versé » dans le gabarit aurait fait entendre le glyphe.

   PAS DE GLYPHE SUR .st-archive : cet état n'existe dans aucun écran livré (R-D6 a retiré le
   cinquième onglet). Lui en donner un serait dessiner pour un écran qui n'existe pas. */
.statut::before {
  font-weight: 700;
  margin-right: 4px;
  letter-spacing: 0;
}
.statut.st-atrier::before { content: "\25CF"; }  /* ● cercle plein */
.statut.st-verse::before  { content: "\2713"; }  /* ✓ coche */
.statut.st-ecarte::before { content: "\2013"; }  /* – tiret demi-cadratin */

/* ---- état en vocabulaire copro (portail public) ---- */
.badge-copro {
  font: 650 10px/1.4 var(--police-interface);
  text-transform: uppercase;
  letter-spacing: .05em;
  border-radius: 4px;
  padding: 2px 8px;
}
.badge-copro.bc-cs { background: var(--role-cs-fond); color: var(--role-cs-encre); }
.badge-copro.bc-syndic { background: var(--role-syndic-fond); border: 1px solid var(--role-syndic-trait); color: var(--role-syndic-encre); }
.badge-copro.bc-syndic .critique-n { color: var(--critique); font-weight: 700; }
.badge-copro.bc-clos { background: transparent; border: 1px solid var(--trait); color: var(--encre-2); }

/* ---- compteurs (nav, onglets) : du travail, jamais de la nouveauté ---- */
.compteur, .pastille {
  background: var(--accent-action);
  color: var(--encre-inverse);
  font: 600 10.5px/1.4 var(--police-interface);
  font-variant-numeric: var(--chiffres-tabulaires);
  border-radius: var(--rayon-pilule);
  padding: 1px 6px;
}

/* === bandeau-brouillon === */
/* Bandeau brouillon partagé — design system Syndic Ledger
   Un état du dossier (« un envoi se prépare »), pas un événement de
   timeline — épinglé en tête. N'importe qui peut reprendre ; la
   reprise est tracée au nom du repreneur (idee-generale.md § 1). */

.bandeau-brouillon {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 14px 26px 0;
  padding: 9px 14px;
  background: var(--accent-fond);
  border: 1px solid var(--role-cs-trait);
  border-radius: var(--rayon-carte);
  font-size: var(--texte-125);
}
.bandeau-brouillon .glyphe { font-size: 14px; }
.bandeau-brouillon strong { font-weight: 600; }
.bandeau-brouillon .detail { color: var(--encre-2); }
.bandeau-brouillon .gestes { margin-left: auto; display: flex; gap: 5px; }

@media (max-width: 980px) {
  .bandeau-brouillon .gestes { margin-left: 0; }
}

/* === boutons === */
/* Boutons — design system Syndic Ledger
   Consomme uniquement les rôles de tokens.css.
   L'accent est réservé à l'action première d'un contexte : UN
   .primaire par groupe d'actions, jamais plus. */

.btn {
  border: 1px solid var(--trait);
  background: var(--surface-carte);
  color: var(--encre);
  border-radius: var(--rayon-controle);
  padding: 3px 10px;
  font: 500 var(--texte-12)/1.45 var(--police-interface);
  cursor: pointer;
}
.btn:hover { border-color: var(--trait-appuye); }
.btn:focus-visible { outline: 2px solid var(--accent-action); outline-offset: 2px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* l'action première — l'unique accent */
.btn.primaire {
  background: var(--accent-action);
  border-color: var(--accent-action);
  color: var(--encre-inverse);
}
.btn.primaire:hover { background: var(--accent-action-survol); }

/* action de retrait : écarter, abandonner, annuler */
.btn.discret { border: none; background: none; color: var(--encre-2); }
.btn.discret:hover { color: var(--encre); }

/* dans une ligne dense (registre, suggestion IA) */
.btn.mini { padding: 1px 8px; font-size: var(--texte-115); }

/* Un geste mini reste une CIBLE DE 24 x 24 — septième règle de la tranche « gestes en modales », et
   la dernière que le budget autorise (quatrième promotion de M-D11, accordée par le propriétaire ;
   la sixième vit dans composants/timeline, toute HUITIÈME est un signal d'alarme à remonter).
   WCAG 2.2 AA, critère 2.5.8 « Target Size (Minimum) ».

   MESURÉ AU NAVIGATEUR (Chrome 151, fenêtre 1440 px, CSS servi, page rendue hors application),
   AVANT : les six gestes mini de l'écran d'un dossier font 18,67 px de HAUT — « ✎ renommer »
   86,58 x 18,67 · « corriger » 60,41 x 18,67 · les quatre « ⋯ » de la timeline 27,05 x 18,67 ·
   « qualifier » du latéral 61,50 x 18,67. La largeur passait déjà partout ; c'est la seule hauteur
   qui manquait. Sonde de la cible RÉELLE — elementFromPoint au centre et aux MILIEUX DES QUATRE
   BORDS d'un carré de 24 x 24 centré sur le geste, jamais aux coins : .btn pose border-radius 6px et
   le test de survol respecte l'arrondi, donc un coin manqué mesurerait le rayon et non la cible
   (WCAG 2.5.8 mesure la boîte englobante). AVANT « 10011 » — centre, gauche et droite atteints, haut
   et bas MANQUÉS. APRÈS 24,67 px de haut et « 11111 » sur les six gestes.
   L'exception « inline » de la norme était plaidable ; le propriétaire a tranché pour la
   conformité, parce que cette tranche fait du ⋯ l'affordance UNIQUE de N gestes par objet — un
   déclencheur par fil et un par mail, là où la cible était un décor.

   POURQUOI PADDING + MARGE NÉGATIVE ET NON « min-height », et c'est une mesure : ces gestes vivent
   tous dans un flex aligné en BASELINE ou en CENTER (« .evt.episode .tete-episode » et
   « .msg-compact » du composant timeline, « .entete-dossier .titre-ligne » et
   « .lateral .ligne-detail » en baseline, « .entete-dossier .meta-ligne » en center — composant
   en-tetes). Un min-height grandit la BOÎTE DE MARGE, donc la hauteur de la ligne de flex : le sujet
   du fil, le .lien-fil et la ligne de message d'en dessous descendaient. Ici les 3 px ajoutés de
   chaque côté du padding (1 px de .btn.mini → 4 px : 16,67 px de boîte de ligne, soit 11,5 px x
   1,45, en demandent 3,665 par côté pour atteindre 24 ; 4 est le premier pixel entier au-dessus, et
   un pixel entier tient le bord de la cible hors d'une frontière sous-pixel) sont RENDUS à la ligne
   par 3 px de marge négative. La boîte de marge vaut donc 18,67 px — exactement sa valeur d'avant —
   et la distance du bord de marge à la ligne de base ne change pas non plus (−3 + 4 = +1, le
   padding d'origine). Vérifié à la mesure : sur les deux écrans concernés, AUCUNE autre boîte ne
   bouge, ni en x, ni en y, ni en taille.

   POURQUOI CE SCOPE-LÀ, CONTENEUR PAR CONTENEUR. La règle nomme les quatre lignes denses où un
   geste mini est le SEUL accès à son objet. Elle ne porte volontairement pas :
   • sur « .entete-dossier .actions », dont le flex est en STRETCH — son ⋯ y mesure déjà
     27,05 x 25,39, la cible est atteinte sans rien faire, et la compensation y déplacerait le
     glyphe d'un pixel pour rien ;
   • sur le reste du dépôt, où .btn.mini n'est PAS un item de flex : le <summary class="btn discret
     mini"> de /fils est un display:list-item en flux, et une marge négative y remonterait le
     contenu qui suit de 3 px — mesuré nul après la règle, précisément parce que le scope l'exclut.
     Les cibles de /fils restent donc sous le plancher ; c'est un constat à remonter, pas une règle
     à écrire ici (le budget est clos à sept).
   CETTE RÈGLE VIT DANS « boutons » ET NON DANS « timeline » OU « en-tetes », et c'est un choix
   assumé : ses quatre sélecteurs finissent tous sur .btn.mini, dont elle corrige la boîte et dont
   le padding de 1 px ci-dessus est la cause. La couper en deux — une moitié dans timeline, l'autre
   dans en-tetes — ferait deux règles pour une seule décision d'accessibilité, donc deux endroits
   pour la faire dériver, et le budget de M-D11 n'en autorise qu'une.
   AUCUN GESTE VISÉ N'A DE BORDURE (tous sont .btn.discret, qui pose « border: none ») : le padding
   grandit une boîte invisible au repos. Un .btn.mini BORDÉ placé demain dans l'une de ces quatre
   lignes y gagnerait, lui, une bordure visiblement plus haute.
   AUCUN TEST NE PEUT VOIR CETTE RÈGLE : les tests lisent le HTML rendu, jamais le CSS appliqué ni
   la géométrie. */
.entete-dossier .titre-ligne > .btn.mini,
.entete-dossier .meta-ligne > .btn.mini,
.timeline .btn.mini,
.lateral .ligne-detail > .btn.mini {
  padding-block: 4px;
  margin-block: -3px;
}

/* création en pied de zone (+ Nouveau dossier) */
.btn.creer {
  border-style: dashed;
  border-color: var(--trait-appuye);
  border-radius: var(--rayon-carte);
  color: var(--encre-2);
  padding: 6px;
}
.btn.creer:hover { color: var(--accent-action); border-color: var(--accent-action); }

/* ---- l'IA est une proposition, jamais le chemin obligé ----
   Le tag marque l'origine ; le bloc porte la suggestion et son
   geste 1-clic. Sans clé LLM, ces blocs disparaissent — le
   composant hôte reste complet. */
.tag-ia {
  font: 700 9px/1 var(--police-interface);
  letter-spacing: .08em;
  border: 1px dashed var(--trait-appuye);
  border-radius: 4px;
  padding: 1px 4px;
  color: var(--encre-2);
}
.bloc-ia {
  border-top: 1px dashed var(--trait);
  padding-top: 6px;
  color: var(--encre-2);
  font-size: var(--texte-115);
}

/* === cartes === */
/* Cartes — design system Syndic Ledger
   Quatre variantes : dossier (accueil, colonnes), fil à trier
   (zone d'entrée), événement (agenda, dossier), fiche publique
   (portail). Toutes dérivent du même socle .carte/.fil. */

.fil, .carte {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.carte h3, .fil h3 {
  font-size: var(--texte-13);
  font-weight: 600;
  line-height: 1.35;
}
.exp, .quand, .meta, .extrait { color: var(--encre-2); font-size: var(--texte-12); }
.exp strong { color: var(--encre); }
.piece { font-size: var(--texte-115); color: var(--encre-2); white-space: nowrap; }
.piece .versee { font-weight: 600; color: var(--encre); }
.actions { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 3px; }

/* ---- carte-dossier : les cartes de l'accueil / colonnes ---- */
.carte .pied {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 2px;
}
.carte .referent { display: inline-flex; align-items: center; gap: 5px; margin-left: auto;
  color: var(--encre-2); font-size: var(--texte-115); }
.carte .epingle { font-size: var(--texte-12); }
.carte .evenement { font-size: var(--texte-12); color: var(--accent-action); font-weight: 500; }

/* silence critique : bord d'encre renforcé rouge (canal non chromatique : ‼ dans le chrono) */
.carte.critique { border-left: 3px solid var(--critique); }

/* la balle au conseil : bord renforcé accent — c'est là qu'on agit */
.carte.agir { border-left: 3px solid var(--accent-action); }

/* colonne en sourdine : la carte perd son ombre, reste lisible */
.colonne.sourdine .carte { box-shadow: none; background: transparent; }

/* ---- fil-à-trier : zone d'entrée, gestes créer/rattacher/écarter ---- */
.fil.bruit { opacity: .7; }

/* ---- carte-événement : agenda global + volet du dossier ---- */
.carte-evenement { display: flex; flex-direction: column; gap: 3px; }
.carte-evenement .ev-titre { font-size: var(--texte-13); font-weight: 600; }
.carte-evenement .ev-quand { font-size: var(--texte-12); color: var(--encre-2);
  font-variant-numeric: var(--chiffres-tabulaires); }
.carte-evenement .ev-origine { font-size: var(--texte-11); color: var(--encre-2); }
.carte-evenement .ev-badges { display: flex; gap: 5px; margin-top: 2px; }

/* ---- fiche-publique : le portail copropriétaires ---- */
.fiche {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.fiche .f-titre { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.fiche .f-titre strong { font-size: var(--texte-145); font-weight: 650; }
.fiche .f-meta { margin-top: 3px; font-size: var(--texte-12); color: var(--encre-2); }
.fiche .f-resume { margin-top: 8px; font-size: var(--texte-13); line-height: 1.55; }
.fiche.close { opacity: .75; }

/* === chips-filtres === */
/* Chips — design system Syndic Ledger
   Deux familles, même forme de pilule :
   - .chip-filtre : filtre cumulable, retirable (Dossiers, Pièces,
     page de résultats de recherche — chips en chips cumulables) ;
   - .chip-selecteur : sélecteur à choix unique (éditions passées
     du point mensuel, bascules de type liste). */

.barre-chips {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 12px 26px 0;
  font-size: var(--texte-12);
  color: var(--encre-2);
}

.chip-filtre {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--trait);
  background: var(--surface-carte);
  color: var(--encre);
  border-radius: var(--rayon-pilule);
  padding: 3px 10px;
  font-size: var(--texte-12);
}
.chip-filtre.actif {
  background: var(--accent-fond);
  border-color: var(--role-cs-trait);
  color: var(--accent-encre);
  font-weight: 600;
}
.chip-filtre .retirer {
  color: var(--encre-2);
  font-size: 11px;
  line-height: 1;
}
.chip-filtre.actif .retirer { color: var(--accent-encre); }
.chip-filtre .retirer:hover { color: var(--critique); }

.chip-ajouter {
  border: 1px dashed var(--trait-discret);
  background: transparent;
  color: var(--encre-2);
  border-radius: var(--rayon-pilule);
  padding: 3px 10px;
  font-size: var(--texte-12);
}
.chip-ajouter:hover { color: var(--accent-action); border-color: var(--accent-action); }

/* sélecteur à choix unique (éditions, bascules de vue) */
.barre-selecteur {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 12px 26px 0;
  font-size: var(--texte-12);
  color: var(--encre-2);
}
.chip-selecteur {
  border: 1px solid var(--trait);
  background: var(--surface-carte);
  border-radius: var(--rayon-pilule);
  padding: 2px 10px;
  font-size: var(--texte-115);
  color: var(--encre);
}
.chip-selecteur.actif {
  background: var(--accent-fond);
  border-color: var(--role-cs-trait);
  color: var(--accent-encre);
  font-weight: 600;
}

/* === chrono === */
/* Chrono deux aiguilles — design system Syndic Ledger
   Règle produit (idee-generale § 1) : le chrono du SILENCE ne repart
   qu'à une réponse de l'interlocuteur — jamais à nos relances ; la
   RELANCE s'affiche en seconde aiguille. Chiffres tabulaires partout.
   Le glyphe ‼ et la graisse portent la criticité — la couleur confirme. */

.chrono-2a {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-variant-numeric: var(--chiffres-tabulaires);
}
.chrono-2a .silence {
  font-size: var(--texte-125);
  font-weight: 600;
  color: var(--encre);
}
.chrono-2a .relance {
  font-size: var(--texte-115);
  color: var(--encre-2);
}

/* criticité : ‼ + graisse dans le markup, la couleur en renfort */
.chrono-2a.critique .silence { color: var(--critique); }

/* variante en ligne (en-têtes, générateur du point) */
.chrono-2a.enligne { flex-direction: row; gap: 6px; align-items: baseline; }
.chrono-2a.enligne .relance::before { content: "· "; }

/* forme courte (listes denses) : « ‼ silence 41 j · 3ᵉ relance » */
.chrono-court {
  font-size: var(--texte-115);
  color: var(--encre-2);
  font-variant-numeric: var(--chiffres-tabulaires);
}
.chrono-court.critique { color: var(--critique); font-weight: 600; }

/* l'item de silence dans une timeline : « — 5 jours sans réponse — » */
.silence-timeline {
  text-align: center;
  color: var(--encre-2);
  font-size: var(--texte-115);
  font-variant-numeric: var(--chiffres-tabulaires);
  padding: 2px 0;
}

/* === cloche-suivis === */
/* Cloche & suivis — design system Syndic Ledger
   Notifications nominatives, jamais issues de Courrier — le tri est
   du travail, pas de la nouveauté (idee-generale.md § 5). La cloche
   de la nav ouvre un panneau court ; « tout voir » mène à la page
   « Mes suivis ». Construit depuis le wireframe de Phase 1
   (docs/maquettes/2026-08-02-bilan-et-suivis.html). */

/* ---- panneau court, ancré sous la cloche ---- */
.cloche-panneau {
  position: absolute;
  width: 320px;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-flottante);
}
.cloche-panneau-tete {
  padding: 10px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-11);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
}
.cloche-nouveaute {
  padding: 9px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
}
.cloche-nouveaute:last-child { border-bottom: none; }
.cloche-nouveaute strong { font-weight: 600; }
.cloche-nouveaute .quand { color: var(--encre-2); font-size: var(--texte-11); }
.cloche-panneau-pied { padding: 8px 14px; text-align: center; border-top: 1px solid var(--trait); }
.cloche-panneau-pied a { color: var(--accent-action); font-size: var(--texte-12); font-weight: 600; }

/* ---- page « Mes suivis » ---- */
.suivis-liste {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  margin-bottom: 12px;
}
.suivis-liste .liste-tete {
  padding: 9px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-11);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
}
.ligne-suivi {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
  padding: 9px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
}
.ligne-suivi:last-child { border-bottom: none; }
.ligne-suivi .raison { font-style: italic; color: var(--encre-2); font-size: var(--texte-115); }
.ligne-suivi .ne-plus-suivre { margin-left: auto; }

.suivis-note { font-size: var(--texte-115); color: var(--encre-2); padding: 0 2px 12px; max-width: 560px; }

/* réglage du digest — un select générique (composants/formulaires) */
.digest-reglage {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 10px 14px;
  font-size: var(--texte-125);
  color: var(--encre-2);
}

/* === colonne-fenetre === */
/* Colonne-fenêtre — design system Syndic Ledger
   Le motif du tableau kanban de l'accueil (idee-generale.md § 1) :
   chaque colonne montre les N premiers selon l'urgence propre à la
   colonne, jamais un contenant infini — « voir les X autres » vers
   l'inventaire filtré. Réutilisable ailleurs qu'à l'accueil (agenda
   en rendu mois) : c'est un patron de disposition, pas un écran. */

.tableau {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 6px 26px 48px;
  overflow-x: auto;
}
.colonne {
  flex: 1 1 0;
  min-width: 218px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.col-tete { margin-bottom: 2px; }
.col-tete h2 {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: var(--texte-11);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
}
.compte {
  background: var(--surface-tonale);
  color: var(--encre);
  border-radius: var(--rayon-pilule);
  padding: 1px 7px;
  font-size: var(--texte-115, 10.5px);
  font-variant-numeric: var(--chiffres-tabulaires);
}
.col-note { font-size: var(--texte-11); color: var(--encre-2); margin-top: 3px; }

/* zone d'entrée « à trier » — pas un état, un statut de tri (retouche actée) */
.colonne.atrier {
  background: var(--surface-tonale);
  border: 1px dashed var(--trait-discret);
  border-radius: var(--rayon-zone);
  padding: 10px;
}

/* colonne en sourdine (clos récemment — n'affiche que les récents) */
.colonne.sourdine .carte { box-shadow: none; background: transparent; }
.colonne.sourdine h3 { color: var(--encre-2); font-weight: 500; }

/* le glisser exprime une intention — l'app propose l'action qui la réalise */
.depose {
  text-align: center;
  margin-top: 2px;
  border: 1px dashed var(--trait-discret);
  border-radius: var(--rayon-carte);
  padding: 8px 10px;
  font-size: var(--texte-115);
  color: var(--encre-2);
}

/* fenêtre priorisée : « voir les X autres » vers l'inventaire filtré */
.deborde { text-align: center; margin-top: 2px; }
.deborde a { color: var(--accent-action); font-size: var(--texte-12); font-weight: 550; }

@media (max-width: 980px) {
  .tableau { flex-direction: column; overflow-x: visible; }
  .colonne { min-width: 0; width: 100%; }
}

/* === composeur === */
/* Composeur — design system Syndic Ledger
   Panneau latéral du dossier / de la vue fil (mobile : plein écran).
   Répondre = pré-ciblé (destinataire, objet, citation) ; le pied est
   permanent — la conséquence d'état se dérive des destinataires et
   se met à jour en direct (idee-generale.md § 1). */

.composeur {
  position: sticky;
  top: 16px;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--accent-action);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-flottante);
  display: flex;
  flex-direction: column;
}
.composeur .c-tete {
  padding: 12px 14px 10px;
  border-bottom: 1px solid var(--trait);
}
.composeur .c-tete strong { font-size: var(--texte-13); font-weight: 650; }
.composeur .c-tete .c-note {
  display: block;
  margin-top: 2px;
  font-size: var(--texte-115);
  color: var(--encre-2);
}
.composeur .c-fermer { float: right; color: var(--encre-2); font-size: 14px; line-height: 1; }

.c-corps {
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-size: var(--texte-125);
}
.c-ligne { display: flex; gap: 7px; align-items: baseline; flex-wrap: wrap; }
.c-lib {
  color: var(--encre-2);
  font-size: var(--texte-11, 10.5px);
  text-transform: uppercase;
  letter-spacing: .05em;
  width: 40px;
  flex: none;
}
.chip-dest {
  border: 1px solid var(--trait);
  background: var(--surface-page);
  border-radius: var(--rayon-pilule);
  padding: 2px 10px;
  font-size: var(--texte-12);
}
.c-ajouter { font-size: var(--texte-115); color: var(--encre-2); }
.c-citation {
  border-left: 3px solid var(--trait);
  color: var(--encre-2);
  padding-left: 9px;
  font-size: var(--texte-12);
  line-height: 1.5;
}
.c-texte {
  border: 1px solid var(--trait);
  border-radius: var(--rayon-controle);
  padding: 9px 11px;
  min-height: 120px;
  font-size: var(--texte-125);
  line-height: 1.55;
  background: var(--surface-champ);
}
.c-pj { font-size: var(--texte-12); color: var(--encre-2); }

/* pied permanent : conséquence d'état + brouillon partagé + envoyer, toujours visibles */
.c-pied {
  border-top: 1px solid var(--trait);
  background: var(--surface-page);
  border-radius: 0 0 var(--rayon-carte) var(--rayon-carte);
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.c-consequence { font-size: var(--texte-115); color: var(--encre-2); }
.c-consequence strong { color: var(--encre); }
.c-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }

/* l'unique accent réservé à l'action première du composeur */
.btn.envoyer { background: var(--accent-action); border-color: var(--accent-action); color: var(--encre-inverse); }
.btn.envoyer:hover { background: var(--accent-action-survol); }

@media (max-width: 980px) {
  .composeur { position: static; }
}

/* === en-tetes === */
/* En-têtes — design system Syndic Ledger
   Deux en-têtes : le dossier (identité, état, actions, résumé IA)
   et le rattachement d'un fil (ce qu'aucun client mail n'a — visible
   et détachable). Chacun porte sa grille de mise en page : le
   dossier deux colonnes (timeline + latéral), le fil une colonne
   + composeur (le composeur est le lot 5). */

/* ---- en-tête de dossier ---- */
.entete-dossier {
  margin: 14px 26px 0;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 16px 18px;
}
.entete-dossier .titre-ligne { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.entete-dossier h1 { font-size: 18px; font-weight: 650; letter-spacing: -.01em; }
.entete-dossier .meta-ligne {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
  font-size: var(--texte-12);
  color: var(--encre-2);
}
.entete-dossier .actions { margin-top: 12px; }
.entete-dossier .ia { margin-top: 12px; font-size: var(--texte-12); line-height: 1.5; }

/* grille dossier : timeline (composants/timeline) + latéral (pièces, événements, détails) */
.grille { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; padding: 16px 26px 48px; }
.lateral { display: flex; flex-direction: column; gap: 12px; }
.lateral .carte h3 {
  font-size: var(--texte-11);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
  margin-bottom: 8px;
}
.lateral ul { list-style: none; display: flex; flex-direction: column; gap: 8px; font-size: var(--texte-125); margin: 0; padding: 0; }
.lateral li small { color: var(--encre-2); font-size: var(--texte-115); }

/* UN LIEN DU LATÉRAL DOIT SE VOIR — et sa forme dit CE QU'IL VA FAIRE.

   LA CONVENTION, énoncée par le propriétaire le 2026-08-14 et adoptée telle quelle :
     • TEINTE D'ACCENT, sans souligné → le lien OUVRE UNE PAGE ;
     • SOULIGNÉ POINTILLÉ, sans teinte au repos → le lien OUVRE UNE MODALE, sur place.
   Les deux formes se distinguent par la FORME autant que par la couleur, ce qui les rend
   discernables l'une de l'autre sans percevoir le bleu. Elles existaient déjà toutes les deux dans
   le dépôt — « .lien-fil a » (teinte) pour « voir le fil », « a.contact » (pointillé) pour la fiche
   d'un interlocuteur — mais aucune n'était énoncée, donc rien n'empêchait de les mélanger.

   C'EST EXACTEMENT CE QUI EST ARRIVÉ : première rédaction de cette règle, les fils du latéral —
   qui MÈNENT À UNE PAGE — recevaient le pointillé des modales. Deux liens voisins, même apparence,
   deux comportements. Le propriétaire l'a vu à l'écran.

   LE SÉLECTEUR EXCLUT LES DÉCLENCHEURS DE MODALE PAR LEUR MARQUEUR RÉEL, « [data-modale] », et non
   par une classe : c'est l'attribut que modales.js lit pour prendre la main, donc le seul qui ne
   puisse pas se désaccorder de ce que le lien FAIT vraiment. Un jour où l'on poserait un
   déclencheur sans classe .contact, il resterait pointillé — parce qu'il ouvre une modale, ce que
   son markup dit déjà.

   PAS DE SOULIGNÉ SUR LA FORME « PAGE » : le lien est déjà seul de sa couleur dans une carte de
   contexte écrite en gris, et le souligner ferait de la carte un tissu de traits dès qu'un dossier
   porte huit fils. C'est aussi le rendu de « .lien-fil a », que cette règle rejoint plutôt qu'elle
   ne l'invente. */
.lateral li a:not([data-modale]) { color: var(--accent-action); }
.lateral li a:not([data-modale]):hover { text-decoration: underline; }
.lateral .ligne-detail { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }

/* ---- en-tête de rattachement (vue fil) — ce qu'aucun client mail n'a ---- */
.vuefil {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 400px;
  gap: 16px;
  padding: 16px 26px 24px;
  align-items: start;
}
.fil-colonne { display: flex; flex-direction: column; gap: 12px; max-width: 760px; min-width: 0; }

.fil-entete .titre-ligne { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.fil-entete .titre-ligne strong { font-size: var(--texte-145, 15px); font-weight: 650; letter-spacing: -.01em; }
.fil-entete .rattachement {
  margin-top: 7px;
  font-size: var(--texte-12);
  color: var(--encre-2);
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}
.fil-entete .actions { margin-top: 10px; }

@media (max-width: 980px) {
  .grille { grid-template-columns: 1fr; }
  .vuefil { grid-template-columns: 1fr; }
}

/* === etats-vides === */
/* États vides — design system Syndic Ledger
   « File vide = ✓ rien à trier » — l'état vide est une récompense,
   à designer comme tel, pas une absence (idee-generale.md § 1,
   anti-réflexe Gmail). Le glyphe porte l'information, jamais la
   couleur seule. */

.etat-vide {
  text-align: center;
  padding: 40px 20px;
  color: var(--encre-2);
}
.etat-vide .glyphe {
  display: block;
  font-size: 28px;
  margin-bottom: 8px;
  color: var(--accent-action);
}
.etat-vide h3 { font-size: var(--texte-13); font-weight: 650; color: var(--encre); margin-bottom: 4px; }
.etat-vide p { font-size: var(--texte-12); max-width: 320px; margin: 0 auto; }

/* variante neutre (pas de contenu, sans connotation positive/négative) */
.etat-vide.neutre .glyphe { color: var(--encre-2); }

/* === fiche-contact === */
/* Fiche-contact — design system Syndic Ledger
   Toute adresse rencontrée peut être associée à une fiche : nom,
   société, rôle (le gestionnaire, l'ascensoriste, le résident du B).
   Popover ouvert depuis un nom cliquable (composants/timeline,
   composants/message : a.contact) — indépendant de la source
   (idee-generale.md § 1). */

.fiche-contact {
  position: absolute;
  width: 240px;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-flottante);
  padding: 12px 14px;
  font-size: var(--texte-125);
}
.fiche-contact .fc-entete { display: flex; align-items: center; gap: 8px; }
.fiche-contact .fc-nom { font-weight: 650; font-size: var(--texte-13); }
.fiche-contact .fc-role { color: var(--encre-2); font-size: var(--texte-115); margin-top: 2px; }
.fiche-contact .fc-societe { font-size: var(--texte-12); color: var(--encre-2); margin-top: 6px; }
.fiche-contact .fc-mail { display: block; margin-top: 6px; font-size: var(--texte-115); color: var(--accent-action); }
.fiche-contact .fc-pied { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--trait); }

/* DANS UNE MODALE, LA FICHE N'EST PLUS UN POPOVER — et sans cette règle elle n'a plus de taille
   du tout (défaut trouvé par le propriétaire au test manuel du 2026-08-14 : « la modale n'est pas
   à la bonne taille »).

   La cause exacte : la règle de base pose « position: absolute » et « width: 240px », parce que ce
   composant a été dessiné comme un POPOVER flottant à côté du nom cliqué — son propre en-tête le
   dit. Sorti du flux, il ne pousse plus son parent : le <dialog> se réduisait donc à la hauteur de
   son seul <h3>, et la fiche flottait par-dessus, sur 240 px, sans rapport avec la boîte qui
   l'entoure.

   Il fallait donc CHOISIR entre les deux formes, pas les superposer. La modale a été retenue
   (accessibilité : un popover au survol n'est atteignable ni au clavier ni au doigt), et la fiche y
   redevient un contenu ordinaire : dans le flux, à la largeur de son parent.

   ET ELLE PERD SON PROPRE HABILLAGE DE CARTE : fond, bordure, ombre et coins arrondis sont ceux de
   « .modale », qui l'entoure déjà. Les garder aurait fait une carte dans une carte — deux bordures
   concentriques à 14 px l'une de l'autre. Le padding part pour la même raison : la modale a le
   sien, et deux paddings ne se rattrapent pas, ils s'additionnent. */
.modale .fiche-contact {
  position: static;
  width: auto;
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}

/* === formulaires === */
/* Formulaires — design system Syndic Ledger
   Champs, select, toggle, radio/case. Aucun des 6 écrans déclinés
   n'en avait besoin (Réglages, Connexion sont « — formulaires
   simples » dans l'inventaire) — composant construit pour que ces
   écrans s'assemblent sans repasser par l'exploration visuelle. */

.ligne-champ {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 14px;
  max-width: 420px;
}
.ligne-champ label {
  font-size: var(--texte-12);
  font-weight: 600;
  color: var(--encre);
}
.ligne-champ .aide { font-size: var(--texte-11); color: var(--encre-2); }
.ligne-champ .erreur { font-size: var(--texte-11); color: var(--critique); font-weight: 500; }

.champ, .champ-select, .champ-texte {
  border: 1px solid var(--trait);
  border-radius: var(--rayon-controle);
  padding: 7px 10px;
  font: var(--texte-125)/1.4 var(--police-interface);
  background: var(--surface-champ);
  color: var(--encre);
}
.champ::placeholder, .champ-texte::placeholder { color: var(--encre-2); }
.champ:focus-visible, .champ-select:focus-visible, .champ-texte:focus-visible {
  outline: 2px solid var(--accent-action);
  outline-offset: 1px;
  border-color: var(--accent-action);
}
.champ.invalide { border-color: var(--critique); }

.champ-texte { min-height: 90px; resize: vertical; }

.champ-select { appearance: none; padding-right: 28px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 12px center, right 8px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  color: var(--encre-2);
}

/* toggle (interrupteur) — libellé toujours à côté, jamais seul */
.toggle-ligne { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.toggle-ligne .toggle-libelle { font-size: var(--texte-125); color: var(--encre); }
.toggle-ligne .toggle-aide { font-size: var(--texte-11); color: var(--encre-2); margin-top: 2px; }
.toggle {
  position: relative;
  width: 34px;
  height: 20px;
  flex: none;
  border-radius: var(--rayon-pilule);
  background: var(--trait-appuye);
  border: none;
  cursor: pointer;
}
.toggle::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--surface-carte);
  transition: transform .15s ease;
}
.toggle.actif { background: var(--accent-action); }
.toggle.actif::after { transform: translateX(14px); }
.toggle:focus-visible { outline: 2px solid var(--accent-action); outline-offset: 2px; }

/* radio / case natives — accent-color suffit, le libellé porte l'info */
input[type="radio"], input[type="checkbox"] { accent-color: var(--accent-action); }

/* section de formulaire (Réglages) */
.section-formulaire { max-width: 480px; margin-bottom: 24px; }
.section-formulaire h2 { font-size: var(--texte-13); font-weight: 650; margin-bottom: 10px; }

/* === gabarits === */
/* Gabarits — design system Syndic Ledger
   Deux gabarits : la page applicative (nav + zone de contenu) et
   la page publique autonome (portail copropriétaires — pas de nav,
   décision actée). Tout écran non exploré s'assemble à partir d'un
   de ces deux gabarits + les composants du système. */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  -webkit-font-smoothing: antialiased;
  background: var(--surface-page);
  color: var(--encre);
  font: var(--texte-corps)/1.45 var(--police-interface);
}
button { font: inherit; cursor: pointer; background: none; border: none; }
a { text-decoration: none; color: inherit; }
h1, h2, h3 { font-weight: inherit; margin: 0; }
svg { width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ---- gabarit-page : nav latérale + zone de contenu ---- */
.app { display: grid; grid-template-columns: 236px 1fr; min-height: 100vh; }
.app:has(.nav.repliee) { grid-template-columns: 64px 1fr; }

.page { min-width: 0; display: flex; flex-direction: column; }

.entete {
  display: flex;
  align-items: baseline;
  gap: 18px;
  padding: 22px 26px 14px;
}
.entete-titre { display: flex; align-items: baseline; gap: 14px; }
.entete h1 { font-size: var(--texte-titre-page); font-weight: 650; letter-spacing: -.01em; }
.date-jour { color: var(--encre-2); font-size: var(--texte-12); }

/* page-titre : variante sans bascule (Courrier, Point mensuel…) */
.page-titre { padding: 22px 26px 0; }
.page-titre h1 { font-size: var(--texte-titre-page); font-weight: 650; letter-spacing: -.01em; }
.page-titre .note { margin-top: 4px; font-size: var(--texte-125); color: var(--encre-2); max-width: 760px; }

/* LA LIGNE QUI SITUE (refonte du 2026-08-14) — « 17 fils à trier · page 1 sur 2 ».
   L'écran du courrier portait DEUX <h1> : « Courrier » dans .entete (gabarit de page) et
   « 42 fils à trier » dans .page-titre. Deux titres de premier niveau sur une même page, c'est un
   défaut d'accessibilité autant qu'un défaut de lecture : le titre changeait de texte à chaque
   onglet, donc la page ne disait jamais où l'on était.

   Le nom de l'écran reste le <h1>, le compte descend d'un cran. Il ne disparaît pas : il reste le
   canal NON CHROMATIQUE qui nomme l'onglet actif, à côté de aria-current — la teinte de
   « .onglet.actif » ne peut pas être seule à le dire.

   Chiffres tabulaires : cette ligne porte des nombres qu'on relit d'un affichage à l'autre. */
.page-titre .situe {
  margin-top: 2px;
  font-size: var(--texte-125);
  color: var(--encre-2);
  font-variant-numeric: var(--chiffres-tabulaires);
}
.page-liens { padding: 16px 26px 0; font-size: var(--texte-125); }
.page-liens a { color: var(--encre-2); }
.page-liens a:hover { color: var(--accent-action); }

/* bascule à 2 options (liste/tableau de l'accueil, liste/mois de l'agenda) */
.bascule { margin-left: auto; display: flex; align-items: center; gap: 0;
  background: var(--surface-tonale); border-radius: 7px; padding: 2px; }
.bascule-lib { margin-right: 8px; color: var(--encre-2); font-size: var(--texte-12); }
.bascule button { padding: 3px 12px; font-size: var(--texte-12); font-weight: 500;
  color: var(--encre-2); border-radius: 5px; }
.bascule button.actif { background: var(--surface-carte); color: var(--encre);
  box-shadow: var(--ombre-carte); }

/* ---- gabarit-public : page autonome, pas de nav (décision actée) ---- */
.portail { background: var(--surface-page); min-height: 100vh; }
.portail-page { max-width: 880px; margin: 0 auto; padding: 0 20px 56px; }
.portail-tete {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding: 26px 0 14px;
  border-bottom: 1px solid var(--trait);
}
.portail-tete h1 { font-size: var(--texte-titre-page, 19px); font-weight: 650; letter-spacing: -.01em; }
.portail-tete .sous-titre { color: var(--encre-2); font-size: var(--texte-13); }
.portail-tete .maj { margin-left: auto; color: var(--encre-2); font-size: var(--texte-12); }
.portail-intro { margin: 16px 0; font-size: var(--texte-125); color: var(--encre-2); line-height: 1.6; }
.portail-intro a { color: var(--accent-action); font-weight: 550; }
.portail-pied {
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid var(--trait);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--texte-12);
  color: var(--encre-2);
}
.portail-pied a { color: var(--accent-action); }

/* === generateur-point === */
/* Générateur du point mensuel — design system Syndic Ledger
   Composition par générateur : dossiers ouverts groupés par état,
   « en attente du syndic » et épinglés pré-cochés, question suggérée
   éditable par dossier, aperçu en face (idee-generale.md § 5,
   question n° 14 fermée). La structure dossier ↔ paragraphe est
   conservée dans l'aperçu. */

.generateur {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  padding: 14px 26px 24px;
  align-items: start;
}
.selection, .apercu {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
}
.selection .s-tete, .apercu .a-tete { padding: 11px 14px; border-bottom: 1px solid var(--trait); }
.selection .s-tete strong, .apercu .a-tete strong { font-size: var(--texte-13); font-weight: 650; }
.selection .s-tete .s-note, .apercu .a-tete .a-note {
  display: block;
  margin-top: 2px;
  font-size: var(--texte-115);
  color: var(--encre-2);
}

.groupe-etat {
  padding: 9px 14px 3px;
  font-size: var(--texte-11, 10.5px);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
  border-bottom: 1px solid var(--trait);
}

.dossier-coche {
  display: flex;
  gap: 9px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
  align-items: flex-start;
}
.dossier-coche:last-child { border-bottom: none; }
.dossier-coche input[type="checkbox"] {
  margin-top: 2px;
  accent-color: var(--accent-action);
  width: 14px;
  height: 14px;
}
.dossier-coche .d-infos { min-width: 0; flex: 1; }
.dossier-coche .d-ligne { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.dossier-coche .d-ligne strong { font-weight: 600; }
.dossier-coche .question { margin-top: 4px; color: var(--encre-2); font-size: var(--texte-12); }
.dossier-coche .question .q-edit { color: var(--accent-action); font-size: var(--texte-115); margin-left: 4px; }
.dossier-coche .question .q-effet { font-size: var(--texte-11); color: var(--encre-2); font-style: italic; }
/* exclu : jamais masqué, juste atténué — la raison reste lisible */
.dossier-coche.exclu { opacity: .6; }

/* aperçu : la structure dossier ↔ paragraphe, préservée en direct */
.apercu .a-corps { padding: 12px 14px; font-size: var(--texte-125); line-height: 1.6; }
.apercu .a-objet { color: var(--encre-2); border-bottom: 1px solid var(--trait); padding-bottom: 8px; margin-bottom: 8px; }
.apercu .a-editable { color: var(--encre-2); font-style: italic; }
.apercu .a-para { margin: 8px 0; }
.apercu .a-para strong { font-weight: 600; }

.generateur-pied {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: flex-end;
  font-size: var(--texte-12);
  color: var(--encre-2);
}

@media (max-width: 980px) { .generateur { grid-template-columns: 1fr; } }

/* === jalons === */
/* Jalons — design system Syndic Ledger
   Les étapes d'un dossier public, dérivées des bascules d'état —
   des métadonnées sûres, jamais du contenu de mail
   (idee-generale.md § 3, portail copropriétaires). Le glyphe (● / ○)
   et l'italique portent l'information de statut, la couleur confirme. */

.jalons {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 10px;
  font-size: var(--texte-12);
  color: var(--encre-2);
}
.jalon { white-space: nowrap; }
.jalon strong { font-variant-numeric: var(--chiffres-tabulaires); font-weight: 600; color: var(--encre); }
.jalon.fait::before { content: "●"; margin-right: 4px; color: var(--accent-action); }
.jalon.attendu { font-style: italic; }
.jalon.attendu::before { content: "○"; margin-right: 4px; }
.jalons .fleche { color: var(--trait-discret); }

/* === logo === */
/* Logo Syndic Ledger — design system
   Hérité de la v0.x : l'immeuble qui s'élève du registre.
   SVG inline, teinté par les rôles de tokens.css — pas de valeur
   en dur. Le badge, son rayon et le dégradé suivent --logo-1/-2/-rx. */

.marque {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.marque-texte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.logo {
  font-size: var(--texte-145);
  font-weight: 650;
  letter-spacing: -.01em;
  color: var(--encre);
}
.logo .mot2 {
  font-weight: 450;
  color: var(--accent-action);
}
/* LA BASELINE EST VISIBLE EN DIRECTION B, et cette règle disait le contraire.
   Elle portait « display: none — masqué en direction B, repris si une future direction le montre ».
   La déclinaison B actée le 2026-08-02 la MONTRE : docs/design/2026-08-02-declinaison-b/b.css:17
   pose « .baseline { display: block } », et sa seule extinction est au point de rupture étroit
   (b.css:66, avec .nav-repli). Le composant contredisait donc la direction qu'il prétendait servir,
   et personne ne l'a vu pendant cinq tranches parce qu'aucun gabarit ne posait le markup.

   Trouvé le 2026-08-14, sur la question du propriétaire : « pourquoi tu ne fais pas exactement ce
   design ? » — la réponse était que sur ce point-là, le design system lui-même ne le faisait pas. */
.baseline {
  display: block;
  font-size: var(--texte-11, 11px);
  color: var(--encre-2);
}

/* Étroit : la baseline s'efface, comme dans la déclinaison (b.css:66). La nav y devient un tiroir,
   et cinq mots d'explication n'y valent pas la hauteur qu'ils prennent. */
@media (max-width: 980px) {
  .baseline { display: none; }
}

.logo-icone {
  width: 30px;
  height: 30px;
  flex: none;
  stroke: none;
}
.logo-icone rect { stroke: none; }
.lg-badge { rx: var(--logo-rx); }
.lg-g1 { stop-color: var(--logo-1); }
.lg-g2 { stop-color: var(--logo-2); }
.lg-clair { fill: var(--logo-clair); }
.lg-fen { fill: var(--logo-1); }

/* variante compacte (pied de page publique, favicons de contexte) */
.logo-icone.compact { width: 20px; height: 20px; }

/* === message === */
/* Message — design system Syndic Ledger
   La conversation entière d'un fil, messages dépliés, nos envois
   en retrait. Teintes de rôle façon iMessage (retouche du
   2026-08-02) : CS bleu, syndic ambre, tiers gris — canal
   chromatique en renfort d'un badge de rôle (composants/badges),
   jamais seul. */

.message {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.message .m-tete { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; font-size: var(--texte-125); }
.message .m-tete .m-meta { color: var(--encre-2); font-size: var(--texte-12); }

/* « DÉJÀ VERSÉ À … », SUR LE MAIL LUI-MÊME (refonte du 2026-08-14).
   La mention est née le 2026-08-13, d'une question du propriétaire à son test manuel : « on me
   propose toujours de verser ce mail, est-ce normal ? » — oui, un mail peut appartenir à plusieurs
   dossiers ; ce qui manquait était de DIRE qu'il est déjà parti quelque part. Elle a été livrée en
   .m-meta, au bout de la ligne d'en-tête, où elle se lit comme un troisième fragment de méta après
   la date et les destinataires : au même poids que ce qu'elle doit dominer.

   Une pastille, donc, avec le même ✓ que le statut « versé » du registre (composant badges) : le
   glyphe qui veut dire « classé » est le même partout, sinon c'est un second vocabulaire à
   apprendre. Le texte, le lien et le mot ne changent pas — seul le poids visuel change. */
.message .m-verse {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--texte-115); color: var(--encre-2);
  background: var(--surface-tonale);
  border-radius: var(--rayon-pilule);
  padding: 1px 9px 1px 7px;
}
.message .m-verse::before { content: "\2713"; font-weight: 700; }
.message .m-verse a { color: var(--accent-action); }
/* white-space: pre-wrap — LA SEULE RÈGLE CSS de la tranche « vue d'un fil », accordée
   explicitement par le propriétaire. La contrainte « aucun CSS » de cette tranche tombe ici, pour
   la raison d'être de la page : elle existe pour LIRE une conversation.

   Le constat, mesuré : la maquette rend 4 sauts de ligne sur 6 lignes (corps de 116,25 px) ;
   l'application en rendait 0 sur 3 lignes (58,13 px), en « white-space: normal ». Le HTML servi
   PORTE bien les « \n » du texte extrait — c'était le rendu HTML qui les écrasait, donc un pavé
   continu là où le mail avait une salutation, un corps et une signature.

   CE N'EST PAS la décision de sécurité qui a été refusée. Rendre du texte NON ÉCHAPPÉ venu d'un
   mail (la variante « .raw » de Qute) reste interdit : pre-wrap ne touche pas à l'échappement,
   n'injecte rien, et n'ajoute aucun élément — elle ne change que la façon dont le navigateur
   traite des blancs déjà présents et déjà échappés.

   ASSUMÉ ET NON IGNORÉ : pre-wrap conserve aussi les COUPURES DURES des mails pliés à 72
   colonnes. C'est ce que fait tout client mail, et ça vaut mieux qu'un paragraphe unique — mais
   le prochain lecteur doit savoir que le choix a été fait en le sachant.

   Scope : « .message .corps », identique à la règle qui existait déjà. Le « .corps » des notes de
   l'écran du dossier vit sous « .evt » et non sous « .message » (vérifié) : il n'est pas touché. */
.message .corps {
  margin-top: 8px;
  font-size: var(--texte-125);
  line-height: 1.55;
  white-space: pre-wrap;
}
.message .m-gestes { margin-top: 9px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* nos envois : en retrait (jamais confondus avec un message reçu) */
.message.notre { margin-left: 26px; border-left: 3px solid var(--role-cs-trait); }

/* teintes de rôle — la couleur confirme, le badge (composants/badges) porte l'info */
.message.de-cs { background: var(--role-cs-fond); border-color: var(--role-cs-trait); }
.message.de-cs.notre { border-left-color: var(--role-cs-trait-fort); }
.message.de-syndic { background: var(--role-syndic-fond); border-color: var(--role-syndic-trait); }
.message.de-tiers { background: var(--role-tiers-fond); border-color: var(--role-tiers-trait); }

/* compensation de l'abandon du lien Gmail (retouche actée) */
.source-brute {
  font-size: var(--texte-115);
  color: var(--encre-2);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.source-brute:hover { color: var(--accent-action); }

@media (max-width: 980px) {
  .message.notre { margin-left: 12px; }
}

/* === modale === */
/* Modale — design system Syndic Ledger
   Coquille générique (fond assombri + carte centrée). L'exemple
   canonique est le garde-fou d'envoi : la confirmation ne s'interrompt
   que quand une adresse est inconnue du dossier — la friction n'existe
   que là où elle protège (idee-generale.md § 1). Réutilisable pour
   toute confirmation ciblée (abandonner un brouillon, fusionner deux
   dossiers…). */

.modale-fond {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 30;
}

.modale {
  max-width: 560px;
  width: 100%;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-zone);
  box-shadow: var(--ombre-modale);
  padding: 16px 18px;
  font-size: var(--texte-125);
}
.modale h3 { font-size: var(--texte-145, 13.5px); font-weight: 650; margin-bottom: 6px; }

/* liste d'informations récapitulatives — la dernière ligne est une note passive */
.modale ul { list-style: none; margin: 0; padding: 0; }
.modale li { padding: 7px 0; border-bottom: 1px solid var(--trait); line-height: 1.5; }
.modale li:last-of-type { border-bottom: none; color: var(--encre-2); }

.modale-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin-top: 10px; }

/* démonstration en page (preview uniquement) — pas un composant du système */
.demo-scene {
  background: var(--surface-tonale);
  border-radius: var(--rayon-zone);
  padding: 36px 20px;
  display: flex;
  justify-content: center;
}

/* Les SEPT règles de la tranche « gestes en modales » (M-D11, relâchée de deux à sept par décision
   de contrôle, en quatre fois — les règles 3 et 4 sont nommées et justifiées ci-dessous, chacune sur
   un constat MESURÉ ; les TROIS DERNIÈRES ne vivent pas ici : la 5e et la 6e dans
   composants/timeline — l'alignement du ⋯ au bord droit de sa ligne (M-D15, étendue de 292,86 px
   mesurée à la tâche 5) et l'heure d'un item lue comme celle d'un mail (M-D8, 12 px proportionnels
   contre 11 px tabulaires) — et la 7e dans composants/boutons, le plancher de 24 × 24 px des cibles
   mini (WCAG 2.2 AA 2.5.8, 18,67 px mesurés). Toute HUITIÈME est un signal d'alarme.
   1. showModal() met le dialogue dans la couche supérieure et dessine ::backdrop : le fond
      assombri est donc natif, et --scrim est le jeton que .modale-fond employait déjà. Aucune
      valeur nouvelle.
   2. Le repli de M-D7 : sans JavaScript, un <dialog> sans [open] est en display:none par la
      feuille de l'agent. La navigation de fragment le rend alors visible — non modal (ni Échap
      ni piégeage du focus, c'est la dégradation assumée), mais le geste reste atteignable.
      À noter, mesuré à la tâche 1 : un <dialog> ouvert par :target reste HORS FLUX, la feuille
      de l'agent ne lui donnant « position: fixed » que sur dialog:modal. Il ne peut donc jamais
      devenir un troisième item de .grille — le danger que le plan lui prêtait n'existait pas. */
dialog.modale::backdrop { background: var(--scrim); }
dialog.modale:target { display: block; }

/* 3. Le champ remplit la modale.
   .ligne-champ porte « max-width: 420px » (formulaires, :762) — juste dans une colonne de page,
   où il borne la longueur de ligne. Dans une modale, il laissait 102 px de blanc à droite du
   champ, et .modale-actions aligne ses boutons à flex-end de la modale ENTIÈRE : les boutons
   tombaient donc bien à droite du champ qu'ils valident.
   Ces 102 px sont un CALCUL, pas une estimation, et ils corrigent le « 140 px » que ce commentaire
   annonçait (revue de la tâche 1, D) : box-sizing: border-box est global (base, « *, *::before,
   *::after »), donc les 560 px de max-width couvrent bordure et padding — 560 − 2×18 de padding
   − 2×1 de bordure = 522 px de boîte de contenu, moins les 420 px de la borne = 102.

   ELLE VAUT POUR TOUS LES CHAMPS DE TOUTES LES MODALES DE LA TRANCHE, pas seulement pour la note :
   le datetime-local de la tâche 3, la catégorie de la tâche 4 et les <select> de la tâche 5
   passeront tous à 522 px. C'est cohérent et voulu — dans une modale, la borne de longueur de
   ligne n'a plus d'objet, c'est la modale qui la porte.

   M-D11 disait « deux règles, pas une troisième » ; cette règle-ci est la troisième, et c'est
   une décision de contrôle assumée. Le but de la contrainte était d'interdire le CSS NON
   EXAMINÉ, pas d'interdire une règle justifiée : l'implémenteur s'est arrêté et a remonté le
   constat, donc la contrainte a fonctionné. Scopée sous .modale, elle ne peut atteindre aucun
   autre écran, et elle n'introduit aucune valeur — elle retire une borne.

   Le correctif de « Annuler » mort (revue de la tâche 1, A) ne compte pas dans les quatre : c'est
   une règle injectée par /js/modales.js, délibérément absente d'ici — sa raison d'être est de ne
   pas exister quand le script ne tourne pas. */
.modale .ligne-champ { max-width: none; }

/* 4. Le filet entre deux gestes de la MÊME modale (M-D12).
   MESURÉ, Chrome 151, sur ce CSS-ci : un <form> n'a AUCUNE marge dans Blink — marge calculée à 0 px
   sur les quatre côtés, la feuille de l'agent ne lui en donnant pas et le système pas davantage
   (aucun sélecteur de type « form » n'existe dans tout le design system). Dans la modale
   à plusieurs gestes, le bas du bouton « Enregistrer la catégorie » et le haut du label
   « Référent » étaient donc à 0,00 px — le bouton d'un geste TOUCHE le libellé du suivant, et se
   lit comme appartenant au champ d'en dessous. C'est un groupement visuel FAUX dans la modale dont
   tout l'objet est de séparer des gestes concurrents. Après cette règle : 15,00 px, filet compris.
   (Deux frontières, pas trois : trois formulaires n'en font que deux. La troisième séparation, du
   dernier geste au « Fermer » de la modale, était et reste à 10 px — le margin-top de
   .modale-actions — et n'a jamais eu besoin de rien.)

   SÉLECTEUR DE FRÈRE ADJACENT, et c'est la moitié de la règle : les cinq modales à UN SEUL geste
   (tâches 1 à 3) n'ont pas de « form + form » et ne reçoivent donc rien. Vérifié au navigateur sur
   celle de la note — bordure, marge et padding de son <form> à 0, hauteur du dialogue identique
   avant et après la règle — et acquis par construction pour les quatre autres : un sélecteur de
   frère adjacent n'a rien à mordre là où il n'y a qu'un formulaire. Le filet n'existe que là où il y
   a deux gestes à séparer.

   AUCUNE VALEUR INVENTÉE : var(--trait) est le jeton de filet que .modale li emploie déjà pour
   séparer des lignes, et les 7 px sont le padding vertical de ce même .modale li. La séparation est
   une LIGNE, pas une couleur — règle d'accessibilité dure, l'utilisateur premier étant daltonien.

   LA VOIE ul/li A ÉTÉ ÉCARTÉE, ne « simplifie » pas vers elle. Envelopper chaque <form> dans un
   <li> de la liste ci-dessus donnait le même écart sans une ligne de CSS, et l'objection du
   grisement est bien inerte — mesuré par la REVUE de la tâche 4, pas ici : « .modale
   li:last-of-type { color: var(--encre-2) } » n'atteint aucun texte, parce que .ligne-champ label,
   .champ et .btn réaffirment tous var(--encre). Deux raisons l'emportent quand même : c'est un
   DÉTOURNEMENT d'un composant
   documenté « liste d'informations récapitulatives — la dernière ligne est une note passive », donc
   un mensonge du markup sur ce qu'il contient ; et « li:last-of-type » resterait une mine pour tout
   bloc futur qui finirait par de la prose non classée — le « verser ailleurs » de la tâche 5 devrait
   l'éviter à jamais, contrainte invisible que rien ne rappellerait. */
.modale form + form { margin-top: 7px; border-top: 1px solid var(--trait); padding-top: 7px; }

/* === nav-laterale === */
/* Nav latérale — design system Syndic Ledger
   Décision actée (idee-generale.md) : barre gauche dépliable/
   repliable, mémorisée par membre. Dépliée : icône + libellé.
   Repliée : icônes seules, le badge de compteur reste lisible
   dans les deux états. Mobile : devient un tiroir. */

.nav {
  display: flex;
  flex-direction: column;
  padding: 18px 12px 14px;
  position: sticky;
  top: 0;
  height: 100vh;
  background: var(--surface-nav);
  border-right: 1px solid var(--trait);
  width: 236px;
}

.nav-tete {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 0 8px 18px;
}
.nav-repli {
  margin-left: auto;
  flex: none;
  width: 24px;
  height: 24px;
  line-height: 1;
  color: var(--encre-2);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-controle);
}
.nav-repli:hover { background: var(--surface-survol); }

.nav-liens {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.nav-liens a, .nav-pied a, .nav-pied .membre {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  color: var(--encre-2);
  border-radius: var(--rayon-controle);
  font-size: var(--texte-13);
  font-weight: 500;
}
.nav-liens a:hover, .nav-pied a:hover {
  background: var(--surface-survol);
  color: var(--encre);
}
.nav-liens a.actif {
  background: var(--accent-fond);
  color: var(--accent-action);
  /* LA GRAISSE EST LE CANAL NON CHROMATIQUE de l'entrée courante (refonte du 2026-08-14).
     Le fond d'accent et la teinte d'accent sont deux canaux de COULEUR : l'utilisateur premier du
     produit est daltonien, et la règle du projet est qu'aucune information ne passe par la seule
     couleur. « Où suis-je » est une information. 650 la fait tenir en niveaux de gris, et
     aria-current="page" la porte pour un lecteur d'écran — trois canaux pour une question qu'on
     se pose sans y penser. */
  font-weight: 650;
}
.nav-liens .compteur, .nav-pied .pastille { margin-left: auto; }

/* LE MEMBRE CONNECTÉ, EN PIED — un <span> et JAMAIS un <a> (refonte du 2026-08-14).
   Le markup de référence de ce composant en fait un lien, vers un écran de profil qui n'existe
   pas dans l'application. Un lien qui ne mène nulle part est le bouton mort qu'E-D10 interdit :
   c'est donc un span, qui reprend la même boîte que les liens voisins (sélecteur ajouté à la règle
   commune ci-dessus) mais ni le survol ni le curseur. Il RÉPOND à une question — « sous quel
   compte suis-je ? » — que l'application ne posait nulle part, et qui compte dès qu'un second
   membre partage l'écran d'un conseil syndical. */
.nav-pied .membre { color: var(--encre-2); cursor: default; }
.nav-liens a.recherche {
  border: 1px solid var(--trait);
  background: var(--surface-carte);
  margin-top: 6px;
}
.nav-liens kbd {
  margin-left: auto;
  font: var(--texte-115)/1 var(--police-interface);
  color: var(--encre-2);
  border: 1px solid var(--trait);
  border-radius: 4px;
  padding: 1px 5px;
  background: var(--surface-page);
}

/* entrée temporaire pendant la reprise d'historique (assistant S5) */
.nav-liens a.reprise {
  color: var(--accent-action);
  font-weight: 600;
}

.nav-pied {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 12px;
  border-top: 1px solid var(--trait);
}
.avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  background: var(--encre);
  color: var(--encre-inverse);
  font-size: 10px;
  font-weight: 600;
}
.avatar-mini {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  background: var(--surface-avatar);
  color: var(--encre);
  font-size: 9px;
  font-weight: 600;
}

/* ---- état replié : icônes seules, libellés masqués, compteur lisible ----
   Le markup ne change pas — seule la classe .repliee sur .nav bascule
   l'affichage. La préférence se mémorise par membre (comme liste/tableau
   de l'accueil), côté application — hors périmètre du design system. */
.nav.repliee { width: 64px; }
.nav.repliee .marque-texte,
.nav.repliee .baseline,
.nav.repliee .nav-liens kbd { display: none; }

/* LES LIBELLÉS SE CACHENT À L'ŒIL, JAMAIS AU LECTEUR D'ÉCRAN.
   Cette règle posait « display: none » sur les .lib, ce qui les retire de l'arbre
   d'accessibilité : les entrées devenaient alors des liens SANS NOM ACCESSIBLE, puisque leur seule
   autre contenu est un <svg aria-hidden>. Une navigation entière muette, dans l'état même où le
   texte a disparu de l'écran — le pire des deux mondes.

   La technique dite « visually hidden » garde le nœud de texte dans l'arbre : le nom accessible de
   l'entrée reste « Courrier 17 » repliée comme dépliée, compteur compris. Un aria-label sur le lien
   aurait AUSSI marché, mais il aurait REMPLACÉ tout le contenu — donc avalé le compteur, qui est
   précisément l'information qu'on veut encore entendre quand les mots ne sont plus là.

   clip-path plutôt que l'ancien clip: rect() : même effet, propriété non dépréciée. white-space
   empêche un mot long de rendre la boîte de 1 px scrollable sur certains moteurs. */
.nav.repliee .nav-liens .lib,
.nav.repliee .nav-pied .lib {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.nav.repliee .nav-liens a, .nav.repliee .nav-pied a,
.nav.repliee .nav-pied .membre, .nav.repliee .nav-pied .btn {
  justify-content: center;
  padding: 9px;
  position: relative;
}
.nav.repliee .nav-liens .compteur, .nav.repliee .nav-pied .pastille {
  margin-left: 0;
  position: absolute;
  top: 2px;
  right: 2px;
}
.nav.repliee .nav-repli { transform: scaleX(-1); }

/* LE BOUTON DE DÉCONNEXION SE TIENT COMME UNE ENTRÉE DE MENU.
   .btn ne pose ni display ni gap (composant boutons) : son icône et son libellé se seraient posés
   comme deux mots collés, et le bouton se serait centré sur sa propre largeur au lieu de s'aligner
   sur la colonne. Ces quatre déclarations lui donnent la boîte de ses voisins — et rien d'autre :
   il garde sa bordure et son fond de .btn.discret, parce que c'est un GESTE et non une
   destination. La différence de forme est voulue ; c'est l'alignement qui ne l'était pas. */
.nav-pied .btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
}

/* LE GESTE DE DÉCONNEXION SUIT LA MÊME RÈGLE QUE LES ENTRÉES. Il vit dans un <form> (un POST, et
   jamais un lien — un GET le rejouerait au rechargement), donc aucun des sélecteurs ci-dessus ne
   l'atteignait : replié, son texte « Se déconnecter » débordait des 64 px de la colonne. Il porte
   maintenant une icône et un .lib comme ses voisins, et son <form> ne doit pas s'interposer entre
   la colonne et lui. */
.nav-pied form { display: contents; }

@media (max-width: 980px) {
  /* mobile : tiroir — .nav.ouverte pilotée côté application (hors CSS pur) */
  .nav {
    position: fixed;
    inset: 0 auto 0 0;
    width: 260px;
    transform: translateX(-100%);
    transition: transform .2s ease;
    z-index: 20;
  }
  .nav.ouverte { transform: translateX(0); }
}

/* === palette-commande === */
/* Palette de commande — design system Syndic Ledger
   Deux portes sur le même index (dossiers / mails / pièces, archivé
   non trié compris — S5) : la palette (Ctrl+K) pour sauter, la page
   de résultats pour fouiller (idee-generale.md § 1, écrans
   secondaires). Aucun des 6 écrans déclinés n'en avait besoin —
   construit depuis le wireframe de Phase 1. */

/* ---- palette (Ctrl+K) ---- */
.palette-fond {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: flex;
  justify-content: center;
  padding-top: 12vh;
  z-index: 40;
}
.palette {
  width: 100%;
  max-width: 560px;
  height: fit-content;
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-zone);
  box-shadow: var(--ombre-modale);
  overflow: hidden;
}
.palette-champ {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
}
.palette-champ input {
  border: none;
  outline: none;
  flex: 1;
  font: inherit;
  color: var(--encre);
  background: transparent;
}
.palette-champ input::placeholder { color: var(--encre-2); }

.palette-groupes { padding: 6px 0; max-height: 340px; overflow-y: auto; }
.palette-groupe-titre {
  padding: 6px 14px 3px;
  font-size: var(--texte-11);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
}
.palette-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 14px;
  font-size: var(--texte-125);
  color: var(--encre);
}
.palette-item .meta { color: var(--encre-2); font-size: var(--texte-115); }
.palette-item:hover, .palette-item.selectionne { background: var(--accent-fond); }

.palette-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  border-top: 1px solid var(--trait);
  font-size: var(--texte-11);
  color: var(--encre-2);
}
.palette-pied .voir-tout { font-weight: 600; color: var(--accent-action); }

/* ---- page de résultats ---- */
.resultats-tete { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 14px 26px 0; }
.resultats-tete .champ-recherche { font-weight: 600; }
.resultats-compte { color: var(--encre-2); font-size: var(--texte-12); }

.resultats-zone { padding: 14px 26px 24px; display: flex; flex-direction: column; gap: 14px; }
.resultats-groupe { background: var(--surface-carte); border: 1px solid var(--trait);
  border-radius: var(--rayon-carte); box-shadow: var(--ombre-carte); }
.resultats-groupe-tete {
  padding: 9px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-11);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
}
.resultat-ligne {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  padding: 9px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
}
.resultat-ligne:last-child { border-bottom: none; }
.resultat-ligne .extrait { color: var(--encre-2); }
.resultat-ligne mark { background: var(--accent-fond); color: var(--accent-encre); font-weight: 600; padding: 0 2px; border-radius: 2px; }

/* === registre === */
/* Registre — design system Syndic Ledger
   Courrier : chaque fil de la boîte est quelque part — la colonne
   de droite est le statut de classement (composants/badges : .statut).
   Anti-réflexe Gmail : zéro non-lu, zéro gras de nouveauté, zéro
   notification née d'ici (idee-generale.md § 1). */

.onglets {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 14px 26px 0;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--trait);
}
.onglet {
  padding: 7px 12px 9px;
  font-size: var(--texte-125);
  font-weight: 500;
  color: var(--encre-2);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  border-radius: var(--rayon-controle) var(--rayon-controle) 0 0;
}
.onglet:hover { color: var(--encre); background: var(--surface-survol); }
.onglet.actif { color: var(--accent-action); border-bottom-color: var(--accent-action); font-weight: 600; }
.onglet .n {
  font-variant-numeric: var(--chiffres-tabulaires);
  color: var(--encre-2);
  font-weight: 500;
  margin-left: 3px;
}
.onglet.actif .n { color: var(--accent-action); }
.onglets .outils { margin-left: auto; display: flex; gap: 6px; align-items: center; padding-bottom: 8px; }

.recherche-registre {
  border: 1px solid var(--trait);
  border-radius: var(--rayon-controle);
  padding: 5px 10px;
  font: var(--texte-125)/1 var(--police-interface);
  background: var(--surface-champ);
  color: var(--encre);
  min-width: 230px;
}
.recherche-registre::placeholder { color: var(--encre-2); }

.registre-zone { padding: 14px 26px 24px; }
.registre {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
}

/* la ligne du registre : initiales + objet + le statut de classement (composants/badges)

   TROIS COLONNES DEPUIS LA REFONTE DU 2026-08-14, et le renversement porte sur la HIÉRARCHIE
   plutôt que sur la couleur. Avant : « Cabinet Girard — Devis remplacement caisson VMC · 30/07 ·
   3 mails », l'expéditeur en tête (metaOf le posait en premier) et l'OBJET au milieu d'une ligne
   de méta. Or on vient ici chercher un objet : « À trier » est une file de travail qu'on dépile,
   et l'objet était précisément l'élément le plus difficile à trouver sur l'écran.

   Après : l'objet seul en première ligne et en graisse, l'expéditeur en seconde avec son badge de
   rôle, la méta en troisième. La date quitte la méta pour la colonne de droite, où elle s'aligne
   et se compare d'une ligne à l'autre. AUCUNE DONNÉE NOUVELLE — les quatre morceaux étaient déjà
   à l'écran, dans le même ordre de lecture, tassés sur une ligne et demie. */
.registre .ligne {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  gap: 8px 12px;
  align-items: start;
  padding: 10px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
}
.registre .ligne:last-child { border-bottom: none; }
.registre .ligne.sourdine { opacity: .72; } /* jamais un gras — l'atténuation est le seul canal, réservé au bruit */

/* LE SURVOL DE LA LIGNE ENTIÈRE. Sur une file qu'on dépile, le geste se pose par un « ⋯ » au bout
   de la ligne : savoir quelle ligne on vise AVANT de cliquer évite le geste posé sur la voisine.
   Une teinte de surface, jamais une teinte d'information — le survol ne dit rien de l'état. */
.registre .ligne:hover { background: var(--surface-survol); }

/* LES INITIALES DE L'EXPÉDITEUR — un repère de FORME, pas une information.
   Elles ne disent rien que le nom, deux lignes plus bas, ne dise déjà ; leur seul rôle est de
   donner à l'œil un point d'ancrage régulier pour balayer vingt-cinq lignes. D'où aria-hidden
   dans le markup : un lecteur d'écran n'a pas à entendre « C G » avant chaque sujet.
   Elles reprennent .avatar-mini (composant nav-laterale) d'un cran plus grand — même fond, même
   graisse, même forme : le lecteur ne doit pas apprendre un second vocabulaire. */
.registre .initiales {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-avatar); color: var(--encre);
  font: 600 10px/1 var(--police-interface);
  letter-spacing: .02em; flex: none; margin-top: 1px;
}

/* Le SUJET d'un fil NON rattaché n'avait aucune graisse — R-D11 (« la dette d'accessibilité de cet
   écran se paie ICI »), tâche 7 de la tranche « registre du courrier ».
   COMPOSANT registre, SÉLECTEUR .registre .objet (avant : .registre .objet a — voir plus bas).

   CE QU'ELLE CORRIGE. La seule règle de graisse portait sur .objet A, jamais sur .objet lui-même. Sur
   la file de travail réelle (spec, section « Mesures »), 42 fils sur 45 ne sont rattachés à AUCUN dossier :
   leur sujet est un texte nu, sans <a>, et ne recevait donc ni cette règle ni aucune autre — c'est le
   défaut le plus visible de l'écran, constaté par le propriétaire à son test manuel.
   MESURÉ AU NAVIGATEUR (Chrome 151.0.7922.110, fenêtre 1440 px, CSS servi, page rendue hors
   application — HTML capturé par un test RestAssured de /fils, l'application n'a jamais été démarrée)
   sur trois sujets réalistes : non lié « Syndic — Cabinet Girard : appel de fonds… » et « Devis
   remplacement ascenseur bâtiment B », graisse 400 (celle de <body>, --texte-corps, rien ne la
   changeait) ; lié « Fuite toiture — copropriétaire du 3e », graisse 600. Le même écran affichait donc
   deux poids pour la même information — le sujet d'un fil — selon un hasard de classement sans rapport
   avec la lisibilité recherchée. APRÈS : les trois sujets, liés ou non, mesurent 600.

   PAS DE COULEUR, ET C'EST DÉLIBÉRÉ (contrainte 10 — utilisateur principal daltonien, R-D11). La
   seule propriété posée est font-weight ; .registre .objet a:hover garde SEULE la teinte d'accent au
   survol. Un sujet non lié ne change donc jamais de couleur et ne se souligne jamais : il ne peut pas
   se lire comme un lien qui ne clique pas — le bouton mort qu'E-D10 interdit. C'est exactement la
   question tranchée par le propriétaire : rendre le sujet lisible SANS imiter un lien.

   LA RÈGLE EST REMONTÉE, PAS DUPLIQUÉE : « .registre .objet a { font-weight: 600 } » devient
   « .registre .objet { font-weight: 600 } ». Un <a> n'a aucun style UA de font-weight (seuls
   text-decoration et color le sont, posés par composants/gabarits) : il HÉRITE de son parent .objet, donc un
   fil rattaché mesure encore 600 après la fusion — 0,00 px de différence, vérifié à la mesure. Écrire
   les deux règles aurait été la redite qu'un futur lecteur aurait pu croire significative.

   CE QUI NE BOUGE PAS, VÉRIFIÉ À LA MESURE : .meta et le second .meta de la mention R-D3b restent des
   <span> SEPARÉS dans le même conteneur .objet (list.html) — jamais des enfants du sujet — donc ils
   n'héritent pas de cette graisse ; leur couleur (--encre-2) et leur taille (--texte-115) sont
   inchangées avant/après.
   AUCUN NOMBRE INVENTÉ : 600 est la valeur déjà en service dans ce même composant.
   AUCUN TEST NE PEUT VOIR CETTE RÈGLE : les tests lisent le HTML rendu, jamais le CSS appliqué. */
.registre .objet { font-weight: 600; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.registre .objet a:hover { color: var(--accent-action); }
.registre .meta { display: block; margin-top: 2px; color: var(--encre-2); font-size: var(--texte-115); }

/* LE SUJET COUPE PLUTÔT QU'IL N'ENROULE. Un sujet de mail réel dépasse souvent la colonne (« RE:
   RE: TR: Devis remplacement caisson VMC bâtiment A1 — relance du 12/07 ») : enroulé sur trois
   lignes, il fait respirer une ligne sur cinq et le tableau perd son rythme. Coupé, chaque ligne
   du registre a la même hauteur et l'œil descend droit. Le sujet ENTIER reste atteignable — c'est
   un lien, la page du fil le porte en titre. */
.registre .sujet {
  font-size: var(--texte-13);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* LA GRAISSE SE REMET À PLAT SUR LES DEUX LIGNES SECONDAIRES. « .registre .objet { font-weight:
   600 } » (ci-dessus) a été remontée à la tâche 7 pour qu'un sujet NON LIÉ soit aussi lisible
   qu'un sujet lié — 42 fils sur 45 sont dans ce cas. Elle porte donc sur tout le bloc .objet, dont
   l'expéditeur et la méta héritent depuis que ce bloc en est le parent. Sans ce retour à 400,
   trois lignes de même poids : c'est-à-dire la ligne d'avant, en plus haut. */
.registre .de,
.registre .objet .meta { font-weight: 400; }

.registre .de {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--texte-12); color: var(--encre-2); min-width: 0;
}
.registre .de .nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* LA DATE EN CHIFFRES TABULAIRES, à largeur réservée. C'est la seule colonne qu'on compare d'une
   ligne à l'autre ; des chiffres proportionnels la font onduler. --chiffres-tabulaires existe
   pour exactement ça (tokens.css). */
.registre .quand {
  font-size: var(--texte-12); color: var(--encre-2);
  font-variant-numeric: var(--chiffres-tabulaires);
  min-width: 42px; text-align: right;
}

/* LA COLONNE DE DROITE S'ENROULE plutôt qu'elle ne s'étire : date + état + ⋯ sur la première
   ligne, la sous-mention (« sans réponse depuis 32 j », « écarté par Nicolas le 16/07 ») sur la
   seconde, alignée à droite. Sur une seule ligne, une sous-mention longue poussait le ⋯ hors de
   son alignement d'une ligne à l'autre — et un geste dont la cible se déplace est un geste qu'on
   manque. La colonne n'a plus de largeur FIXE (220px avant) : elle prend ce que son contenu
   demande, bornée pour que le sujet garde la sienne. */
.registre .droite {
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center;
  gap: 4px 8px; max-width: 250px;
}
.registre .droite .sous-statut { flex-basis: 100%; text-align: right; }
.registre .gestes { display: flex; gap: 4px; flex-wrap: wrap; }

/* Le « ⋯ » de chaque ligne est sous le plancher WCAG 2.2 AA 2.5.8 (24 x 24 px) — R-D11, tâche 7.
   COMPOSANT registre, SÉLECTEUR .registre .gestes .btn.mini.

   C'est la cible la PLUS IMPORTANTE de cet écran, et son exposition a GRANDI à la tâche 6 : le « ⋯ »
   discret et permanent est devenu l'affordance UNIQUE des quatre gestes d'une ligne (Créer, Rattacher,
   Écarter, Remettre à trier — M-D12). Signalé aux tâches 5 et 6, non corrigé faute de scope.

   MESURÉ AU NAVIGATEUR (Chrome 151.0.7922.110, fenêtre 1440 px, CSS servi, page rendue hors
   application — même capture que ci-dessus) sur les trois « ⋯ » de la file : AVANT 27,05 x 18,67 px
   sur les trois, LARGEUR déjà conforme, HAUTEUR sous le plancher. Sonde de la cible RÉELLE —
   elementFromPoint au centre et aux MILIEUX DES QUATRE BORDS d'un carré de 24 x 24 centré sur le
   geste (.btn pose border-radius 6px ; un coin manqué mesurerait le rayon, pas la boîte englobante que
   2.5.8 définit) : AVANT centre/gauche/droite atteints, haut/bas MANQUÉS sur les trois. APRÈS
   24,67 x 27,05 px et les cinq points atteints sur les trois.

   MÊME BOÎTE DE DÉPART, MÊME CORRECTION QUE composants/boutons (.btn.mini sous .entete-dossier,
   .timeline, .lateral) : 18,67 px AVANT ici est EXACTEMENT le nombre déjà mesuré là-bas pour la même
   .btn.mini nue (padding 1px 8px, texte-115, ligne 1.45) dans un flex row — .registre .gestes en est
   un lui aussi. Les deux nombres ci-dessous (4px de padding, -3px de marge) ne sont donc pas
   inventés : ce sont ceux déjà audités par boutons.css pour cette même boîte, repris à l'identique
   plutôt que recalculés. 4px correspond au jeton --esp-1 ; -3px n'a pas de jeton (c'est une
   COMPENSATION dérivée de ce 4px et du 1px de padding d'origine, pas un choix d'espacement).
   PADDING + MARGE NÉGATIVE ET NON min-height, pour la raison déjà écrite côté boutons : .gestes est
   un flex, un min-height grandirait la boîte de MARGE et donc la hauteur de la ligne — le sujet et le
   statut à côté descendraient. Ici seule la boîte de PADDING (invisible au repos, .btn.discret pose
   border:none) grandit ; la boîte de marge reste 18,67 px avant et après, mesuré.

   POURQUOI DANS registre.css ET NON DANS LES QUATRE SÉLECTEURS DE boutons.css (le choix le plus
   proche) : cette correction naît de R-D11, la dette de CETTE tranche — pas de M-D11, le budget de la
   tranche « gestes en modales », clos à sept règles et déjà soldé. Le plan de cette tâche restreint
   l'écriture à design-system/composants/registre/registre.css, la source du composant qui POSSÈDE
   .gestes ; .timeline .quand donne déjà le précédent d'une correction scopée au composant qui porte
   le conteneur plutôt que centralisée dans boutons. Aucune règle de boutons.css n'est modifiée ; les
   quatre sélecteurs déjà corrigés là-bas ne bougent pas.

   CE QUI NE BOUGE PAS AILLEURS, VÉRIFIÉ À LA MESURE : .objet, .meta, .statut et le reste de .droite
   sont identiques en x/y avant/après sur les trois lignes de la fixture de mesure.
   AUCUN TEST NE PEUT VOIR CETTE RÈGLE : les tests lisent le HTML rendu, jamais le CSS appliqué ni la
   géométrie. */
.registre .gestes .btn.mini {
  padding-block: 4px;
  margin-block: -3px;
}

/* .onglet MESURÉ (R-D11, même navigateur/fenêtre) et non touché : 36,13 px de haut, 51 à 69 px de
   large selon le libellé — déjà au-dessus du plancher WCAG 24 x 24 grâce au padding vertical existant
   (7px/9px) et au border-bottom de 2px toujours réservé (actif ou non). Aucune règle à écrire ici. */

.registre .ia { border-top: none; padding-top: 0; } /* bloc-ia sans le filet — déjà dans une ligne */

.sous-statut { font-size: var(--texte-115); color: var(--encre-2); }

.pagination { text-align: center; color: var(--encre-2); font-size: var(--texte-12); margin-top: 10px; }
.pagination a { color: var(--accent-action); }

@media (max-width: 980px) {
  /* En étroit, la ligne redevient UNE colonne et les initiales disparaissent : elles servent à
     balayer une liste haute, et un écran étroit n'en montre que quelques lignes. Le nom de
     l'expéditeur, lui, reste — c'est l'information ; les initiales n'en étaient que le repère. */
  .registre .ligne { grid-template-columns: 1fr; }
  .registre .initiales { display: none; }
  .registre .droite { max-width: none; justify-content: flex-start; }
  .registre .droite .sous-statut { text-align: left; }
  .registre .quand { text-align: left; min-width: 0; }
  .onglets .outils { margin-left: 0; }
}

/* LA PAGINATION DU REGISTRE (R-D12) — une classe qui dit ce qu'elle est.
   COMPOSANT registre, SÉLECTEUR .registre-pages.

   CE QU'ELLE CORRIGE, et ce n'est pas un problème de rendu : la tâche 8 a habillé son <nav> de
   pagination avec « .modale-actions », faute de classe de pagination dans le design system — et elle
   l'a SIGNALÉ plutôt que d'écrire du CSS, parce que le volet design system lui était interdit. La
   règle de « .modale-actions » n'est pas scopée, donc l'affichage était juste. Deux choses ne
   l'étaient pas : le NOM, qui annonce une modale là où il n'y en a aucune — un lecteur cherchera un
   dialogue autour de ces deux liens ; et le COUPLAGE, qui faisait dépendre la place de la pagination
   du composant modale, si bien qu'un jour où l'on alignerait autrement les boutons d'un dialogue, les
   pages du registre auraient bougé avec eux.

   AUCUN CHANGEMENT VISUEL, et par construction : les cinq déclarations sont celles de
   « .modale-actions » (composant modale, ligne 37), reprises À L'IDENTIQUE. Il n'y avait donc rien à
   mesurer de nouveau — ce qui est mesurable ici, c'est que le rendu est le MÊME, et il l'est parce
   que les propriétés sont les mêmes. Ce n'est pas une retouche de mise en page déguisée en renommage.

   AUCUN TEST NE PEUT VOIR CETTE RÈGLE : les tests lisent le HTML rendu, jamais le CSS appliqué. Le
   changement de classe dans le gabarit, LUI, est visible d'un test — et c'est le seul des deux qui
   pouvait casser quelque chose. */
.registre-pages { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin-top: 10px; }

/* === stats-tuiles === */
/* Stats-tuiles — design system Syndic Ledger
   Le travail bénévole du CS rendu visible et factuel : bandeau de
   stats du portail public et du bilan du syndic (rapport à la
   demande). Chaque chiffre renvoie aux dossiers qui le composent
   (idee-generale.md § 5) — jamais une page de stats orpheline. */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin: 18px 0 6px;
}
.stat {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 14px 10px;
  text-align: center;
}
.stat strong {
  display: block;
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -.01em;
  font-variant-numeric: var(--chiffres-tabulaires);
}
.stat small { color: var(--encre-2); font-size: var(--texte-115); }

@media (max-width: 700px) { .stats { grid-template-columns: repeat(2, 1fr); } }

/* === stepper-reprise === */
/* Stepper de reprise — design system Syndic Ledger
   Le hub de l'assistant de reprise (S5) : parcours vertical, étape
   courante dépliée, suivantes verrouillées avec leur coût annoncé,
   avancement partagé entre membres. Construit depuis le wireframe
   de Phase 1 (docs/maquettes/2026-08-02-assistant-reprise.html) —
   aucun des 6 écrans déclinés n'en avait besoin. */

.stepper { display: flex; gap: 10px; padding: 14px 26px 0; max-width: 640px; }

/* le rail : points reliés par un trait — plein pour le fait, pointillé pour le verrouillé */
.stepper-rail {
  width: 14px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.rail-point { font-size: 13px; line-height: 1; }
.rail-point.fait { color: var(--accent-action); }
.rail-point.courant { color: var(--encre); font-weight: 700; font-size: 15px; }
.rail-point.verrou { color: var(--encre-2); }
.rail-trait { flex: 1; width: 0; min-height: 16px; border-left: 2px solid var(--trait-appuye); }
.rail-trait.verrouille { border-left-style: dotted; border-left-color: var(--trait-discret); }

.stepper-etapes { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }

.etape-faite { color: var(--encre-2); font-size: var(--texte-125); padding: 4px 0; }
.etape-faite strong { color: var(--encre); font-weight: 600; }

.etape-courante {
  border: 2px solid var(--encre);
  background: var(--surface-carte);
  border-radius: var(--rayon-carte);
  padding: 10px 12px;
  font-size: var(--texte-125);
}
.etape-courante .titre { font-weight: 700; }
.etape-courante .detail { margin-top: 4px; color: var(--encre-2); }
.etape-courante .partage { display: block; margin-top: 2px; font-size: var(--texte-115); color: var(--encre-2); }
.etape-courante .btn { margin-top: 8px; }

.etape-verrouillee { color: var(--encre-2); font-size: var(--texte-125); padding: 4px 0; opacity: .8; }
.etape-verrouillee strong { font-weight: 600; }

.stepper-pied {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--trait);
  font-size: var(--texte-115);
  color: var(--encre-2);
}
.stepper-pied strong { color: var(--encre); }

/* === table-suivi === */
/* Table de suivi — design system Syndic Ledger
   Une édition passée du point mensuel : le silence du syndic devient
   visible et actionnable. Le dispatch reste 100 % humain — la table
   aide, elle ne devine pas (idee-generale.md § 5). */

.table-suivi {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
}
.table-suivi .t-tete { padding: 11px 14px; border-bottom: 1px solid var(--trait); font-size: var(--texte-125); }
.table-suivi .t-tete strong { font-size: var(--texte-13); font-weight: 650; }
.table-suivi .t-tete .t-meta { color: var(--encre-2); }

.mails-edition { padding: 10px 14px; border-bottom: 1px solid var(--trait); font-size: var(--texte-12); color: var(--encre-2); }

.suivi-ligne {
  display: flex;
  gap: 9px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--trait);
  font-size: var(--texte-125);
  align-items: flex-start;
}
.suivi-ligne:last-child { border-bottom: none; }
.suivi-ligne .verdict { flex: none; width: 18px; text-align: center; }
.suivi-ligne .s-infos { flex: 1; min-width: 0; }
.suivi-ligne .s-reponse { color: var(--encre-2); }
.suivi-ligne .gestes { margin-top: 6px; display: flex; gap: 5px; flex-wrap: wrap; align-items: center; }

/* le silence passé sous silence : fond rosé en renfort — le ‼, le gras et
   le libellé portent l'information seuls (contrôlé AA au brief) */
.suivi-ligne.silence-ligne { background: var(--critique-fond); }
.suivi-ligne.silence-ligne .s-titre { color: var(--critique); }

/* === tableau-dense === */
/* Tableau dense — design system Syndic Ledger
   L'inventaire (page Dossiers), l'écrémage par expéditeur de
   l'assistant de reprise. Zéro gras de nouveauté, zéro zébrage —
   la densité et la hiérarchie typographique font le travail
   (même éthique anti-réflexe Gmail que le registre). */

.table-dense-cadre {
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  overflow: hidden;
  overflow-x: auto;
}
.table-dense {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface-carte);
  font-size: var(--texte-125);
}
.table-dense thead th {
  text-align: left;
  font-size: var(--texte-11);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--encre-2);
  padding: 8px 12px;
  border-bottom: 1px solid var(--trait);
  background: var(--surface-tonale);
  white-space: nowrap;
}
.table-dense thead th.triable { cursor: pointer; }
.table-dense thead th.triable .fleche { opacity: .5; margin-left: 3px; }
.table-dense thead th.triable.actif .fleche { opacity: 1; color: var(--accent-action); }
/* Aligné comme les cellules qu'il coiffe (.table-dense td.numerique) : un en-tête à gauche
   au-dessus d'une colonne de chiffres alignés à droite désaccorde visuellement le tableau. */
.table-dense thead th.numerique { text-align: right; }

.table-dense tbody td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--trait);
  color: var(--encre);
  vertical-align: middle;
}
.table-dense tbody tr:last-child td { border-bottom: none; }
.table-dense tbody tr:hover { background: var(--surface-survol); }
.table-dense tbody tr.selectionnee { background: var(--accent-fond); }
.table-dense td.numerique { font-variant-numeric: var(--chiffres-tabulaires); text-align: right; }
.table-dense td.checkbox { width: 32px; }
.table-dense td .titre { font-weight: 600; }
.table-dense td .sous-ligne { display: block; margin-top: 2px; font-size: var(--texte-11); color: var(--encre-2); }

/* === timeline === */
/* Timeline — design system Syndic Ledger
   Trois niveaux de lecture (idee-generale.md § 1) : la timeline
   raconte des JOURS, pas des mails ; dans un jour, les messages
   d'un même fil se regroupent en CARTE-ÉPISODE ; « voir le fil »
   ouvre la conversation entière (composant vue-fil, lot 4 aussi —
   composants/message). Notes, bascules d'état et silences restent
   des items simples du flux des jours. */

.timeline {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  margin: 0;
  padding: 0;
}

/* séparateur de jour — filet qui prolonge le libellé */
.timeline .jour {
  font-size: var(--texte-11);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--encre-2);
  margin: 10px 0 2px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.timeline .jour::after { content: ""; flex: 1; border-top: 1px solid var(--trait); }
.timeline .jour:first-child { margin-top: 0; }

/* LE JOUR RESTE VISIBLE PENDANT QU'ON DÉFILE (refonte du 2026-08-14).
   Un dossier de trois mois porte des dizaines d'événements. Les séparateurs de jour défilaient
   hors de l'écran et l'on perdait la date de ce qu'on lisait — c'est exactement là que commence
   le reproche « ça fait tableur » : une liste sans repère temporel visible.

   Le séparateur se colle en haut de la zone défilante tant que SON jour dure, et cède la place au
   suivant. Aucun script, aucun markup : position: sticky suffit, et il dégrade en statique sur un
   navigateur qui ne le connaît pas.

   LE FOND OPAQUE EST OBLIGATOIRE, pas décoratif : sans lui, le texte de l'événement qui passe
   dessous se superpose au libellé du jour et les deux deviennent illisibles. --surface-page et
   non --surface-carte : le séparateur vit sur le fond de page, entre les cartes d'événements.

   PADDING PLUTÔT QUE MARGIN EN HAUT : une marge laisse un couloir transparent au-dessus du
   libellé collé, par lequel on voit passer le texte. */
.timeline .jour {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-page);
  padding: 4px 0 2px;
}

/* item simple du flux des jours : note, bascule d'état, système */
.evt {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  padding: 10px 12px;
  box-shadow: var(--ombre-carte);
  font-size: var(--texte-125);
}
.evt .type {
  font-size: var(--texte-11, 10px);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--encre-2);
}
.evt .corps { margin-top: 4px; line-height: 1.5; }

/* L'heure d'un item se lit COMME CELLE D'UN MAIL — sixième règle de la tranche « gestes en
   modales » (M-D8, quatrième promotion de M-D11, accordée par le propriétaire ; la septième vit
   dans composants/boutons).

   CE QU'ELLE CORRIGE. « Rajouter l'heure sur chaque card comme c'est fait dans l'email » était la
   demande d'origine ; la tâche 7 a rendu l'heure, pas le « comme ». Mesuré au navigateur (Chrome
   151, fenêtre 1440 px, CSS servi, page rendue hors application) sur un dossier portant deux items
   simples et deux lignes de message : .quand tombait à font-size 12 px, chiffres PROPORTIONNELS,
   29,47 px d'avance pour « 23:11 » ; .msg-compact .heure à 11 px, tabular-nums, 31,31 px pour
   « 11:00 ». Ni la taille ni le gabarit de chiffres ne concordaient — deux tailles et deux avances
   dans la même colonne de lecture, et c'est exactement ce que la demande visait. Après : 11 px et
   tabular-nums des deux côtés, même avance, donc les chiffres d'un item et ceux d'un mail tombent
   sur la même grille.
   CE QU'ELLE NE CORRIGE PAS, ET C'EST MESURÉ : les deux colonnes ne partagent pas le même x, et
   aucune règle ne le leur donnera sans défaire le RETRAIT de la ligne de message. .quand part à
   275,00 px, .heure à 287,00 px — 12,00 px d'écart, qui sont exactement le « border-left: 2px » et
   le « padding-left: 10px » de .msg-compact ci-dessous. Ce retrait dit qu'un message appartient à
   son épisode (E-D6) ; l'effacer serait un choix de mise en page, pas l'alignement typographique
   qui était demandé. Chaque heure reste le premier item de SA ligne, à gauche.

   POURQUOI LE SCOPE, et ce n'est pas une précaution de style : .quand est une règle NON scopée du
   composant cartes (« .exp, .quand, .meta, .extrait ») et elle sert AILLEURS — les cartes de mail
   de composants/cartes et de composants/colonne-fenetre (« hier 16:42 »), où rien ne demande de
   tabular-nums, et .cloche-nouveaute .quand (composants/cloche-suivis), qui pose DÉJÀ 11 px et
   qu'une règle nue de même spécificité n'aurait pas battue de toute façon. Une règle nue aurait
   donc rapetissé des heures de carte pour aligner celles d'une timeline. Le scope est la timeline
   parce que c'est là que la colonne d'heures existe.
   AUCUN NOMBRE INVENTÉ : var(--texte-11) et var(--chiffres-tabulaires) sont les DEUX jetons que
   .msg-compact .heure consomme déjà, repris tels quels — la couleur, elle, était déjà commune
   (var(--encre-2), des deux côtés).
   AUCUN TEST NE PEUT VOIR CETTE RÈGLE : les tests lisent le HTML rendu, jamais le CSS appliqué. */
.timeline .quand {
  font-size: var(--texte-11);
  font-variant-numeric: var(--chiffres-tabulaires);
}

/* item système (création du dossier, cité dans le point de…) : discret, pointillé */
.evt.systeme {
  background: transparent;
  box-shadow: none;
  border-style: dashed;
  color: var(--encre-2);
}

/* le silence est un item — jamais une conversation */
.silence-item {
  text-align: center;
  color: var(--encre-2);
  font-size: var(--texte-115);
  font-variant-numeric: var(--chiffres-tabulaires);
  padding: 2px 0;
}

/* ---- carte-épisode : un fil, un jour, lignes horodatées dépliables ---- */
.evt.episode .tete-episode { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.fil-tab {
  background: var(--accent-fond);
  color: var(--accent-action);
  font-size: var(--texte-11, 10px);
  font-weight: 700;
  letter-spacing: .06em;
  border-radius: 4px;
  padding: 2px 6px;
  flex: none;
}
.evt.episode .tete-episode strong { font-weight: 600; font-size: var(--texte-13); }
.evt.episode .tete-episode .lien-fil { color: var(--encre-2); font-size: var(--texte-12); }
.evt.episode .tete-episode .lien-fil a { color: var(--accent-action); }

.msg-compact {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex-wrap: wrap;
  margin-top: 6px;
  padding-left: 10px;
  border-left: 2px solid var(--trait);
  line-height: 1.45;
}
.msg-compact .heure {
  font-size: var(--texte-11);
  color: var(--encre-2);
  font-variant-numeric: var(--chiffres-tabulaires);
  flex: none;
}
.msg-compact .deplier { font-size: var(--texte-115); color: var(--accent-action); }

/* Le bouton de geste d'une ligne s'aligne au bord DROIT de sa ligne.
   Cinquième règle de la tranche « gestes en modales » (M-D15, TROISIÈME promotion de M-D11 — ce
   commentaire disait « cinquième et DERNIÈRE » et « QUATRIÈME promotion », deux erreurs : le budget
   a reçu une quatrième promotion, celle de la section C, qui a ouvert les règles 6 ci-dessus et 7
   dans composants/boutons ; et les promotions étaient trois à ce moment-là, la spec disant « de
   deux à cinq, en trois fois »). Écrite sur un constat MESURÉ et remonté avant de l'être, comme les
   deux précédentes.

   CE QU'ELLE CORRIGE. M-D4 pariait : « aligné en colonne à droite, le ⋯ se lit comme une marge, pas
   comme une rangée de boutons ». Le pari a échoué à la mesure : les deux conteneurs ci-dessus sont
   des flex sans rien qui pousse leur dernier item, donc chaque ⋯ suit la fin de SA ligne et sa
   position dépend de la longueur du sujet. Vérification navigateur (Chrome 151, fenêtre 1440 px,
   CSS servi) : étendue de 292,86 px à la tâche 5 sur un dossier à trois épisodes, 747,08 px à la
   tâche 5 bis sur un dossier aux sujets de longueurs réalistes — dont un assez long pour que sa
   ligne passe à la ligne, envoyant son ⋯ à l'extrême GAUCHE, à 783,95 px du bord droit. Après cette
   règle : 0,00 px d'étendue, les six ⋯ du dossier de mesure au même x, à 13,00 px du bord droit de
   la colonne de contenu — c'est-à-dire au ras du bord intérieur de la carte-épisode
   (padding 12 px + bordure 1 px), et non un chiffre choisi.

   « margin-left: auto » PLUTÔT QUE justify-content SUR LE CONTENEUR : justify-content:space-between
   déplacerait TOUS les items de la ligne, l'heure et le texte compris. La marge automatique n'agit
   que sur l'item qui la porte, et c'est la forme que ce design system emploie déjà neuf fois pour
   ce besoin (.ligne-suivi .ne-plus-suivre, .nav-liens .compteur, .onglets .outils, .carte .referent,
   .portail-tete .maj…). Aucune valeur inventée : « auto » est un mot-clé, pas une mesure.

   LE SÉLECTEUR NOMME LA CLASSE DE L'ENFANT, JAMAIS SA POSITION, et c'est une mesure, pas un goût.
   « > :last-child » — la forme que le rapport de la tâche 5 proposait — atteint tout autre chose que
   le bouton dès qu'il n'y en a pas : dans le markup de RÉFÉRENCE de ce composant (timeline.html,
   preview.html, maquette-dossier-detail.html) le dernier enfant d'une .msg-compact est le <span> du
   corps du message, le lien « déplier » vivant DEDANS, et celui d'une .tete-episode est .lien-fil.
   Mesuré sur la preview de ce composant : le corps du message part de 91,31 px à 318,02 px, et
   .lien-fil jusqu'à +281,95 px. Mesuré sur l'écran d'un dossier portant un mail VERSÉ SEUL, où la
   garde viaThread supprime le ⋯ de l'en-tête : la phrase « mail versé seul, ce message uniquement ·
   voir le fil » quitte le sujet qu'elle qualifie de +210,22 px, alors qu'E-D6 existe pour qu'on la
   lise À CÔTÉ de lui. La même mesure donne Δ 0,00 px avec le sélecteur ci-dessous.

   LE COMBINATEUR D'ENFANT EST PORTEUR : une marge automatique ne fait quelque chose que sur un ITEM
   DE FLEX. Sur un .btn imbriqué plus profond — dans le <span> du corps, par exemple — elle
   pousserait le bouton à droite À L'INTÉRIEUR du span, ce que personne n'a demandé.

   CONSÉQUENCE ASSUMÉE ET MESURÉE SUR L'AUTRE CONSOMMATEUR : /fils réutilise .msg-compact et y met un
   <button class="btn mini">Verser ce mail</button>. Ses quatre boutons, étalés sur 504,36 px,
   s'alignent eux aussi (1330,28 px, Δ 0,00 px d'étendue). C'est le même rôle structurel — le geste
   d'une ligne de message — donc le même traitement, et l'éviter demanderait au design system de
   connaître un marqueur applicatif (data-modale) pour décider d'une mise en page : il n'emploie
   d'attribut nulle part ailleurs qu'input[type=…]. */
.msg-compact > .btn, .evt.episode .tete-episode > .btn { margin-left: auto; }

/* conséquence d'une bascule d'état, rattachée à un message d'épisode */
.consequence { margin-top: 6px; font-size: var(--texte-115); color: var(--encre-2); }
.consequence em { font-style: normal; font-weight: 600; }

/* Toute adresse rencontrée résout en fiche annuaire (indépendant de la source).

   LE POINTILLÉ DIT « CECI OUVRE UNE MODALE », et c'est la moitié d'une convention énoncée par le
   propriétaire le 2026-08-14 : teinte d'accent pour un lien qui OUVRE UNE PAGE, pointillé pour un
   lien qui OUVRE UNE MODALE sur place. Les deux formes se distinguent par la FORME autant que par
   la couleur — elles restent donc discernables l'une de l'autre sans percevoir le bleu, ce qui
   compte : l'utilisateur premier du produit est daltonien.

   Cette règle-ci existait AVANT la convention et s'y trouve conforme ; c'est l'autre moitié qui est
   écrite dans le composant en-tetes (« .lateral li a:not([data-modale]) »), avec le défaut qui a
   fait énoncer la règle — des liens de NAVIGATION habillés en pointillé, donc indiscernables des
   déclencheurs de modale voisins.

   LA TEINTE AU SURVOL SEULEMENT : au repos, une timeline qui nomme dix interlocuteurs se couvrirait
   d'accent, et l'accent est réservé à l'action (direction B). */
a.contact { text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
a.contact:hover { color: var(--accent-action); }

/* Bascule des gestes administratifs (E-D5) : masqués par défaut, révélés en CSS pur.
   Une case à cocher et un sélecteur de frère — ni htmx ni script, vérifié sur la maquette.
   La case est hors flux plutôt que display:none : un contrôle en display:none n'est pas
   focusable au clavier, et son <label> perdrait sa cible. Elle reste donc FOCUSABLE — mais
   opacity:0 efface aussi son contour de focus, ce qui n'est pas la même propriété : la
   VISIBILITÉ du focus est rendue plus bas, sur le plot, par :focus-visible (revue de la tâche 6,
   finding 5 — le commentaire d'origine revendiquait ici l'une en n'ayant préservé que l'autre,
   et l'accessibilité est une règle dure de ce produit).

   Le MASQUAGE est scopé sur le frère, exactement comme la révélation. Sans cette garde il
   frappait TOUTE .timeline du dépôt : les deux <li class="evt systeme"> de la preview de ce
   composant devenaient invisibles sans case pour les révéler — le composant ne documentait plus
   le troisième de ses trois genres d'item, juste sous le commentaire qui le décrit — et la
   timeline du point mensuel (T9) perdrait ses entrées sans qu'aucun test échoue (revue de la
   tâche 6, finding 2 : les tests lisent le HTML rendu, jamais le CSS appliqué).

   La révélation rend à CHAQUE genre le display qui est le sien, jamais un display uniforme :
   un <li class="evt systeme"> est un item de liste ; un <li class="jour systeme"> — l'en-tête
   d'un jour qui ne porte QUE des gestes (finding 3) — est le flex qui porte le filet de
   séparation de .timeline .jour, et le remettre en list-item lui ôterait ce filet. */
.bascule-gestes-case { position: absolute; opacity: 0; pointer-events: none; }
.bascule-gestes-case ~ .timeline .systeme { display: none; }
.bascule-gestes-case:checked ~ .timeline .evt.systeme { display: list-item; }
.bascule-gestes-case:checked ~ .timeline .jour.systeme { display: flex; }
.bascule-gestes-case:focus-visible ~ .toggle-ligne .toggle { outline: 2px solid var(--accent-action); outline-offset: 2px; }

/* L'état vide de la timeline est le MIROIR des gestes (finding 3) : un dossier qui ne porte
   encore ni correspondance ni note n'a QUE des gestes à montrer, et cocher la bascule les
   révèle — l'état vide n'a alors plus lieu d'être. La règle vit ici et non dans
   composants/etats-vides parce qu'elle est ancrée sur .bascule-gestes-case, qui appartient à
   ce composant : hors de ce voisinage elle ne peut atteindre aucun .etat-vide du dépôt. */
.bascule-gestes-case:checked ~ .etat-vide { display: none; }

/* Le plot de .toggle doit rester LISIBLE, pas seulement fonctionnel (règle du composant
   toggle) : sans ces deux règles, la case cochée révèle les gestes mais son propre interrupteur
   reste figé — un switch qui ne bouge jamais se lit comme cassé. .toggle et .toggle.actif
   (composants/formulaires) n'offrent aucune règle atteignable depuis :checked : .actif n'existe
   que pour un <button> commuté en script, ce que la bascule pure CSS de ce composant n'a pas.
   Ce couple reprend les MÊMES valeurs que .toggle.actif, par le sélecteur de frère plutôt qu'une
   teinte ou un déplacement inventés ici, pour ne jamais diverger du seul état "actif" que le
   design system connaît. */
.bascule-gestes-case:checked ~ .toggle-ligne .toggle { background: var(--accent-action); }
.bascule-gestes-case:checked ~ .toggle-ligne .toggle::after { transform: translateX(14px); }

/* === vignette-piece === */
/* Vignette-pièce — design system Syndic Ledger
   La vue Pièces globale : toutes pièces, tous dossiers, avec
   étiquette métier (devis, facture, rapport, photo…) posée à la
   main ou proposée par l'IA, et filtres par origine
   (idee-generale.md § 1). L'étiquette métier réutilise .badge
   (composants/badges) — pas de nouvelle classe de badge. */

.grille-pieces {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 10px;
}
.vignette-piece {
  background: var(--surface-carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
}
.vignette-piece .vp-icone { font-size: 22px; }
.vignette-piece .vp-nom {
  font-weight: 600;
  font-size: var(--texte-125);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vignette-piece .vp-meta { font-size: var(--texte-11); color: var(--encre-2); }
.vignette-piece .vp-badges { display: flex; gap: 4px; flex-wrap: wrap; }
.vignette-piece .vp-suggestion { font-size: var(--texte-11); color: var(--encre-2); }
