/* MARVIA — design system AS3P (STORY-108, charte à la lettre).
   Source de vérité : docs/new-ux/braindup-ingestion-suivi.html (<style> L7-341).
   Sous-ensemble RÉUTILISABLE : jetons + reset + focus + composants génériques.
   Shell (.app/.side/.nav/.main) = STORY-109 ; classes d'écran = épics 024+.
   Souverain : 100 % auto-heberge, aucune URL externe, aucune police distante. */

:root{
  --cyan:#008EAA; --teal:#004F59; --noir:#002B30;
  /* ⚠️ VARIANTE DE TEXTE du cyan — le jeton de MARQUE ne bouge pas. `--cyan` vaut
     3,85:1 sur blanc, sous le seuil AA (4,5) : il reste l'accent (bordures, fonds,
     filets, pastilles), mais il ne porte plus de petit texte. Valeur prise dans la
     CHARTE (`--teal`, 9,28:1) plutôt qu'inventée : introduire une couleur neuve
     serait un acte de charte. Indirection délibérée — basculer sur un cyan assombri
     (`#00819B` 4,55 · `#007C94` 4,87) est UNE ligne, mais NON NEUTRE : sur `--pale`,
     `#007C94` vaut 3,53 et `.badge` resterait en dette. */
  --cyan-txt:var(--teal);
  --pale:#C3E1E5; --cta:#FFA400; --blanc:#FFFFFF;
  --gris-bg:#F3F6F7; --gris-bord:#E1E8EA; --gris-txt:#5B6B6E;
  --ls:0.025em;
  --font:Arial,Helvetica,sans-serif;
  --ok:var(--cyan); --run:#0AA9C7; --wait:#9AAAAD;
  /* ⚠️ Jetons d'INSTANCE (STORY-260, AD-O6) — le SEUL jeu surchargeable par
     l'identité. Défaut = la charte : une instance sans couleur rend l'interface
     BIT-À-BIT identique à aujourd'hui. Ne JAMAIS y recopier #008EAA/#FFA400 :
     les variables ci-dessus sont l'unique vérité, les recopier en créerait une
     seconde, divergente au premier changement de charte. */
  --instance-primary:var(--cyan); --instance-accent:var(--cta);
  /* Familles de types du graphe (STORY-296, arbitrage JMA du 2026-08-12) — DEUX
     teintes AJOUTEES a la charte de marque, parce que cinq familles ne se
     distinguent pas avec trois couleurs. Le mauve est celui de la maquette
     (source de verite, braindup-ingestion-suivi.html) : il etait employe SANS
     etre declare, c est ce defaut-la que la sentinelle avait attrape.
     ⚠️ L orange n est PAS --cta : #FFA400 est l anneau de selection
     (.mg-node:focus/.sel), et un remplissage de la meme teinte rendrait la
     selection INVISIBLE — garde par test_css_charte_graphe.py. */
  --type-objet:#7F35B2; --type-organisation:#D2691E;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--font); color:var(--noir);
  background:var(--gris-bg); font-size:14px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
:focus-visible{outline:3px solid var(--cta); outline-offset:2px; border-radius:4px}

/* ---------- BADGE ---------- */
.badge{display:inline-block; font-size:11px; font-weight:700; letter-spacing:var(--ls);
  color:var(--cyan-txt); background:var(--pale); padding:3px 9px; border-radius:20px; vertical-align:middle; margin-left:8px}

/* ---------- CARTE ---------- */
.card{background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px; padding:18px}
.card h2{margin:0 0 4px; font-size:15px; letter-spacing:var(--ls); color:var(--teal)}
.card .hint{font-size:12px; color:var(--gris-txt); margin:0 0 14px}

/* ---------- Cartes de sources + zone de dépôt (STORY-118, maquette à la lettre) ---------- */
.sources{display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-bottom:26px}
.drop{border:2px dashed var(--cyan); border-radius:12px; background:#F5FBFC; padding:26px 16px; text-align:center; cursor:pointer; transition:background .15s,border-color .15s}
.drop:hover,.drop.over{background:var(--pale); border-color:var(--teal)}
.drop .big{font-size:15px; font-weight:700; letter-spacing:var(--ls); color:var(--teal)}
.drop .small{font-size:12px; color:var(--gris-txt); margin-top:4px}
.drop .plus{font-size:30px; color:var(--cyan-txt); line-height:1; margin-bottom:8px}
.demo{all:unset; cursor:pointer; display:inline-block; margin-top:12px; font-size:12px; color:var(--cyan-txt); font-weight:700; letter-spacing:var(--ls); text-decoration:underline}
/* Carte web : URL + options avancées repliées (STORY-119, maquette à la lettre) */
.url-row{display:flex; gap:8px}
.url-row input{flex:1; padding:11px 12px; border:1px solid var(--gris-bord); border-radius:9px; font-family:var(--font); font-size:13.5px; color:var(--noir)}
.url-row input:focus{border-color:var(--cyan); outline:none; box-shadow:0 0 0 3px rgba(0,142,170,.15)}
.adv{margin-top:12px; font-size:12px}
.adv summary{cursor:pointer; color:var(--cyan-txt); font-weight:700; letter-spacing:var(--ls); list-style:none}
.adv summary::-webkit-details-marker{display:none}
.adv summary::before{content:"▸ "}
.adv[open] summary::before{content:"▾ "}
.adv .defaults{margin-top:10px; background:var(--gris-bg); border:1px solid var(--gris-bord); border-radius:9px; padding:10px 12px; color:var(--gris-txt)}
.adv .defaults div{display:flex; justify-content:space-between; padding:3px 0}
.adv .defaults b{color:var(--teal); font-weight:700}
/* ---------- Suivi en direct : compteurs, lignes, journal (STORY-120, à la lettre) ---------- */
.suivi-head{display:flex; align-items:baseline; justify-content:space-between; margin-bottom:12px; flex-wrap:wrap; gap:8px; margin-top:26px}
.suivi-head h2{margin:0; font-size:17px; letter-spacing:var(--ls); color:var(--teal)}
.counts{display:flex; gap:8px}
.empty{background:var(--blanc); border:1px dashed var(--gris-bord); border-radius:14px; padding:40px 20px; text-align:center; color:var(--gris-txt)}
.empty .e-t{font-size:15px; font-weight:700; color:var(--teal); letter-spacing:var(--ls); margin-bottom:4px}
.list{display:flex; flex-direction:column; gap:12px}
.item{background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px; padding:14px 16px 12px; animation:pop .25s ease}
.item-top{display:flex; align-items:flex-start; gap:12px}
.ftype{width:34px; height:34px; flex:none; border-radius:9px; display:grid; place-items:center; background:var(--pale); color:var(--teal); font-size:16px; font-weight:700}
.ftype.web{background:#E9E3F5; color:#5B2E8F}
.fmeta{flex:1; min-width:0}
.fname{font-weight:700; letter-spacing:var(--ls); font-size:14px; color:var(--noir); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.ftitle{font-size:12.5px; color:var(--cyan-txt); margin-top:2px; min-height:17px; transition:opacity .3s}
.ftitle.wait{color:var(--gris-txt); font-style:italic}
.fsource{font-size:12px; color:var(--gris-txt); margin-top:2px}
.fstatus{flex:none; text-align:right; font-size:11.5px; min-width:132px}
.fstatus .st{font-weight:700; letter-spacing:var(--ls)}
.fstatus .st.run{color:var(--run)} .fstatus .st.done{color:var(--cyan-txt)} .fstatus .st.q{color:var(--gris-txt)}
.fstatus .ts{color:var(--gris-txt); margin-top:2px}
.audit-link{all:unset; cursor:pointer; color:var(--cyan-txt); text-decoration:underline; font-size:11.5px; font-weight:700; letter-spacing:var(--ls)}
/* PDF liés imbriqués (STORY-126, EPIC-025) — patron EXACT maquette docs/new-ux, §PDF liés. */
.children{margin:10px 0 2px 46px; padding-left:14px; border-left:2px solid var(--pale); display:flex; flex-direction:column; gap:8px}
.ch-head{font-size:11px; color:var(--gris-txt); letter-spacing:var(--ls)}
.item.sub{padding:10px 12px; border-style:dashed; background:#FAFCFD}
.item.sub .ftype{width:28px; height:28px; font-size:11px}
.item.sub .fname{font-size:13px}
.sub-tag{display:inline-block; font-size:9.5px; font-weight:700; letter-spacing:var(--ls); color:var(--teal); background:var(--pale); border-radius:10px; padding:1px 7px; margin-left:6px; vertical-align:middle}
.journal{margin-top:24px; background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px; overflow:hidden}
.journal summary{cursor:pointer; padding:13px 16px; font-weight:700; letter-spacing:var(--ls); color:var(--teal); list-style:none; display:flex; align-items:center; gap:8px}
.journal summary::-webkit-details-marker{display:none}
.journal summary::before{content:"▸"; color:var(--cyan-txt)}
.journal[open] summary::before{content:"▾"}
.journal .log{border-top:1px solid var(--gris-bord); max-height:230px; overflow:auto; padding:6px 0}
.logline{display:flex; gap:12px; padding:5px 16px; font-size:12px; border-bottom:1px solid #F0F4F5}
.logline:last-child{border-bottom:none}
.logline .t{color:var(--gris-txt); flex:none; font-variant-numeric:tabular-nums}
.logline .m b{color:var(--teal)}
.log-empty{padding:14px 16px; color:var(--gris-txt); font-size:12px}
/* ---------- Tableau Audit du corpus (STORY-121, maquette à la lettre) ---------- */
.audit-stat{display:flex; gap:22px; flex-wrap:wrap; background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px; padding:16px 20px; margin-bottom:20px}
.audit-stat .s .n{font-size:22px; font-weight:700; color:var(--cyan-txt); letter-spacing:var(--ls)}
.audit-stat .s .l{font-size:11.5px; color:var(--gris-txt); letter-spacing:var(--ls)}
.audit-search{margin-bottom:14px}
.audit-search input{width:100%; max-width:360px; padding:10px 12px; border:1px solid var(--gris-bord); border-radius:9px; font-family:var(--font); font-size:13.5px}
.audit-search input:focus{border-color:var(--cyan); outline:none; box-shadow:0 0 0 3px rgba(0,142,170,.15)}
/* Sélecteurs SCOPÉS sous .audit-table (CR : pas de fuite de style vers d'autres
   tables/tags MARVIA — EPIC-025→030 auront leurs propres tables). */
.audit-table{overflow-x:auto}  /* défilement horizontal en petit écran (STORY-113) */
/* Disposition FIXE : la table ne dépasse jamais sa zone — les colonnes de données
   ont une largeur propre et le Titre absorbe le reste (large sur grand écran,
   tronqué à l'ellipse sur petit). Supprime le défilement horizontal qui reléguait
   la colonne Actions hors de vue. */
.audit-table table{width:100%; table-layout:fixed; border-collapse:collapse; background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px; overflow:hidden}
/* Plancher porté par la TABLE (en disposition fixe, `min-width` sur une cellule
   est ignoré) : 830px de colonnes de données + ~150px de titre lisible. Sous
   ~1100px, `overflow-x:auto` reprend la main plutôt que d'écraser le titre. */
.audit-table table{min-width:980px}
/* Largeurs par ATTRIBUT, pas par position (STORY-178). L'épic prescrivait de décaler
   `nth-child(2..10)` en `(3..11)` pour la colonne de sélection, avec un `:has()` ou une
   classe pour le cas sans `can_remove`. Les sélecteurs d'attribut rendent le CSS
   IMMUNISÉ à toute insertion de colonne — présente ou future — et suppriment le besoin
   de maintenir deux jeux de règles selon la capacité. Les neuf colonnes à largeur
   portent toutes un `data-sort` ; Actions n'en a pas et n'a pas de largeur. */
.audit-table thead th[data-sort="source"]{width:120px}   /* Source */
.audit-table thead th[data-sort="type"]{width:70px}    /* Type */
.audit-table thead th[data-sort="date"]{width:105px}   /* Date d'ingestion */
.audit-table thead th[data-sort="chunks"]{width:80px}    /* Chunks */
.audit-table thead th[data-sort="entites"]{width:80px}    /* Entités */
.audit-table thead th[data-sort="pages"]{width:85px}    /* Nombre de pages */
.audit-table thead th[data-sort="duree"]{width:100px}   /* Temps d'ingestion */
.audit-table thead th[data-sort="statut"]{width:80px}    /* Statut */
.audit-table thead th.act-col{width:110px}        /* Actions (capacité REMOVE/CRUD) */
/* Source peut être longue (nom de domaine) : ellipse plutôt que débordement. */
.audit-table tbody td.fn{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.audit-table thead th{text-align:left; font-size:11px; letter-spacing:var(--ls); text-transform:uppercase; color:var(--gris-txt); background:var(--gris-bg); padding:11px 14px; border-bottom:1px solid var(--gris-bord)}
/* En-têtes triables (#8) + lignes ouvrables (#9) — curseurs explicites. */
/* Les libellés d'en-tête peuvent revenir à la ligne : en `nowrap`, « Date
   d'ingestion » / « Nombre de pages » / « Temps d'ingestion » imposaient ~140px
   à des colonnes dont la donnée tient en ~70px, poussant la dernière colonne
   (Actions) hors écran. Le tri reste cliquable à l'identique. */
.audit-table thead th[data-sort]{cursor:pointer; user-select:none}
/* Le titre absorbe l'espace restant (disposition fixe) ; au-delà, ellipse — le
   libellé complet reste lisible en infobulle (attribut `title` posé par le JS).
   ⚠️ Ciblé par CLASSE, plus par `td:first-child` (STORY-178) : la colonne de sélection
   passe devant quand `can_remove` est détenue, et l'ellipse serait alors appliquée à la
   case à cocher au lieu du titre — un défaut visible uniquement pour les curateurs. */
.audit-table tbody td.ttl-col{overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
/* Sort d'une ligne après une suppression MULTIPLE (STORY-180) : la ligne qui a résisté
   reste à l'écran, cochée — encore faut-il la VOIR et savoir quoi en faire (le `title`
   posé par le JS porte l'action). Trois causes, trois remèdes : un `refused` s'annule,
   un `partial_failure` se rejoue, un `not_found` ne demande rien. */
.audit-table tbody tr[data-batch-status] td{background:#FFF6E5}
.audit-table tbody tr[data-batch-status="partial_failure"] td{background:#FDEBEC}
.audit-table tbody tr[data-batch-status] td:first-child{box-shadow:inset 3px 0 0 #E2A03F}
.audit-table tbody tr[data-batch-status="partial_failure"] td:first-child{
  box-shadow:inset 3px 0 0 #C0392B}
/* Aperçu du lot dans la modale de purge (STORY-180) — sous le nom de la ligne. */
.purge-target{font-weight:700; color:var(--noir)}
.audit-table thead th[data-sort]:hover{color:var(--cyan-txt)}
.audit-table thead th[data-sort]:focus-visible{outline:2px solid var(--cyan); outline-offset:-2px}
.audit-table thead th[aria-sort="ascending"],.audit-table thead th[aria-sort="descending"]{color:var(--cyan-txt)}
.audit-table thead th .sort-ind{font-size:9px; margin-left:2px}
.audit-table tbody tr[data-doc-id]{cursor:pointer}
.audit-table tbody tr[data-doc-id]:hover td{background:var(--pale)}
.audit-table tbody td{padding:12px 14px; border-bottom:1px solid #EEF3F4; font-size:13px; vertical-align:top}
.audit-table tbody tr:last-child td{border-bottom:none}
.audit-table tbody tr.fresh{animation:flash 1.4s ease}
@keyframes flash{0%{background:#EAF9FC} 100%{background:transparent}}
.audit-table td .ttl{font-weight:700; color:var(--noir); letter-spacing:.01em}
.audit-table td .fn{color:var(--gris-txt); font-size:12px}
.audit-table td .batch{font-size:11px; color:var(--cyan-txt); font-weight:700; letter-spacing:var(--ls); margin-top:3px}
.audit-table .tag{font-size:10.5px; font-weight:700; letter-spacing:var(--ls); padding:2px 8px; border-radius:14px}
.audit-table .tag.pdf{color:var(--teal); background:var(--pale)}
.audit-table .tag.web{color:#5B2E8F; background:#E9E3F5}
.audit-table .tag.ok{color:var(--blanc); background:var(--cyan)}
.audit-table .num{font-variant-numeric:tabular-nums; color:var(--teal); font-weight:700}
/* Toasts (.toasts/.toast/@keyframes pop) : DÉJÀ définis plus bas — ne pas dupliquer (CR). */

/* ---------- CHAMP ---------- */
.field{margin-bottom:14px}
.field label{display:block; font-size:12.5px; font-weight:700; letter-spacing:var(--ls); color:var(--teal); margin-bottom:5px}
.field .req{color:#C0392B}
.field input{width:100%; padding:10px 12px; border:1px solid var(--gris-bord); border-radius:9px; font-family:var(--font); font-size:13.5px}
.field input:focus{border-color:var(--cyan); outline:none; box-shadow:0 0 0 3px rgba(0,142,170,.15)}
.field.invalid input{border-color:#C0392B; box-shadow:0 0 0 3px rgba(192,57,43,.12)}
.field-err{display:none; font-size:11.5px; color:#C0392B; margin-top:5px}
.field.invalid .field-err{display:block}
.field.shake{animation:shake .3s}
@keyframes shake{0%,100%{transform:translateX(0)} 25%{transform:translateX(-5px)} 75%{transform:translateX(5px)}}

/* ---------- BOUTON CTA ---------- */
.btn-cta{
  all:unset; cursor:pointer; background:var(--instance-accent); color:var(--noir); font-weight:700;
  letter-spacing:var(--ls); font-size:13.5px; padding:11px 16px; border-radius:9px; white-space:nowrap;
}
.btn-cta:hover{filter:brightness(.96)}
.btn-cta:active{transform:translateY(1px)}

/* ---------- BOUTON DANGER (purge, Task 9) ---------- */
.btn-danger{background:#c0392b;color:#fff;border:0;border-radius:8px;
  padding:8px 14px;font-weight:600;cursor:pointer}
.btn-danger:disabled{opacity:.45;cursor:not-allowed}
.row-act{font-size:.78rem;padding:3px 8px;border-radius:6px;cursor:pointer;
  border:1px solid var(--line,#d5d9e0);background:transparent}
.row-act.danger{color:#c0392b;border-color:#c0392b}

/* ---------- PILL ---------- */
.pill{font-size:11.5px; font-weight:700; letter-spacing:var(--ls); padding:4px 11px; border-radius:20px; border:1px solid transparent}
.pill.q{color:var(--gris-txt); background:var(--gris-bg); border-color:var(--gris-bord)}
.pill.r{color:#06697C; background:#E3F5F9; border-color:#BEE8F0}
.pill.d{color:var(--blanc); background:var(--cyan)}
.pill.dup{color:#886C00; background:#FBF3D6; border-color:#F0E2A8}

/* ---------- apparition générique (modale, toast) ---------- */
@keyframes pop{from{opacity:0; transform:translateY(6px)} to{opacity:1; transform:none}}

/* ---------- STEPPER (jalons) ---------- */
.steps{display:flex; align-items:center; margin-top:12px; padding:0 2px}
.step{display:flex; align-items:center; flex:1}
.step:last-child{flex:none}
.dot{width:22px; height:22px; border-radius:50%; flex:none; display:grid; place-items:center;
  background:var(--gris-bg); border:2px solid var(--gris-bord); color:var(--wait);
  font-size:11px; font-weight:700; position:relative; cursor:default}
.dot.done{background:var(--cyan); border-color:var(--cyan); color:var(--blanc)}
.dot.active{border-color:var(--run); color:var(--run); background:#EAF9FC; animation:pulse 1.1s infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(10,169,199,.45)} 50%{box-shadow:0 0 0 6px rgba(10,169,199,0)}}
.bar{flex:1; height:3px; background:var(--gris-bord); margin:0 4px; border-radius:2px; overflow:hidden; position:relative}
.bar>i{position:absolute; inset:0; width:0; background:var(--cyan); transition:width .5s ease}
.steplabels{display:flex; margin-top:5px; padding:0 2px}
.steplabels span{flex:1; font-size:10px; color:var(--gris-txt); letter-spacing:.01em}
.steplabels span:last-child{flex:none; text-align:right; width:44px}
.dot .tip{visibility:hidden; opacity:0; position:absolute; bottom:130%; left:50%; transform:translateX(-50%);
  background:var(--noir); color:var(--blanc); font-size:11px; font-weight:400; letter-spacing:normal;
  padding:7px 9px; border-radius:7px; width:190px; z-index:5; transition:opacity .15s; line-height:1.4; text-align:left}
.dot:hover .tip{visibility:visible; opacity:1}

/* ---------- TOAST ---------- */
.toasts{position:fixed; right:20px; bottom:20px; display:flex; flex-direction:column; gap:8px; z-index:50}
.toast{background:var(--teal); color:var(--blanc); padding:11px 15px; border-radius:10px; font-size:13px;
  letter-spacing:var(--ls); box-shadow:0 6px 20px rgba(0,43,48,.25); animation:pop .25s ease; max-width:300px}
.toast b{color:var(--pale)}

/* ---------- MODALE (coquille générique ; contenu « À propos » = STORY-110) ---------- */
.modal-overlay{position:fixed; inset:0; background:rgba(0,43,48,.55); display:none; align-items:center; justify-content:center; padding:20px; z-index:80}
.modal-overlay.show{display:flex; animation:pop .2s ease}
.modal{background:var(--blanc); border-radius:16px; max-width:560px; width:100%; max-height:90vh; overflow:auto; position:relative; box-shadow:0 20px 60px rgba(0,43,48,.35)}
.modal-close{position:absolute; top:12px; right:12px; z-index:2; all:unset; cursor:pointer; width:32px; height:32px; border-radius:50%; background:rgba(255,255,255,.9); color:var(--teal); font-size:20px; line-height:32px; text-align:center; font-weight:700}
.modal-close:hover{background:var(--gris-bg); color:var(--cyan-txt)}
.modal-close:focus-visible{outline:3px solid var(--cta); outline-offset:2px}
.modal-body{padding:22px 24px 26px}
.modal-body p{margin:0 0 12px; line-height:1.65; color:var(--noir); font-size:14px}
.modal-body p b{color:var(--teal)}

/* ---------- Mouvement réduit (accessibilité, base — complétée STORY-114) ---------- */
@media (prefers-reduced-motion:reduce){
  *{animation:none !important; transition:none !important}
}

/* ========== SHELL (STORY-109) — ossature ; identité=110, pied=111, responsive=113 ========== */
.app{display:grid; grid-template-columns:236px 1fr; min-height:100vh}
.side{background:var(--teal); color:var(--blanc); display:flex; flex-direction:column; padding:20px 14px}
.brand{display:flex; align-items:center; gap:10px; padding:6px 6px 18px}
.nav{display:flex; flex-direction:column; gap:2px; margin-top:6px}
.nav button{
  all:unset; cursor:pointer; display:flex; align-items:center; gap:10px;
  padding:10px 12px; border-radius:9px; color:#DDEDEF; font-size:13.5px;
  letter-spacing:var(--ls); transition:background .15s;
}
.nav button .ico{width:17px; text-align:center; opacity:.9}
.nav button:hover{background:rgba(255,255,255,.08)}
.nav button.active{background:var(--instance-primary); color:var(--blanc); font-weight:700}
/* Zone principale FLUIDE : occupe toute la largeur de la fenêtre (moins la barre
   latérale). L'ancienne borne `max-width:1180px` reléguait les dernières colonnes
   des tableaux larges (Audit : 10 colonnes, dont Actions) derrière un défilement
   horizontal peu intuitif — une action destructive ne doit pas être hors écran.
   Les blocs sensibles à la lisibilité gardent leur propre borne (`.head p`,
   `.ms-answer-text`, `.mg-controls`) — Réglages n'en fait PAS partie : il n'y a
   aucune ligne de prose à y protéger, seulement des cartes de contrôles. */
.main{padding:26px 30px 60px; min-width:0}
.head h1{font-size:26px; letter-spacing:var(--ls); margin:0 0 4px; color:var(--teal)}
.head p{margin:0 0 22px; color:var(--gris-txt); max-width:720px}
.view{display:none}
.view.show{display:block}

/* ========== IDENTITÉ + MODALE À PROPOS (STORY-110) — à la lettre maquette ========== */
.brand{cursor:pointer; border-radius:10px; transition:background .15s}
.brand:hover{background:rgba(255,255,255,.08)}
.brand:focus-visible{outline:3px solid var(--cta); outline-offset:2px}
.brand-logo{width:42px; height:42px; border-radius:50%; object-fit:cover; display:block}
.brand .nm{font-weight:700; letter-spacing:var(--ls); font-size:16px; line-height:1.1}
.brand .sub{font-size:10.5px; color:var(--pale); letter-spacing:var(--ls)}
.about-img{width:100%; height:auto; display:block; border-radius:16px 16px 0 0}
.about-title{font-size:22px; letter-spacing:var(--ls); color:var(--teal); margin:0 0 12px}

/* ========== PIED BrainDup by AS3P (STORY-111) — à la lettre maquette ========== */
.side .foot{margin-top:auto; font-size:10.5px; color:var(--pale); letter-spacing:var(--ls); padding:12px 8px 2px; line-height:1.55}
/* Logo centré dans la largeur du bandeau. ⚠️ `text-align` sur le pied serait
   sans effet : l'image est en `display:block`, donc c'est la marge automatique
   qui la centre — et le texte, lui, reste aligné à gauche pour rester lisible. */
.bd-logo{width:118px; height:auto; display:block; margin:0 auto 10px}
/* ⚠️ Le lien du logo est un BLOC, pas un `inline-block`. En inline-block, le
   `<span>` qui suit coule sur la MÊME ligne — « Propulsé par BrainDup by AS3P »
   se retrouvait à DROITE du logo au lieu d'être dessous, et l'image en
   `display:block` à l'intérieur ne changeait rien : c'est la boîte du lien qui
   décide de la ligne, pas son contenu. Un `<br>` dans le gabarit n'y aurait rien
   fait non plus, pour la même raison. */
.foot a.bd-link{display:block}
.foot a{color:var(--pale); text-decoration:underline; text-underline-offset:2px}
.foot a:hover{color:var(--blanc)}

/* ========== RESPONSIVE 860px — shell (STORY-113) ; écrans .sources/.graph/.settings = 024/028/029 ========== */
@media (max-width:860px){
  .app{grid-template-columns:1fr}
  .side{flex-direction:row; align-items:center; padding:12px; overflow-x:auto}
  .brand{padding:0 14px 0 4px}
  .nav{flex-direction:row; margin:0}
  .side .foot{display:none}
  .main{padding:20px 16px 50px}
  .sources{grid-template-columns:1fr}  /* cartes empilées (STORY-118) */
}

/* ============================================================
   Écran Recherche (GraphRAG) — STORY-134/135 (EPIC-027).
   Styles créés ex nihilo (134 n'avait livré aucun .ms-*).
   ============================================================ */
.ms-bar{display:flex; gap:10px; margin:6px 0 12px}
.ms-bar input{flex:1; border:1px solid var(--gris-bord); border-radius:12px;
  padding:12px 15px; font-size:14px; background:var(--blanc); color:var(--noir)}
.ms-bar input:focus{outline:2px solid var(--cyan); outline-offset:1px}
/* ---------- PANNEAU DE PARAMÈTRES (STORY-212) ----------
   ⚠️ « Paramètres » est SECONDAIRE : deux boutons orange côte à côte détruiraient la
   hiérarchie de la charte (§ 7.1) — le CTA orange reste unique sur l'écran. */
.btn-param{all:unset; cursor:pointer; border:1px solid var(--gris-bord); background:var(--blanc);
  color:var(--teal); font-weight:700; letter-spacing:var(--ls); font-size:13.5px;
  padding:10px 15px; border-radius:9px; white-space:nowrap; display:inline-flex;
  align-items:center; gap:8px}
.btn-param:hover{background:var(--pale); border-color:var(--teal)}
.btn-param .caret{font-size:10px; transition:transform .15s}
.btn-param[aria-expanded="true"] .caret{transform:rotate(180deg)}
.btn-param .dot{width:7px; height:7px; border-radius:50%; background:var(--cta); display:none}
.btn-param.modified .dot{display:block}
/* État visible SANS ouvrir le panneau (UX-DR2). */
.ms-params-state{display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin:0 0 12px}
.ms-params-state[hidden]{display:none}
.ms-params-state .lab{font-size:11.5px; color:var(--gris-txt); letter-spacing:var(--ls)}
.ms-params-state .pill{border:1px solid var(--pale); background:#F0F9FA; color:var(--teal);
  border-radius:20px; padding:4px 11px; font-size:12px; font-weight:700; letter-spacing:var(--ls)}
.ms-params{background:var(--blanc); border:1px solid var(--gris-bord); border-radius:14px;
  padding:16px 18px; margin:0 0 16px}
.ms-params[hidden]{display:none}
.ms-params-grid{display:grid; gap:20px; grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.ms-params fieldset{border:0; margin:0; padding:0; min-width:0}
.ms-params legend{padding:0; margin:0 0 8px; font-size:12.5px; font-weight:700;
  letter-spacing:var(--ls); color:var(--teal)}
.ms-seg{display:flex; border:1px solid var(--gris-bord); border-radius:9px; overflow:hidden;
  background:var(--blanc)}
.ms-seg label{flex:1; min-width:0; position:relative}
.ms-seg input{position:absolute; opacity:0; width:1px; height:1px}
.ms-seg .opt{display:block; text-align:center; padding:9px 8px; font-size:13px; cursor:pointer;
  color:var(--teal); letter-spacing:var(--ls); transition:background .13s,color .13s}
.ms-seg label + label .opt{border-left:1px solid var(--gris-bord)}
.ms-seg .opt:hover{background:var(--gris-bg)}
.ms-seg input:checked + .opt{background:var(--cyan); color:var(--blanc); font-weight:700}
.ms-seg input:focus-visible + .opt{outline:3px solid var(--cta); outline-offset:-3px}
.ms-params .why{font-size:11.5px; color:var(--gris-txt); margin:7px 0 0; min-height:15px;
  letter-spacing:var(--ls)}
.ms-params .why.slow{color:#9A6100; font-weight:700}
.ms-params-foot{display:flex; justify-content:space-between; align-items:center; gap:12px;
  flex-wrap:wrap; margin-top:16px; padding-top:13px; border-top:1px solid var(--gris-bord)}
.btn-reset{all:unset; cursor:pointer; font-size:12.5px; color:var(--cyan-txt); font-weight:700;
  letter-spacing:var(--ls); text-decoration:underline}
.btn-reset[disabled]{color:var(--wait); cursor:not-allowed; text-decoration:none}
.reset-echo{font-size:11.5px; color:var(--cyan-txt); letter-spacing:var(--ls)}
/* Cause d'un repli d'enrichissement — un repli ne se tait JAMAIS (AD-6). */
.ms-graph-fallback{margin-top:13px; border-left:3px solid var(--cta); background:#FFF9EF;
  border-radius:4px; padding:10px 13px; font-size:12.5px; color:#7A4E00}

.ms-chips{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px}
.ms-chips .chip{border:1px solid var(--gris-bord); background:var(--blanc);
  color:var(--teal); border-radius:20px; padding:6px 13px; font-size:12.5px;
  letter-spacing:var(--ls); cursor:pointer}
.ms-chips .chip:hover{background:var(--pale); border-color:var(--teal)}
.ms-pipeline{background:var(--blanc); border:1px solid var(--gris-bord);
  border-radius:14px; padding:14px 16px; margin-bottom:16px}
.ms-pl-head{display:flex; justify-content:space-between; align-items:baseline;
  font-size:13px; color:var(--teal); font-weight:700; letter-spacing:var(--ls); margin-bottom:4px}
.ms-elapsed{font-size:11.5px; font-weight:400; color:var(--gris-txt); font-variant-numeric:tabular-nums; white-space:nowrap}
/* STORY-339 — journal des étapes. ⚠️ Hauteur BORNÉE + défilement interne : sans
   borne, une cascade complète (7 étapes) pousse la réponse hors de l'écran au moment
   même où elle arrive. ⚠️ La règle `[hidden]` n'est pas décorative — un `display`
   d'auteur bat l'attribut du navigateur (garde `tests/js/marvia-hidden.test.js`). */
.ms-journal{display:flex; flex-direction:column; gap:2px; margin:8px 0 0; padding:8px 0 0; list-style:none; max-height:180px; overflow-y:auto; border-top:1px solid var(--gris-brd, #e3e7ea)}
.ms-journal[hidden]{display:none}
.ms-jn-l{display:flex; gap:10px; font-size:12px; color:var(--gris-txt); letter-spacing:var(--ls)}
.ms-jn-t{flex:0 0 52px; text-align:right; font-variant-numeric:tabular-nums; color:var(--gris-txt)}
.ms-jn-run .ms-jn-t{opacity:.65}
.ms-jn-run .ms-jn-x{opacity:.8}
.ms-pipeline .ms-status{font-size:12px; font-weight:400; color:var(--gris-txt); letter-spacing:var(--ls); margin-top:8px; min-height:16px}
/* Réponse sourcée : filet cyan à gauche (§7.3). #msAnswer PORTE .ms-answer. */
.ms-answer{background:var(--blanc); border:1px solid var(--gris-bord);
  border-left:4px solid var(--cyan); border-radius:12px; padding:16px 18px}
.ms-meta{font-size:11.5px; color:var(--gris-txt); letter-spacing:var(--ls); margin-bottom:12px; display:flex; gap:14px; flex-wrap:wrap; align-items:baseline}
.ms-meta b{color:var(--teal); font-weight:700}
/* Garde de lisibilité (zone principale fluide) : la borne ne mord qu'au-delà de
   l'ancienne largeur de contenu — rendu inchangé sur un écran ordinaire, prose
   non étirée sur un très grand écran. */
.ms-answer-text{font-size:14.5px; line-height:1.7; color:var(--noir); max-width:1120px}
/* Repère de citation (#7) : exposant, fond = couleur de LA source (inline). */
.ms-cite,.ms-deep-cite{display:inline-block; font-size:10px; font-weight:700; border-radius:5px; padding:0 5px; margin:0 1px; cursor:pointer; vertical-align:top; line-height:1.6}
.ms-cite:hover,.ms-cite:focus,.ms-deep-cite:hover,.ms-deep-cite:focus{outline:2px solid var(--cyan); outline-offset:1px}
/* Sources (#7) : bloc SÉPARÉ repliable, REPLIÉ par défaut, triangle de dépliage. */
.ms-srcs{margin-top:14px; background:var(--blanc); border:1px solid var(--gris-bord); border-radius:12px; padding:2px 16px 14px}
.ms-srcs-sum{cursor:pointer; font-size:12px; text-transform:uppercase; letter-spacing:var(--ls);
  color:var(--gris-txt); font-weight:700; padding:12px 0; list-style:none}
.ms-srcs-sum::-webkit-details-marker{display:none}
.ms-srcs-sum::before{content:"▸"; display:inline-block; margin-right:8px; color:var(--cyan-txt); transition:transform .15s}
.ms-srcs[open] .ms-srcs-sum::before{transform:rotate(90deg)}
.ms-srcs-body{display:flex; flex-direction:column; gap:10px}
.ms-src{background:var(--gris-bg); border:1px solid var(--gris-bord);
  border-radius:10px; padding:11px 13px; transition:background .3s}
.ms-src-h{display:flex; align-items:baseline; gap:6px; font-size:13px; color:var(--teal)}
.ms-src-n{display:inline-block; border-radius:5px; padding:0 6px; font-weight:700; font-size:11.5px; flex:none}
.ms-src-h b{flex:1}
.ms-src-open{margin-left:auto; flex:none; color:var(--cyan-txt); font-weight:600; font-size:11.5px; text-decoration:underline; white-space:nowrap}
.ms-src-open:hover{text-decoration:underline}
.ms-src-name{margin-left:auto; flex:none; font-size:11.5px; color:var(--gris-txt)}
.ms-src-type{font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:var(--ls); padding:1px 6px; border-radius:5px; margin-left:4px}
.ms-src-type-pdf{background:#FBE0DD; color:#A23A2E}
.ms-src-type-web{background:#D6ECF0; color:#06697C}
/* Score de pertinence du reranker (#13, mock-up .s-score) : cyan, gras, tabulaire. */
.ms-src-score{flex:none; color:var(--cyan-txt); font-weight:700; font-size:11.5px; font-variant-numeric:tabular-nums; white-space:nowrap}
.ms-src-m{font-size:11.5px; color:var(--gris-txt); margin:3px 0}
.ms-src-x{font-size:12.5px; color:var(--noir); line-height:1.5; margin-top:4px}
.ms-src.ms-hl{background:var(--pale); border-color:var(--cyan)}
.ms-refusal{background:var(--gris-bg); border:1px solid var(--gris-bord);
  border-left:4px solid var(--wait); border-radius:12px; padding:16px 18px;
  color:var(--gris-txt); font-size:14px}
/* Entités soulignées → Graphe (STORY-136). */
.ms-ent{border-bottom:1.5px dotted var(--cyan); color:var(--teal); cursor:pointer}
.ms-ent:hover,.ms-ent:focus{background:var(--pale); outline:none}
.ms-legend{font-size:11.5px; color:var(--gris-txt); margin-top:8px; font-style:italic}

/* ===== Écran Graphe de connaissances (STORY-138, EPIC-028) ============== */
.mg-wrap{display:flex; flex-direction:column; gap:12px}
.mg-controls{position:relative; max-width:520px}
#mgSearch{width:100%; padding:9px 12px; border:1px solid var(--gris-bord);
  border-radius:8px; font-family:var(--font); font-size:14px; letter-spacing:var(--ls)}
#mgSearch:focus{outline:2px solid var(--cta); outline-offset:1px; border-color:var(--cyan)}
.mg-results{display:flex; flex-direction:column; gap:2px; margin-top:6px}
.mg-result{display:flex; align-items:baseline; gap:8px; text-align:left; width:100%;
  padding:7px 10px; background:var(--blanc); border:1px solid var(--gris-bord);
  border-radius:6px; cursor:pointer; font-family:var(--font); font-size:13px}
.mg-result:hover,.mg-result:focus{background:var(--pale); outline:none}
.mg-r-name{color:var(--teal); font-weight:bold}
.mg-r-type{color:var(--gris-txt); font-size:11.5px; letter-spacing:var(--ls)}
.mg-r-cnt{margin-left:auto; color:var(--gris-txt); font-size:11.5px}
.mg-layouts{display:flex; flex-wrap:wrap; align-items:center; gap:6px}
.mg-layouts-lbl{font-size:12px; color:var(--gris-txt); letter-spacing:var(--ls); margin-right:2px}
.mg-layout-btn{padding:5px 11px; border:1px solid var(--gris-bord); background:var(--blanc);
  color:var(--teal); border-radius:16px; cursor:pointer; font-family:var(--font);
  font-size:12.5px; letter-spacing:var(--ls); transition:background .15s,border-color .15s}
.mg-layout-btn:hover{background:var(--pale)}
.mg-layout-btn:focus{outline:2px solid var(--cta); outline-offset:1px}
.mg-layout-btn.is-active{background:var(--teal); border-color:var(--teal); color:var(--blanc)}
.mg-note{color:var(--gris-txt); font-size:12px; font-style:italic; margin:0; min-height:16px}
.mg-canvas{border:1px solid var(--gris-bord); background:var(--gris-bg); border-radius:10px;
  min-height:520px; overflow:hidden}
.mg-svg{display:block; width:100%; height:auto;
  /* Le canevas est FIGÉ à 1000x560 unités : sans borne, `width:100%` étirait le
     graphe à toute la largeur du panneau (×1,4 et plus sur écran large) et la
     hauteur suivait — le graphe grossissait sans fin avec la fenêtre. La borne le
     rend au plus 1:1 ; `preserveAspectRatio` fait déjà le letterboxing. */
  max-width:1000px; margin-inline:auto}
.mg-svg.mg-dragging,.mg-svg.mg-dragging .mg-node{cursor:grabbing}
.mg-edge{stroke:var(--gris-bord); stroke-width:1.5}
.mg-edge.mg-hl{stroke:var(--cyan); stroke-width:2.5}
.mg-node{stroke:var(--blanc); stroke-width:2; cursor:grab; touch-action:none}
.mg-node:focus{outline:none; stroke:var(--cta); stroke-width:3}
.mg-node.sel{stroke:var(--cta); stroke-width:3.5}
.mg-label{font-family:var(--font); font-size:11px; fill:var(--noir); letter-spacing:var(--ls);
  pointer-events:none}
.mg-g.dim{opacity:.22}
.mg-edge.dim{opacity:.18}
.mg-legend{display:flex; flex-wrap:wrap; gap:14px; list-style:none; padding:0; margin:2px 0 0}
.mg-leg{display:flex; align-items:center; gap:6px; font-size:12px; color:var(--gris-txt);
  letter-spacing:var(--ls)}
.mg-swatch{width:12px; height:12px; border-radius:50%; display:inline-block;
  flex:0 0 auto}
/* STORY-296 — legende GROUPEE par famille POLE+O : le nom de la famille porte la
   couleur, les types du pack se lisent dessous. Sans ces regles, l ecran est
   cable, teste, CI verte... et NON STYLE (defaut STORY-274). */
.mg-leg{flex-wrap:wrap; max-width:230px}
.mg-leg-fam{font-weight:700; color:var(--noir)}
.mg-leg-types{display:block; width:100%; padding-left:18px; font-size:11px;
  color:var(--gris-txt); line-height:1.35}
@media (prefers-reduced-motion:reduce){.mg-node,.mg-edge{transition:none}}

/* ===== Panneau de détail d'entité (STORY-139) ========================== */
/* Le panneau de détail passe SOUS le graphe (largeur gagnée au graphe → plus
   lisible). Le graphe occupe toute la largeur ; le détail est une bande basse
   défilante. */
.mg-stage{display:flex; flex-direction:column; gap:14px}
.mg-stage .mg-canvas{width:100%; min-width:0}
.mg-detail{width:100%; border:1px solid var(--gris-bord); background:var(--blanc);
  border-radius:10px; padding:14px; overflow:auto; max-height:340px; min-height:120px;
  font-size:13px}
.mg-d-empty{color:var(--gris-txt); font-style:italic; font-size:12.5px}
.mg-d-title{display:flex; align-items:center; gap:8px; margin:0 0 6px; font-size:16px;
  color:var(--teal); letter-spacing:var(--ls)}
.mg-d-dot{width:12px; height:12px; border-radius:50%; display:inline-block; flex:0 0 auto}
.mg-d-meta{margin:0 0 8px; color:var(--gris-txt)}
.mg-d-type{color:var(--cyan-txt); font-weight:bold; letter-spacing:var(--ls)}
.mg-d-geo{margin:0 0 10px; font-size:12.5px}
.mg-d-nogeo{color:var(--gris-txt); font-style:italic}
.mg-d-h{margin:12px 0 4px; font-size:12px; text-transform:uppercase; letter-spacing:var(--ls);
  color:var(--gris-txt)}
.mg-d-rels,.mg-d-evs{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:3px}
.mg-d-rel,.mg-d-ev{padding:4px 0; border-bottom:1px solid var(--gris-bord); font-size:12.5px}
.mg-d-rtype{color:var(--cyan-txt); font-weight:bold}
.mg-d-rtarget{color:var(--teal)}
/* #12 — éléments navigables du panneau : mentions dépliables, cibles cliquables,
   « Autres types connus ». Boutons dénudés (aspect lien, curseur main). */
.mg-d-mentions,.mg-d-goto{all:unset; cursor:pointer; color:var(--teal); font-weight:700}
.mg-d-mentions:hover,.mg-d-goto:hover{text-decoration:underline}
.mg-d-mentions:focus-visible,.mg-d-goto:focus-visible{outline:2px solid var(--cta); outline-offset:2px; border-radius:3px}
.mg-d-mentions::after{content:" ▸"; font-size:9px}
.mg-d-mentions[aria-expanded="true"]::after{content:" ▾"}
.mg-d-mentions-body{margin:6px 0 8px}
.mg-d-cites{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:4px}
.mg-d-cite{font-size:12px; color:var(--gris-txt)}
.mg-d-cite-open{color:var(--teal); font-weight:700; text-decoration:none}
.mg-d-cite-open:hover{text-decoration:underline}
.mg-d-others{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:3px}
.mg-d-others li{padding:4px 0; border-bottom:1px solid var(--gris-bord); font-size:12.5px}
.mg-d-o-type{color:var(--gris-txt); font-size:11px; text-transform:uppercase; letter-spacing:var(--ls); font-weight:400}
.mg-d-o-cnt{float:right; color:var(--cyan-txt); font-weight:700}
.mg-d-badge{display:inline-block; font-size:10.5px; padding:1px 6px; border-radius:8px;
  letter-spacing:var(--ls); margin-left:4px}
.mg-d-contested{background:#FBF6EE; color:#8A6D2F; border:1px solid #F0E2C8}
.mg-d-superseded{background:var(--gris-bg); color:var(--gris-txt); border:1px solid var(--gris-bord)}
@media (max-width:860px){.mg-canvas{min-height:380px}.mg-detail{max-height:none}}

/* ===== Fusion d'entités HITL (STORY-141) — bloc beige charte =========== */
.mg-fuse{margin-top:16px; background:#FBF6EE; border:1px solid #F0E2C8; border-radius:10px;
  padding:14px}
.mg-fuse-head{display:flex; align-items:center; justify-content:space-between; gap:12px;
  flex-wrap:wrap; margin-bottom:8px}
.mg-fuse-head h2{margin:0; font-size:16px; color:#8A6D2F; letter-spacing:var(--ls)}
.mg-fuse-lbl{font-size:12.5px; color:#8A6D2F; letter-spacing:var(--ls)}
.mg-fuse-lbl select{margin-left:6px; padding:5px 8px; border:1px solid #F0E2C8; border-radius:6px;
  font-family:var(--font); font-size:13px}
.mg-fuse-list{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:8px}
.mg-fuse-empty{color:#8A6D2F; font-style:italic; font-size:12.5px; padding:6px 0}
.mg-fuse-card{background:var(--blanc); border:1px solid #F0E2C8; border-radius:8px; padding:10px 12px;
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap}
.mg-fuse-pair{display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-size:13.5px}
.mg-fuse-canon{color:var(--teal); font-weight:bold}
.mg-fuse-dup{color:var(--noir)}
.mg-fuse-cnt{color:var(--gris-txt); font-size:11.5px; font-weight:normal}
.mg-fuse-approx{color:#8A6D2F; font-weight:bold}
.mg-fuse-score{background:#FBF6EE; border:1px solid #F0E2C8; color:#8A6D2F; font-size:11.5px; padding:1px 8px; border-radius:8px;
  letter-spacing:var(--ls)}
.mg-fuse-acts{display:flex; gap:8px}
.mg-fuse-btn{padding:6px 12px; border-radius:6px; font-family:var(--font); font-size:12.5px;
  letter-spacing:var(--ls); cursor:pointer; border:1px solid transparent}
.mg-fuse-btn:focus{outline:2px solid var(--cta); outline-offset:1px}
.mg-fuse-btn[disabled]{opacity:.5; cursor:default}
.mg-fuse-merge{background:var(--cta); color:var(--noir); font-weight:bold}
.mg-fuse-ignore{background:var(--blanc); color:var(--gris-txt); border-color:var(--gris-bord)}

/* ===== Écran Réglages (STORY-143) ====================================== */
/* FLUIDE : les cartes suivent la largeur de la fenêtre, comme les autres écrans.
   ⚠️ Pas de `max-width` ici. Elle bornait la colonne à 640px — les pastilles de
   santé se repliaient sur trois rangs et les bascules de configuration
   occupaient un tiers de l'écran, sur un écran qui n'a AUCUN texte long à
   protéger (le seul argument d'une borne de lisibilité). */
.st-wrap{display:flex; flex-direction:column; gap:16px}
.st-card{border:1px solid var(--gris-bord); background:var(--blanc); border-radius:10px; padding:16px}
.st-card h2{margin:0 0 8px; font-size:17px; color:var(--teal); letter-spacing:var(--ls)}
.st-sov{margin:0 0 12px; font-size:12.5px; color:var(--gris-txt); font-style:italic}
.st-status{list-style:none; padding:0; margin:0; display:flex; flex-wrap:wrap; gap:8px}
.mg-pill{display:inline-flex; align-items:center; gap:7px; padding:5px 12px; border-radius:16px;
  font-size:12.5px; letter-spacing:var(--ls); border:1px solid var(--gris-bord); background:var(--gris-bg)}
.mg-pill .mg-dot{width:9px; height:9px; border-radius:50%; display:inline-block; background:var(--wait)}
.mg-pill.mg-on{background:var(--pale); color:var(--teal); border-color:var(--pale)}
.mg-pill.mg-on .mg-dot{background:var(--run)}
.mg-pill.mg-off{background:#FBECEA; color:#C0392B; border-color:#F3C6C0}
.mg-pill.mg-off .mg-dot{background:#C0392B}
.mg-state{font-weight:bold}
.st-models{display:flex; flex-direction:column; gap:4px}
.st-model{display:flex; justify-content:space-between; gap:12px; padding:6px 0;
  border-bottom:1px solid var(--gris-bord); font-size:13px}
.st-model-k{color:var(--gris-txt); letter-spacing:var(--ls)}
.st-model-v{color:var(--teal); font-weight:bold; word-break:break-all}

/* ===== Bascules & note golden (STORY-145) ============================== */
.st-toggles{display:flex; flex-direction:column; gap:14px}
.st-group h3{margin:0 0 6px; font-size:12px; text-transform:uppercase; letter-spacing:var(--ls);
  color:var(--gris-txt)}
.st-toggle{display:flex; align-items:center; gap:10px; padding:6px 0; cursor:pointer; font-size:13.5px}
.st-toggle input[type="checkbox"]{width:16px; height:16px; accent-color:var(--cyan); cursor:pointer}
.st-toggle input:focus{outline:2px solid var(--cta); outline-offset:2px}
.st-toggle-lbl{color:var(--noir)}
.st-toggle-err{color:#C0392B; font-size:12.5px; font-style:italic; margin:0}
.st-golden{margin:0; font-size:12.5px; color:var(--gris-txt); font-style:italic}

/* ===== Écran Gouvernance — sous-nav par onglets (STORY-147) ============= */
.gov-tabs{display:flex; gap:4px; border-bottom:1px solid var(--gris-bord); margin-bottom:16px;
  flex-wrap:wrap}
.gov-tab{padding:9px 16px; background:transparent; border:none; border-bottom:3px solid transparent;
  font-family:var(--font); font-size:14px; letter-spacing:var(--ls); color:var(--gris-txt);
  cursor:pointer}
.gov-tab:hover{color:var(--teal)}
.gov-tab.active{color:var(--teal); border-bottom-color:var(--cyan); font-weight:bold}
.gov-tab:focus-visible{outline:3px solid var(--cta); outline-offset:2px}
.gov-panel{display:none}
.gov-panel.show{display:block}

/* ===== Gouvernance : arbitrage des citations (STORY-148) =============== */
.gc-list{list-style:none; padding:0; margin:0 0 16px; display:flex; flex-direction:column; gap:4px}
.gc-empty{color:var(--gris-txt); font-style:italic; font-size:12.5px; padding:6px 0}
.gc-row{display:flex; flex-wrap:wrap; gap:10px; align-items:baseline; padding:9px 12px;
  border:1px solid var(--gris-bord); border-radius:6px; background:var(--blanc); cursor:pointer;
  font-size:13px}
.gc-row:hover{background:var(--pale)}
.gc-file{color:var(--teal); font-weight:bold}
.gc-cur{color:var(--noir)}
.gc-reason{margin-left:auto; color:var(--gris-txt); font-size:11.5px; font-style:italic}
.gc-dossier{border:1px solid var(--gris-bord); border-radius:10px; padding:16px; background:var(--gris-bg)}
.gc-dossier h3{margin:0 0 8px; color:var(--teal); font-size:16px; letter-spacing:var(--ls)}
.gc-dossier h4{margin:12px 0 6px; font-size:12px; text-transform:uppercase; letter-spacing:var(--ls);
  color:var(--gris-txt)}
.gc-reasons{margin:0 0 8px; padding-left:18px; color:var(--gris-txt); font-size:12.5px}
.gc-ocr{background:var(--blanc); border:1px solid var(--gris-bord); border-radius:6px; padding:10px;
  font-size:12px; white-space:pre-wrap; max-height:180px; overflow:auto}
.gc-cand{display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:8px 10px;
  border:1px solid var(--gris-bord); border-radius:6px; background:var(--blanc); margin-bottom:6px;
  font-size:12.5px}
.gc-origin{background:var(--pale); color:var(--teal); font-size:11px; padding:1px 8px; border-radius:8px;
  letter-spacing:var(--ls)}
.gc-score{color:var(--gris-txt); font-size:11px}
.gc-cand-body{flex:1 1 auto}
.gc-use{padding:4px 10px; border:1px solid var(--gris-bord); border-radius:6px; background:var(--blanc);
  cursor:pointer; font-size:12px}
.gc-use:hover{background:var(--pale)}
.gc-form{display:flex; flex-direction:column; gap:6px; margin-top:8px}
.gc-fld{display:flex; flex-direction:column; gap:2px; font-size:12px; color:var(--gris-txt)}
.gc-fld input{padding:6px 8px; border:1px solid var(--gris-bord); border-radius:6px;
  font-family:var(--font); font-size:13px}
.gc-fld input:focus{outline:2px solid var(--cta); outline-offset:1px}
.gc-acts{display:flex; gap:10px; margin-top:12px}
.gc-decide{padding:8px 16px; border-radius:6px; border:1px solid transparent; cursor:pointer;
  font-family:var(--font); font-size:13px; letter-spacing:var(--ls)}
.gc-approve{background:var(--cta); color:var(--noir); font-weight:bold}
.gc-reject{background:var(--blanc); color:var(--gris-txt); border-color:var(--gris-bord)}
.gc-decide[disabled]{opacity:.5; cursor:default}

/* ===== Gouvernance : curation des contradictions (STORY-149) =========== */
.gk-head{display:flex; justify-content:flex-end; margin-bottom:12px}
.gk-notify{padding:7px 14px; background:var(--cyan); color:var(--blanc); border:none; border-radius:6px;
  font-family:var(--font); font-size:13px; letter-spacing:var(--ls); cursor:pointer; font-weight:bold}
.gk-notify:hover{background:var(--teal)}
.gk-notify:focus-visible{outline:3px solid var(--cta); outline-offset:2px}
.gk-list{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:6px}
.gk-empty{color:var(--gris-txt); font-style:italic; font-size:12.5px; padding:6px 0}
.gk-row{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:10px 12px; border:1px solid var(--gris-bord); border-radius:8px; background:var(--blanc);
  font-size:12.5px}
.gk-info{display:flex; align-items:center; gap:8px; flex-wrap:wrap}
.gk-kind{font-size:10.5px; padding:1px 8px; border-radius:8px; letter-spacing:var(--ls);
  text-transform:uppercase}
.gk-contested{background:#FBF6EE; color:#8A6D2F; border:1px solid #F0E2C8}
.gk-superseded{background:var(--gris-bg); color:var(--gris-txt); border:1px solid var(--gris-bord)}
.gk-subj{color:var(--teal); font-weight:bold; font-family:monospace}
.gk-lbl{color:var(--cyan-txt); font-size:11px; letter-spacing:var(--ls)}
.gk-rel{color:var(--noir); font-family:monospace; font-size:11.5px}
.gk-cnt{color:var(--gris-txt); font-size:11px}
.gk-acts{display:flex; gap:8px}
.gk-decide{padding:6px 12px; border-radius:6px; border:1px solid transparent; cursor:pointer;
  font-family:var(--font); font-size:12px; letter-spacing:var(--ls)}
.gk-approve{background:var(--cta); color:var(--noir); font-weight:bold}
.gk-reject{background:var(--blanc); color:var(--gris-txt); border-color:var(--gris-bord)}
.gk-decide[disabled]{opacity:.5; cursor:default}

/* ===== Gouvernance : comptes & rôles (STORY-150) ====================== */
.ga-create{border:1px solid var(--gris-bord); border-radius:10px; padding:14px; background:var(--gris-bg);
  margin-bottom:16px; display:flex; flex-wrap:wrap; gap:10px; align-items:flex-end}
.ga-create h4{width:100%; margin:0 0 4px; font-size:12px; text-transform:uppercase; letter-spacing:var(--ls);
  color:var(--gris-txt)}
.ga-fld{display:flex; flex-direction:column; gap:2px; font-size:12px; color:var(--gris-txt)}
.ga-fld input,.ga-fld select,.ga-role{padding:6px 8px; border:1px solid var(--gris-bord); border-radius:6px;
  font-family:var(--font); font-size:13px}
.ga-fld input:focus,.ga-fld select:focus,.ga-role:focus{outline:2px solid var(--cta); outline-offset:1px}
.ga-create-btn{padding:8px 16px; background:var(--cta); color:var(--noir); border:none; border-radius:6px;
  font-family:var(--font); font-size:13px; font-weight:bold; letter-spacing:var(--ls); cursor:pointer}
.ga-list{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:6px}
.ga-empty{color:var(--gris-txt); font-style:italic; font-size:12.5px; padding:6px 0}
.ga-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:9px 12px;
  border:1px solid var(--gris-bord); border-radius:8px; background:var(--blanc); font-size:13px}
.ga-login{color:var(--teal); font-weight:bold; font-family:monospace}
.ga-badge{font-size:10.5px; padding:1px 8px; border-radius:8px; letter-spacing:var(--ls)}
.ga-on{background:var(--pale); color:var(--teal)}
.ga-off{background:#FBECEA; color:#C0392B}
.ga-svc{background:var(--gris-bg); color:var(--gris-txt); border:1px solid var(--gris-bord)}
.ga-acts{display:flex; gap:8px; margin-left:auto}
.ga-set-role,.ga-deactivate{padding:5px 12px; border:1px solid var(--gris-bord); border-radius:6px;
  background:var(--blanc); cursor:pointer; font-family:var(--font); font-size:12px}
.ga-set-role:hover,.ga-deactivate:hover{background:var(--pale)}
.ga-deactivate{color:#C0392B; border-color:#F3C6C0}

/* CR épic STORY-148 : bouton pagination de la file d'arbitrage */
.gc-more-zone{margin:8px 0 16px}
.gc-more{padding:7px 14px; background:var(--blanc); border:1px solid var(--gris-bord); border-radius:6px;
  cursor:pointer; font-family:var(--font); font-size:12.5px; color:var(--teal)}
.gc-more:hover{background:var(--pale)}

/* --- Second niveau « Approfondir » (STORY-176, EPIC-035) ------------------ */
.ms-deep-bar { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.ms-deep-btn {
  background: var(--as3p-accent, #06697C); color: #fff; border: 0; border-radius: 6px;
  padding: 8px 14px; font-size: 0.92rem; cursor: pointer;
}
.ms-deep-btn:disabled { opacity: 0.6; cursor: progress; }
.ms-deep-hint { color: #667; font-size: 0.85rem; }
.ms-deep { margin-top: 14px; padding: 12px 14px; border-left: 3px solid #06697C;
  background: #F7FBFC; border-radius: 4px; }
.ms-deep-title { font-weight: 600; margin-bottom: 8px; }
.ms-deep-body { line-height: 1.55; }
.ms-deep-reason { color: #667; font-size: 0.88rem; margin-top: 6px; }
.ms-deep-nograph { color: #667; font-size: 0.88rem; margin-bottom: 8px; }
/* STORY-321 : mention d'apport nul — meme registre discret */
.ms-apport { color: #667; font-size: 0.88rem; margin-bottom: 8px; }
/* STORY-318 : badge de regroupement des sources a chunk partage */
.ms-src-multi { color: #667; font-size: 0.82rem; margin: 4px 0 2px; }
.ms-src-alias { display: block; height: 0; }
/* STORY-309 : mention de troncature — même registre discret que .ms-deep-nograph */
.ms-tronquee { color: #8a6d00; font-size: 0.88rem; margin-bottom: 8px; }
/* STORY-217 — même registre discret : un CONSTAT, pas une alerte. */
.ms-deep-graphpass { color: #667; font-size: 0.88rem; margin-bottom: 8px; }
.ms-deep-fact--contested { color: #A23A2E; }
.ms-deep-flag {
  background: #FBE0DD; color: #A23A2E; border-radius: 3px;
  padding: 1px 5px; font-size: 0.8rem;
}
.ms-deep-rels { margin-top: 10px; font-size: 0.9rem; }
.ms-deep-rel-list { margin: 8px 0 0; padding-left: 22px; }
.ms-deep-rel { margin-bottom: 4px; }
.ms-deep-rel-t { color: #667; font-style: italic; }
.ms-deep-rest { color: #667; font-size: 0.85rem; margin-top: 6px; }
.ms-deep-prev { margin-top: 12px; }
.ms-deep-prev > summary { cursor: pointer; color: #06697C; font-size: 0.9rem; }

/* --- Onglet Journal de Gouvernance (STORY-187, EPIC-037) ----------------- */
.jrn-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; }
.jrn-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.jrn-chip {
  border: 1px solid #CBD5DD; background: #fff; border-radius: 14px;
  padding: 4px 12px; font-size: 0.85rem; cursor: pointer;
}
.jrn-chip.active { background: #06697C; color: #fff; border-color: #06697C; }
.jrn-status { color: #667; font-size: 0.85rem; }
/* Le Journal est un TABLEAU depuis STORY-193. ⚠️ Il ne réutilise PAS `.audit-table` :
   celui-ci pose ses largeurs par ATTRIBUT (`th[data-sort=…]`) pour ses propres colonnes — les appliquer
   aux quatre du Journal donnerait des largeurs arbitraires. Mêmes variables, règles
   propres. La règle `display:grid` d'origine (liste) a été retirée : sur des `<tr>`
   elle aurait cassé la mise en page du tableau. */
.jrn-table-wrap { overflow-x: auto; }
.jrn-table {
  width: 100%; border-collapse: collapse; background: var(--blanc);
  border: 1px solid var(--gris-bord); border-radius: 14px; overflow: hidden;
}
.jrn-table thead th {
  text-align: left; font-size: 0.8rem; color: var(--gris-txt);
  padding: 8px; border-bottom: 1px solid var(--gris-bord); white-space: nowrap;
}
.jrn-table th:nth-child(1) { width: 165px; }
.jrn-table th:nth-child(2) { width: 120px; }
.jrn-table th:nth-child(3) { width: 26%; }
.jrn-table td { padding: 7px 8px; border-bottom: 1px solid #EEF2F4; vertical-align: top; }
.jrn-row { cursor: pointer; }
.jrn-row:hover { background: #F7FBFC; }
.jrn-empty td { color: var(--gris-txt); font-style: italic; text-align: center; padding: 18px; }
.jrn-at { color: #667; font-variant-numeric: tabular-nums; font-size: 0.82rem; }
.jrn-kind { font-size: 0.78rem; border-radius: 3px; padding: 1px 6px; background: #EEF2F4; }
.jrn-subject { font-weight: 500; }
.jrn-summary { color: #445; font-size: 0.9rem; }
/* L'acteur n'a PAS de colonne réservée : il n'existe que sur une source sur six. */
.jrn-actor { color: #667; font-size: 0.78rem; font-style: italic; }
.jrn-detail-row td { background: #FBFDFD; border-bottom: 1px solid var(--gris-bord); }
.jrn-detail-body { background: #F7FBFC; border-left: 3px solid #06697C; padding: 8px 12px; margin-top: 6px; }
.jrn-ref { color: #667; font-size: 0.8rem; margin-top: 4px; }
.jrn-more { margin-top: 12px; }

/* File cross-type PRIORISÉE par impact (STORY-194). Aucune couleur nouvelle : les
   variables de la charte uniquement. */
.xt-queue { margin-bottom: 18px; }
.xt-total { color: var(--gris-txt); font-size: 0.85rem; }
.xt-list { border: 1px solid var(--gris-bord); border-radius: 14px; overflow: hidden; }
.xt-row {
  display: grid; grid-template-columns: 70px 1fr 1fr; gap: 10px;
  align-items: baseline; padding: 7px 10px; border-bottom: 1px solid #EEF2F4;
}
.xt-row:last-child { border-bottom: none; }
/* L'IMPACT en tête : c'est le degré cumulé des doublons, donc ce que la fusion
   déplacerait. Sans lui, une entité-carrefour est indiscernable d'un orphelin. */
.xt-impact {
  font-variant-numeric: tabular-nums; font-weight: 600; color: var(--teal);
  background: var(--gris-bg); border-radius: 3px; padding: 1px 6px; text-align: right;
}
.xt-name { font-weight: 500; }
.xt-labels { color: var(--gris-txt); font-size: 0.85rem; }
.xt-empty { color: var(--gris-txt); font-style: italic; padding: 14px; margin: 0; }

/* Poignée de redimensionnement des colonnes de l'Audit (STORY-177). Pleine hauteur
   d'en-tête, ~6 px de préhension. `aria-hidden` + non focalisable : le tri au clavier
   passe par le `<th>` lui-même, la poignée ne doit pas devenir un piège de tabulation. */
.audit-table thead th { position: relative; }
.col-resize {
  position: absolute; top: 0; right: 0; width: 6px; height: 100%;
  cursor: col-resize; user-select: none;
}
.col-resize:hover { background: var(--pale); }

/* Colonne de sélection (STORY-178) — présente seulement si `can_remove` (D4 : sa seule
   action est la suppression). Étroite, centrée. */
.audit-table thead th.sel-col, .audit-table tbody td.sel-col { width: 38px; text-align: center; }
.audit-table td.sel-col input, .audit-table th.sel-col input { cursor: pointer; }

/* Zone dangereuse — remise à zéro du corpus (STORY-183). Le rouge n'est pas
   décoratif : c'est le seul écran qui détruit tout, et il doit se distinguer au
   premier coup d'œil des autres onglets de Gouvernance. */
.gov-tab.danger { color: #C0392B; }
.gov-tab.danger[aria-selected="true"], .gov-tab.danger.active { border-bottom-color: #C0392B; }
.danger-zone { border: 2px solid #C0392B; border-radius: 6px; padding: 18px; }
.danger-zone .dz-avert { color: #C0392B; font-weight: 700; margin: 0 0 14px }
.danger-zone .dz-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 16px }
.danger-zone .dz-cols h3 { font-size: 13px; letter-spacing: var(--ls); margin: 0 0 6px }
.danger-zone .dz-cols ul { margin: 0; padding-left: 18px; font-size: 13px }
.danger-zone .dz-preserve li { color: var(--teal) }
.danger-zone .dz-detruit li { color: #C0392B }
.danger-zone code.dz-phrase { background: var(--gris-bg); padding: 2px 6px; border-radius: 3px; font-weight: 700 }
.danger-zone .dz-saisie { width: 100%; max-width: 420px; padding: 8px 10px; margin: 6px 0 12px;
  border: 1px solid #CBD5D8; border-radius: 4px; font-size: 14px }
.danger-zone .dz-go:disabled { opacity: .45; cursor: not-allowed }
.danger-zone .dz-bilan { font-weight: 700; margin-top: 12px }
.danger-zone .dz-erreur { color: #C0392B; margin-top: 6px }

/* ---- Gouvernance : onglet « Batches » (STORY-170) ------------------------- */
#gov-batches .bt-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 4px }
#gov-batches .bt-head h2 { font-size: 15px; letter-spacing: var(--ls); margin: 0 }
#gov-batches .bt-state { font-weight: 700; font-size: 13px; color: var(--teal) }
#gov-batches .bt-state[data-state="running"] { color: var(--teal) }
#gov-batches .bt-state[data-state="stopping"] { color: #99651A }
#gov-batches .bt-state[data-state="idle"] { color: var(--gris-txt) }
#gov-batches .bt-note { font-size: 12px; color: var(--gris-txt); margin: 0 0 14px; max-width: 62ch }
#gov-batches .bt-bar { height: 8px; background: var(--gris-bg); border-radius: 4px;
  overflow: hidden; margin-bottom: 14px }
#gov-batches .bt-fill { display: block; height: 100%; width: 0; background: var(--teal);
  transition: width .4s ease }
#gov-batches .bt-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px 18px; margin: 0 0 14px }
#gov-batches .bt-metrics dt { font-size: 11px; letter-spacing: var(--ls); color: var(--gris-txt);
  text-transform: uppercase }
#gov-batches .bt-metrics dd { margin: 0 0 4px; font-size: 15px; font-weight: 700 }
/* Bandeau « arrêt demandé » : l'arrêt est COOPÉRATIF (jusqu'à ~4 min). Sans cet
   état visible, l'usager clique, ne voit rien changer, et reclique. */
#gov-batches .bt-stopping { background: #FDF6E3; border-left: 3px solid #99651A;
  padding: 8px 12px; font-size: 13px; margin: 0 0 12px }
#gov-batches .bt-actions { display: flex; gap: 10px; margin-bottom: 12px }
#gov-batches .bt-actions button:disabled { opacity: .45; cursor: not-allowed }
/* Un REFUS n'est pas une panne : « hors fenêtre » est l'état normal 18 h sur 24.
   Ton informatif, jamais l'alarme rouge des erreurs. */
#gov-batches .bt-refus { background: var(--gris-bg); border-left: 3px solid var(--teal);
  padding: 8px 12px; font-size: 13px; margin: 0 0 12px }
#gov-batches .bt-erreur { color: #C0392B; font-size: 13px; margin: 0 0 12px }
#gov-batches h3 { font-size: 13px; letter-spacing: var(--ls); margin: 18px 0 8px }
#gov-batches .bt-table-wrap { overflow-x: auto }
#gov-batches .bt-table { width: 100%; border-collapse: collapse; font-size: 13px }
#gov-batches .bt-table thead th { text-align: left; font-size: 11px; letter-spacing: var(--ls);
  color: var(--gris-txt); text-transform: uppercase; padding: 6px 8px;
  border-bottom: 1px solid #E3E9EC }
#gov-batches .bt-table td { padding: 7px 8px; border-bottom: 1px solid #EEF2F4 }

/* ---- Réglages : politiques NON NÉGOCIABLES, en lecture seule (STORY-198) --- */
/* Volontairement distinctes des bascules : ce ne sont pas des cases grisées, ce
   sont des informations. Le respect de robots.txt n'est pas un réglage. */
.st-policy { display: flex; justify-content: space-between; gap: 12px;
  padding: 6px 0; border-top: 1px solid #EEF2F4; font-size: 13px }
.st-policy-k { color: var(--gris-txt) }
.st-policy-v { font-weight: 700; color: var(--teal) }

/* ============================================================
   Écran « Statistiques » (hors-plan) — volumes, rendement, 7 graphiques.

   Graphiques en SVG maison : aucune bibliothèque, aucune URL externe (FR-039).
   Les couleurs des parts sont posées EN LIGNE par le JS (une part = une teinte de
   la palette) ; ici on n'habille que la structure.
   ============================================================ */
.sx-refresh{ all:unset; cursor:pointer; font-size:12px; letter-spacing:var(--ls);
  color:var(--cyan-txt); border:1px solid var(--gris-bord); border-radius:8px;
  padding:6px 12px; background:var(--blanc) }
.sx-refresh:hover{ border-color:var(--cyan) }
.sx-etat{ min-height:18px; margin:0 0 12px; font-size:12.5px; color:var(--gris-txt);
  letter-spacing:var(--ls) }

.sx-card{ background:var(--blanc); border:1px solid var(--gris-bord);
  border-radius:14px; padding:16px 20px; margin-bottom:18px }
.sx-card h2{ margin:0 0 12px; font-size:13px; font-weight:700; color:var(--teal);
  letter-spacing:var(--ls); text-transform:uppercase }
.sx-grain{ font-weight:400; text-transform:none; color:var(--gris-txt); font-size:11.5px }

.sx-tiles{ display:flex; gap:26px; flex-wrap:wrap }
.sx-tile{ display:flex; flex-direction:column; gap:2px; min-width:104px }
.sx-tile .k{ font-size:11.5px; color:var(--gris-txt); letter-spacing:var(--ls) }
.sx-tile .n{ font-size:20px; font-weight:700; color:var(--cyan-txt);
  letter-spacing:var(--ls) }
/* Sous-libellé : ce sur quoi la mesure porte réellement (ex. « sur 3 des 212
   questions »). Discret, mais jamais absent quand l'écart existe. */
.sx-sous{ font-size:10.5px; color:var(--gris-txt); letter-spacing:var(--ls) }

/* Deux colonnes sur large, une seule en dessous : les graphiques restent lisibles
   plutôt que de rétrécir sous leur seuil de lecture. */
.sx-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(340px,1fr));
  gap:18px }
.sx-grid .sx-card{ margin-bottom:0 }
.sx-wide{ grid-column:1/-1 }

.sx-chart{ display:flex; flex-wrap:wrap; align-items:center; gap:18px }
.stx-pie{ width:150px; height:150px; flex:0 0 auto }
.stx-line,.stx-scatter{ width:100%; max-width:340px; height:auto }
.stx-axe{ stroke:var(--gris-bord); stroke-width:1 }
.stx-poly{ fill:none; stroke:var(--cyan); stroke-width:2;
  stroke-linejoin:round; stroke-linecap:round }
.stx-pt{ fill:var(--cyan) }
/* Graduations et légendes d'axes. Les valeurs sont l'information : une courbe sans
   elles dit « plus » puis « moins » ; avec elles, elle dit 134 puis 73 documents. */
.stx-grille{ stroke:#EEF2F4; stroke-width:1 }
.stx-grad{ font-family:var(--font); font-size:9px; fill:var(--gris-txt) }
.stx-grad-y{ text-anchor:end }
.stx-grad-x{ text-anchor:middle }
.stx-titre{ font-family:var(--font); font-size:9.5px; fill:var(--teal);
  font-weight:700; text-anchor:middle; letter-spacing:var(--ls) }

.stx-leg{ list-style:none; margin:0; padding:0; flex:1 1 150px; min-width:150px }
.stx-leg li{ display:flex; align-items:center; gap:7px; padding:3px 0;
  font-size:12px; letter-spacing:var(--ls) }
.stx-puce{ width:10px; height:10px; border-radius:3px; flex:0 0 auto }
.stx-pct{ color:var(--gris-txt); font-size:11px }

/* ⚠️ « Aucune donnée » se DIT. Un SVG vide ressemble à un écran cassé — et la
   réserve connue de ce dépôt est qu'un écran peut être une boîte vide avec une
   suite de tests verte. */
.stx-vide{ margin:0; font-size:12.5px; color:var(--gris-txt);
  letter-spacing:var(--ls); font-style:italic }

/* Coût de calcul et projection (tokens, durées, simulation tarifaire). */
.sx-models{ margin-top:14px; overflow-x:auto }
.sx-tbl{ width:100%; border-collapse:collapse; font-size:12.5px }
.sx-tbl th{ text-align:left; font-weight:700; color:var(--gris-txt); font-size:11px;
  letter-spacing:var(--ls); border-bottom:1px solid var(--gris-bord); padding:6px 10px 6px 0 }
.sx-tbl td{ padding:6px 10px 6px 0; border-bottom:1px solid #F2F6F7 }
.sx-tbl td:not(:first-child), .sx-tbl th:not(:first-child){ text-align:right }
.sx-prov{ color:var(--gris-txt); font-size:10.5px }

.sx-proj{ display:flex; gap:18px; flex-wrap:wrap; align-items:flex-end }
.sx-proj label{ display:flex; flex-direction:column; gap:4px; font-size:11.5px;
  color:var(--gris-txt); letter-spacing:var(--ls) }
.sx-proj input{ width:130px; padding:6px 8px; border:1px solid var(--gris-bord);
  border-radius:8px; font-size:13px; font-family:var(--font) }
.sx-proj-out{ margin:14px 0 0; font-size:15px; font-weight:700; color:var(--teal);
  letter-spacing:var(--ls); line-height:1.5 }
/* ⚠️ La note dit d'où vient le chiffre ET que rien n'est enregistré : une
   projection sans provenance se lit comme un engagement. */
.sx-proj-note{ margin:6px 0 0; font-size:11px; color:var(--gris-txt);
  letter-spacing:var(--ls); font-style:italic }

/* ⚠️ Jetons de la charte, pas de valeurs en dur : `#667` et `0.85rem` rendaient la
   note plus grande et dans un gris hors palette que le tableau qu'elle annote. */
.sx-scroll{ overflow-x:auto }
.sx-note{ margin:8px 0 0; font-size:11.5px; line-height:1.45; color:var(--gris-txt) }

/* STORY-238 — l'attente minimale. ⚠️ Sans règle, la phrase s'affichait en texte
   nu, collée sous le titre : rien ne la distinguait du contenu ordinaire, alors
   que tout son intérêt est d'être remarquée AVANT que l'usager conclue à une
   panne. Registre d'information, pas d'erreur — le corpus se construit, il n'est
   pas cassé. */
.corpus-attente {
  margin: 0 0 16px;
  padding: 10px 14px;
  border-left: 3px solid #c9a227;
  background: rgba(201, 162, 39, 0.08);
  color: #4a4433;
  font-size: 0.92rem;
  border-radius: 3px;
}

/* --- Écran « Démarrage » : catalogue de packs (STORY-253) ---------------- */
#view-start .grid { display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)) }
.pack { border: 1px solid var(--gris-bord); border-radius: 10px; padding: 14px;
  background: var(--blanc); cursor: pointer }
.pack:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px }
.pack.sel { border-color: var(--teal); box-shadow: 0 0 0 1px var(--teal) inset }
/* ⚠️ Verrouillé : le curseur ET l'opacité le disent, mais le TEXTE de `.verrou`
   reste la source accessible — jamais la seule couleur. */
.pack.verrouille { cursor: default; opacity: .72 }
.pack h3 { margin: 0 0 4px; font-size: 1rem }
.pack .dom { color: var(--gris-txt); font-size: .85rem }
.pack .counts, .pack .caps { color: var(--gris-txt); font-size: .8rem; margin-top: 4px }
.pack .badges { margin-top: 8px }
.pack .verrou { color: var(--gris-txt); font-size: .8rem; margin: 8px 0 0 }
.pack .voir { margin-top: 10px }
.preview-t { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: .85rem }
.preview-t th, .preview-t td { text-align: left; padding: 4px 8px;
  border-bottom: 1px solid var(--gris-bord) }
.preview-ev { color: var(--gris-txt); font-size: .85rem; margin-top: 10px }

/* --- founding-stepper (STORY-254) ---------------------------------------- */
#msStartStepper { margin-top: 20px }
.stepper { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px }
.stepper button { border: 1px solid var(--gris-bord); background: var(--blanc);
  border-radius: 8px; padding: 8px 12px; cursor: pointer; font-size: .85rem }
.stepper button b { display: block; font-size: 1rem }
.stepper button.done { color: var(--cyan-txt); border-color: var(--cyan) }
.stepper button.on { color: var(--blanc); background: var(--teal); border-color: var(--teal) }
.stepper button[disabled] { opacity: .5; cursor: default }
.recap-dl { margin: 0 0 12px }
.recap-dl dt { color: var(--gris-txt); font-size: .8rem; margin-top: 8px }
.recap-dl dd { margin: 2px 0 0 }
/* ⚠️ `restart` est INFORMATIF, jamais une alerte (AD-O13) : ton neutre, pas de rouge. */
.restart { border: 1px solid var(--gris-bord); border-radius: 8px; padding: 12px;
  background: var(--blanc); margin-top: 12px; font-size: .9rem }
.etat-o13 { list-style: none; padding: 0; margin: 8px 0 }
.etat-o13 li { font-size: .85rem; color: var(--gris-txt) }
button.activate { background: var(--instance-accent); color: var(--noir); border: 0;
  border-radius: 8px; padding: 10px 16px; cursor: pointer; font-weight: 700 }

/* ---------- IDENTITÉ : saisie et APERÇU (STORY-263) ---------- */
.ident-form{display:grid; gap:6px; margin-bottom:14px}
.ident-form label{font-size:12px; font-weight:700; letter-spacing:var(--ls); color:var(--gris-txt)}
.ident-form input[type=text]{padding:8px 10px; border:1px solid var(--gris-bord); border-radius:8px; font:inherit}
.ident-form input[type=color]{width:56px; height:32px; padding:2px; border:1px solid var(--gris-bord); border-radius:8px}
.ident-contraintes{margin:0; font-size:12px; color:var(--gris-txt)}
.ident-avertissement:empty, .ident-refus-slot:empty{display:none}
.ident-avertissement{margin:6px 0 0; font-size:12px; color:var(--noir); background:#FFF6E5;
  border-left:3px solid var(--cta); padding:6px 10px; border-radius:0 6px 6px 0}
.ident-refus{margin:6px 0 0; font-size:12px; color:#c0392b}
/* ⚠️ Le volet porte les jetons EN LOCAL (attribut `style`) — jamais `:root` :
   repeindre toute l'application pour une valeur non enregistrée laisserait
   l'interface dans un état que la base ne connaît pas si le parcours est
   abandonné. */
.ident-mention{margin:0 0 6px; font-size:12px; font-weight:700; color:var(--gris-txt)}
.ident-apercu{display:flex; align-items:center; gap:10px; padding:14px;
  border:1px dashed var(--gris-bord); border-radius:10px; background:var(--blanc)}
.ident-apercu .ident-logo{width:40px; height:40px; object-fit:contain; border-radius:8px}
.ident-apercu .ident-nom{font-weight:700; color:var(--instance-primary)}
.ident-apercu .ident-tag{font-size:12px; color:var(--gris-txt)}

/* ⚠️ L'avertissement de sauvegarde est DISTINCT de « irréversible » : le
   premier dit qu'on ne peut pas revenir, le second qu'aucun filet n'existe.
   Les fondre laisserait croire qu'une copie traîne quelque part. */
.dz-avert-backup{border-left:3px solid #c0392b; padding-left:10px; font-weight:700}

/* ⚠️ BLOCAGE de corpus non fondé (décision JMA 2026-08-08) — distinct de
   `.corpus-attente` : celle-ci informe d'une ingestion en cours, celui-ci dit
   que RIEN ne fonctionne. Les fondre laisserait croire qu'il suffit d'attendre. */
.corpus-bloque{display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  margin:0 0 18px; padding:12px 16px; border-radius:10px;
  background:#FFF6E5; border-left:4px solid var(--cta); font-size:13.5px}
.corpus-bloque b{color:var(--noir)}


/* ── Écran Catalogue (STORY-275) ────────────────────────────────────────────
   ⚠️ STORY-274 avait livré cet écran avec ZÉRO règle pour 8 classes émises :
   il était câblé, testé, en CI verte — et non stylé. La sentinelle
   `tests/test_css_catalogue.py` ferme cet angle mort, qu'aucune garde du dépôt
   ne couvrait (elles vérifient le câblage, jamais l'apparence). */
.cat-bandeau { display:flex; flex-wrap:wrap; gap:8px; margin:12px 0 4px }
.cat-chip { background:var(--gris-bg); border:1px solid var(--gris-bord); border-radius:14px;
            padding:4px 12px; font-size:12px; letter-spacing:var(--ls) }
.cat-chip b { color:var(--teal); font-size:14px; margin-right:4px }
.cat-note { color:var(--gris-txt); font-size:12px; margin:6px 0 10px; max-width:70ch }
.cat-msg { color:var(--gris-txt); font-size:12px; margin:8px 0 }
.cat-echec { color:var(--rouge, #c0392b); font-size:12px; margin:8px 0 }
.cat-total { color:var(--gris-txt); font-size:12px; margin:6px 0 }
.cat-barre { margin:10px 0 }
.cat-q { width:100%; max-width:420px; padding:7px 10px; font-size:13px;
         border:1px solid var(--gris-bord); border-radius:4px;
         background:var(--gris-bg); color:inherit }
.cat-table { overflow-x:auto; margin-top:6px }
.cat-table table { width:100%; border-collapse:collapse; font-size:13px }
.cat-table th { text-align:left; font-weight:600; font-size:11px;
                           letter-spacing:var(--ls); text-transform:uppercase;
                           color:var(--gris-txt); border-bottom:1px solid var(--gris-bord);
                           padding:6px 8px }
.cat-table td { padding:6px 8px;
    border-bottom:1px solid var(--gris-bord) }
/* ⚠️ En-tetes TRIABLES — patron de l'Audit, classes propres : son CSS est
   scope sous `.audit-table` (« pas de fuite de style »), et l'adopter ferait
   heriter un min-width:980px pour 4 colonnes. */
.cat-table thead th { cursor:pointer; user-select:none; white-space:nowrap }
.cat-table thead th:hover, .cat-table thead th:focus { color:var(--teal) }
.cat-tri { font-size:9px; margin-left:3px; color:var(--teal) }
.cat-no { white-space:nowrap; color:var(--gris-txt) }
.cat-table tbody tr:hover { background:var(--gris-bg) }
.cat-titre { font-weight:500 }
/* ⚠️ L'absence se NOMME : 494 articles sur 627 n'ont pas de rubrique, 149 pas
   d'auteur. Un blanc se lirait comme une perte. */
.cat-vide { color:var(--gris-txt); font-style:italic; font-size:12px }
.cat-src { width:100%; border-collapse:collapse; font-size:13px; margin:8px 0 }
.cat-src td, .cat-src th { padding:5px 8px; border-bottom:1px solid var(--gris-bord);
                           text-align:left }
.cat-major b, .cat-major { font-weight:600 }
.cat-minor { color:var(--gris-txt) }
.cat-fix { font-size:12px; margin:8px 0 4px }
.cat-files { margin:0 0 8px 18px; font-size:12px; color:var(--gris-txt) }
.cat-plus { font-size:12px; color:var(--gris-txt) }
.cat-warn { font-size:12px; margin:10px 0 4px }
.cat-head, .cat-actions { margin:8px 0 }
.cat-actions button { margin-right:8px }
.cat-resultat { margin-top:10px }
.cat-l { display:flex; justify-content:space-between; max-width:520px;
         padding:3px 0; font-size:13px; border-bottom:1px solid var(--gris-bord) }

/* ⚠️ TROUVÉES par l'élargissement de la sentinelle CSS : ces deux classes sont
   émises par le GABARIT (panneau Gouvernance → Reconstruction du catalogue) et
   n'avaient aucune règle — l'angle mort exact que la garde prétendait fermer,
   sur un médium qu'elle ne lisait pas. */
.cat-simuler { }
.cat-appliquer { background:var(--cta); color:var(--noir); border:none;
                 border-radius:4px; padding:6px 14px; cursor:pointer;
                 font-size:13px; letter-spacing:var(--ls) }
.cat-appliquer:hover { filter:brightness(1.06) }

/* ===== MARVIA — Gouvernance, onglet « Constitution » (STORY-291, UX-DR2). =====
   La frontière VISUELLE des natures est aussi une frontière de droits :
   l'exécutable (garanti par le code, lecture seule) ne ressemble jamais à une
   intention (déclarative, éditable en 55.7). */
.cst-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.cst-export { font-size: 13px; text-decoration: underline; cursor: pointer; }
.cst-etat { margin: 8px 0; color: var(--muted, #66707a); }
.cst-verdict { margin: 8px 0; }
/* CR épic [0] : la classe est posée par le JS sur .cst-verdict-corps — la règle
   doit viser CET élément, sinon le sélecteur ne matche jamais et un verdict
   dégradé garde la bordure verte. */
.cst-verdict-corps { padding: 8px 10px; border-left: 3px solid var(--ok, #2e7d32); }
.cst-verdict-corps.cst-degrade { border-left-color: var(--warn, #A26100); }
.cst-anterieurs-ligne { margin: 6px 0; color: var(--muted, #66707a); }
.cst-anterieurs { font-weight: 600; }
.cst-articles { margin-top: 10px; }
.cst-nature { margin: 10px 0; padding: 8px 10px; border-radius: 6px; }
.cst-nature-executable { background: rgba(46, 125, 50, 0.08); border: 1px solid rgba(46, 125, 50, 0.35); }
.cst-nature-politique { background: rgba(2, 119, 189, 0.08); border: 1px solid rgba(2, 119, 189, 0.35); }
.cst-nature-intention { background: rgba(123, 31, 162, 0.08); border: 1px dashed rgba(123, 31, 162, 0.45); }
.cst-nature h3 { margin: 0 0 6px; font-size: 14px; }
.cst-badge { font-size: 11px; padding: 1px 6px; border-radius: 8px; background: rgba(0, 0, 0, 0.12); margin-left: 6px; }
.cst-article { margin: 6px 0; }
.cst-clause { font-weight: 500; }
.cst-raison { color: var(--muted, #66707a); font-size: 13px; }
.cst-matrice table, .cst-versions table { width: 100%; border-collapse: collapse; margin-top: 8px; }
.cst-matrice th, .cst-matrice td, .cst-versions th, .cst-versions td {
  text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--line, #e0e0e0); font-size: 13px;
}
.cst-coord { font-family: monospace; font-size: 12px; }
.cst-verdict-corps { font-size: 14px; }
.cst-noncouvertes, .cst-orphelines { color: var(--warn, #A26100); font-size: 13px; margin-top: 4px; }
.cst-preambule { font-style: italic; color: var(--muted, #66707a); margin-top: 6px; }
/* STORY-292 — l'éditeur du déclaratif. */
.cst-actions { display: flex; gap: 8px; align-items: center; }
.cst-init { font-weight: 600; }
.cst-editer { font-size: 13px; }
.cst-editeur { margin-top: 10px; padding: 10px; border: 1px dashed var(--pale, #ccc); border-radius: 6px; }
.cst-edit-preambule { width: 100%; min-height: 60px; }
.cst-edit-raison, .cst-edit-clause { width: 100%; min-height: 40px; margin: 4px 0; }
.cst-edit-article { margin: 8px 0; }
.cst-edit-ajout { margin-top: 10px; }
.cst-enregistrer { margin-top: 10px; font-weight: 600; }
.cst-ajout-intention { font-size: 13px; }
.cst-neuve-id { width: 100%; margin: 4px 0; }
.cst-neuve-clause, .cst-neuve-raison { width: 100%; min-height: 40px; margin: 4px 0; }

/* STORY-326 — commandes de taille du graphe. Boutons d'ACTION (pas de bascule) :
   pas d'état `is-active`, et `:disabled` aux bornes plutôt qu'un clic sans effet. */
.mg-zooms{display:flex; align-items:center; gap:8px; margin:8px 0}
.mg-zoom-btn{all:unset; cursor:pointer; padding:3px 10px; border:1px solid var(--gris-bord);
  border-radius:6px; font-size:13px; font-weight:700; line-height:1.6; min-width:14px;
  text-align:center}
.mg-zoom-btn:hover:not(:disabled),.mg-zoom-btn:focus-visible{border-color:var(--cyan); color:var(--cyan-txt)}
.mg-zoom-btn:disabled{opacity:.4; cursor:default}
.mg-zoom-fit{font-weight:400; letter-spacing:var(--ls)}
.mg-zoom-pct{font-size:12px; min-width:44px; text-align:center; color:var(--gris-txt)}

/* STORY-327 — mot de passe régénéré, affiché UNE SEULE FOIS. Registre d'alerte
   (pas un toast : il doit rester à l'écran le temps d'être copié). */
.ga-mdp{border:1px solid var(--cyan); border-radius:8px; padding:10px 12px; margin:10px 0}
.ga-mdp-val{display:block; margin:6px 0; padding:6px 8px; background:var(--gris-bg);
  border-radius:6px; font-family:monospace; font-size:14px; user-select:all}
/* ⚠️ `--gris-txt`, jamais `--pale` : sur fond clair, --pale donne ~1,4:1 — et c'est
   la ligne dont la NON-LECTURE est irrécupérable (revue d'épic, constat 10). */
.ga-mdp-note{font-size:12px; color:var(--gris-txt); margin:0}
.ga-password{all:unset; cursor:pointer; padding:2px 8px; border:1px solid var(--gris-bord);
  border-radius:6px; font-size:12px; background:#fff}
.ga-password:hover,.ga-password:focus-visible{border-color:var(--cyan); color:var(--cyan-txt)}

/* ============================================================
   Retours de bêta-testeurs (EPIC-068, STORY-331/332).
   ⚠️ Sans ces règles, le formulaire et l'onglet Retours seraient rendus
   NUS : le HTML existe, les classes sont posées, et l'écran paraît cassé
   sans qu'aucun test ne rougisse (les harnais vérifient le balisage, pas
   la feuille de style).
   ============================================================ */

/* --- La barre sous une réponse (écran Recherche) --- */
.ms-fb { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line, #d5d9e0); }
.ms-fb-open {
  background: transparent; border: 1px solid var(--line, #d5d9e0);
  color: var(--gris-txt, #5a6570); border-radius: 4px;
  padding: 5px 12px; font-size: 12.5px; cursor: pointer;
}
.ms-fb-open:hover { border-color: var(--cyan); color: var(--cyan-txt); }
.ms-fb-form { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
/* ⚠️ SANS cette règle, le formulaire est VISIBLE dès le rendu : `display:flex`
   d'auteur BAT le `[hidden]{display:none}` de la feuille du navigateur, et
   l'attribut `hidden` posé par le JS devient décoratif. Le dépôt connaissait déjà
   le piège (`.ms-params[hidden]`, `.ms-params-state[hidden]`) — il a été rejoué.
   Gardé par `tests/js/marvia-hidden.test.js`. */
.ms-fb-form[hidden] { display: none; }
.ms-fb-verdicts { display: flex; flex-wrap: wrap; gap: 6px; }
.ms-fb-v {
  background: transparent; border: 1px solid var(--line, #d5d9e0);
  border-radius: 14px; padding: 4px 11px; font-size: 12px; cursor: pointer;
}
.ms-fb-v.is-on { background: var(--cyan); border-color: var(--cyan); color: #fff; }
.ms-fb-text {
  width: 100%; border: 1px solid var(--line, #d5d9e0); border-radius: 4px;
  padding: 8px; font: inherit; font-size: 13px; resize: vertical;
}
/* ⚠️ Cette mention DIT ce qui part avec le commentaire : elle ne doit jamais
   devenir invisible (pas de `display:none`, pas de taille sous 11px). */
.ms-fb-dit { font-size: 11.5px; color: var(--gris-txt, #5a6570); margin: 0; font-style: italic; }
.ms-fb-send { align-self: flex-start; }
.ms-fb-send[disabled] { opacity: .5; cursor: not-allowed; }
.ms-fb-merci { font-size: 12.5px; color: var(--teal); margin: 0; }
.ms-fb-vide { font-size: 12px; color: var(--gris-txt, #5a6570); margin: 0; }

/* --- L'onglet Retours (Gouvernance) --- */
.fb-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.fb-stats { font-size: 12.5px; color: var(--gris-txt, #5a6570); margin: 0 0 12px; }
.fb-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.fb-item { border: 1px solid var(--line, #d5d9e0); border-radius: 6px; padding: 12px; }
.fb-head { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; font-size: 12px; }
.fb-verdict { font-weight: 600; color: var(--teal); }
.fb-statut { border-radius: 10px; padding: 1px 9px; background: #eef1f4; }
.fb-statut-nouveau { background: var(--cyan); color: #fff; }
/* Classement suspendu faute de vocabulaire (STORY-333) : la liste reste lisible,
   seul le tri est indisponible — l'avis se distingue d'un « aucun retour ». */
.fb-vocab-ko { color: var(--gris-txt, #5a6570); font-style: italic; }
.fb-date, .fb-niveau { color: var(--gris-txt, #5a6570); margin-left: auto; }
.fb-question { font-size: 13px; margin: 8px 0 4px; }
.fb-comment { font-size: 13px; margin: 0 0 8px; white-space: pre-wrap; }
.fb-comment.fb-vide { color: var(--gris-txt, #5a6570); font-style: italic; }
.fb-answer { font-size: 12.5px; white-space: pre-wrap; background: #f7f8fa; padding: 8px; border-radius: 4px; overflow-x: auto; }
.fb-trace { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; font-size: 12px; margin: 8px 0 0; }
.fb-trace dt { color: var(--gris-txt, #5a6570); }
.fb-trace dd { margin: 0; }
.fb-trace-absente { font-size: 12px; color: var(--gris-txt, #5a6570); font-style: italic; margin: 8px 0 0; }
.fb-actions { display: flex; gap: 8px; margin-top: 10px; }
.fb-empty { color: var(--gris-txt, #5a6570); font-size: 13px; }
/* Classes manquantes relevées par la garde dérivée (revue d'épic EPIC-068). */
.fb-detail { margin-top: 8px; font-size: 12.5px; }
.fb-detail summary { cursor: pointer; color: var(--cyan-txt); }
.fb-del { margin-left: auto; }
.fb-f-statut, .fb-f-since, .fb-f-until {
  border: 1px solid var(--line, #d5d9e0); border-radius: 4px;
  padding: 4px 8px; font: inherit; font-size: 12.5px;
}
.fb-stats-zone { min-height: 18px; }
.fb-more { margin-top: 12px; }
/* Repli du vocabulaire des retours (hors-plan) : un message sans sortie est un
   cul-de-sac — le bouton « Réessayer » doit se voir. */
.ms-fb-retry {
  background: transparent; border: 1px solid var(--cyan); color: var(--cyan-txt);
  border-radius: 4px; padding: 2px 9px; font-size: 11.5px; cursor: pointer;
}

/* ═══ STORY-374 — LES SIX QUI SE DÉRIVENT ═══════════════════════════════════════
   ⚠️ CHAQUE règle cite son FRÈRE et la RAISON d'en être un — pas « dérivé de »,
   mais POURQUOI. Sans cela, une invention est indiscernable d'une dérivation à la
   relecture, et l'escalade d'EPIC-074 disait justement qu'écrire du CSS est un
   acte de conception.

   ⚠️ AUCUNE nuance ni variable NEUVE : chaque valeur vient du frère.
   ⚠️ `var(--x, repli)` est PROSCRIT ici — six variables fantômes vivent déjà ainsi
   dans cette feuille (`--line`, `--gris-brd`…), la forme avec repli échappant à la
   garde des variables. On n'en propage pas une septième. */

/* frère : `.gc-cand-body{flex:1 1 auto}` — les DEUX sont enfants directs du même
   `.gc-cand`, qui est `display:flex`. Un `flex:1 1 auto` en face appelle
   littéralement un `flex:none` : l'en-tête ne s'étire pas, le corps prend le reste. */
.gc-cand-head { flex: none; }

/* frère : `.mg-d-o-type` et `.mg-d-o-cnt` — TROIS `<span>` frères dans le même
   `<li>`. Le type est en `--gris-txt` 11px, le compte en `--cyan` gras ; le nom est
   la donnée principale, donc `--noir` au corps de texte.
   ⚠️ PAS de `display:block` : `.mg-d-o-cnt` est en `float:right` et en sortirait. */
.mg-d-o-name { color: var(--noir); font-weight: 700; }

/* frère : `.ms-apport` — MÊME BLOC `.ms-deep`, appelée à trois lignes d'écart de
   `apportNoteHtml` / `tronqueeNoteHtml` / `deepGraphNoteHtml`. QUATRE règles de ce
   bloc portent déjà `#667` + `0.88rem` : s'en écarter créerait une cinquième nuance.
   ⚠️ PIÈGE DE NOM : `.ms-tronquee` est OCRE — c'est la troncature de GÉNÉRATION.
   « Dossier borné » est un constat NEUTRE, pas un avertissement. */
.ms-deep-trunc { color: #667; font-size: 0.88rem; margin-bottom: 8px; }

/* frères : `.jrn-more` ET `.fb-more` (`margin-top:12px`) — les DEUX AUTRES « Voir
   plus » du produit, même libellé, même rôle de pagination.
   ⚠️ PAS `.btn-param` : c'est la bascule « Paramètres » de la Recherche (`all:unset`
   + bordure + `inline-flex`). Le préfixe `btn-` est un FAUX critère — il aurait rendu
   ce bouton différent de ses deux jumeaux.
   ⚠️ Et PAS de `display:` : ce bouton est masqué par un `style="display:none"` que le
   JS remet à `""` ; en poser un ici n'aiderait pas, et `.jrn-more` n'en pose aucun. */
.btn-more { margin-top: 12px; }

/* frère : `.cst-actions` — MÊME GABARIT, barre d'actions d'un panneau, même rôle. */
.st-actions { display: flex; gap: 8px; align-items: center; }

/* frère : `.gc-form` — même `<div>` + `<h4>` dans le MÊME `.gc-dossier`, dont le
   `h4` est déjà stylé par `.gc-dossier h4`. Seule manque la mise en colonne.
   ⚠️ PAS `.gc-list` : c'est le `<ul>` de la file d'attente, au niveau PANNEAU — un
   autre écran, un autre objet. */
/* ⚠️ REVUE D'ÉPIC : `gap: 6px` DOUBLAIT l'espacement. Les marges ne s'effondrent pas
   dans un conteneur flex, et `.gc-cand` porte déjà `margin-bottom:6px`, le `<h4>`
   `margin:12px 0 6px` via `.gc-dossier h4` — soit 12 px au lieu de 6, deux fois.
   Le frère `.gc-form` ne s'en sort que parce que `.gc-fld` n'a aucune marge propre. */
.gc-cands { display: flex; flex-direction: column; margin-top: 8px; }

/* ═══ STORY-375 — LES QUATRE BADGES, DÉCIDÉS ENSEMBLE ═══════════════════════════
   ⚠️ `badgesHtml` en émet SIX, pas quatre : « structure actuelle » et un par
   standard sont rendus NUS. Les quatre modificateurs doivent se distinguer DES
   NUES autant qu'entre eux — mon premier jet rendait `stable` indiscernable d'eux.

   ⚠️ HIÉRARCHIE PAR LE REMPLISSAGE, jamais par la teinte : aplat sombre > pâle
   bordé > gris plein > contour seul. Deux gris qui ne différeraient que de teinte
   se confondraient entre eux ET avec les nues.

   ⚠️ LE SOCLE `.badge` ÉCHOUE AA — `--cyan` sur `--pale` = 2,79:1, quand un badge
   de 11px gras est un texte NORMAL (seuil 4,5:1). Il n'est PAS corrigé ici : le
   repeindre change TOUS les écrans, c'est un arbitrage. Les quatre règles
   ci-dessous passent toutes AA, donc chacune AMÉLIORE ce dont elle hérite.

   ⚠️ `.badge.X` et jamais `.X` seul : `.beta{}` a la MÊME spécificité que `.badge`
   et ne gagnerait que par l'ordre source. Le dépôt porte déjà deux règles rendues
   inertes par la cascade — défaut mesuré en 77.2.

   ⚠️ AUCUN `dashed` : le dépôt l'emploie 7 fois, pour « zone d'accueil / vide /
   éditable », jamais pour « provisoire ». */

/* LE CHOIX DE L'USAGER — il doit dominer les cinq autres.
   Forme de `.fb-statut-nouveau` (aplat plein + texte blanc).
   ⚠️ `--teal` et non `--cyan` : le cyan plein est à 3,85:1, sous AA.
   contraste mesuré : #FFF sur --teal = 9,28:1 */
.badge.sel-badge { background: var(--teal); color: var(--blanc); }

/* MATURITÉ NON ÉPROUVÉE — la seule alerte de la ligne.
   `.gk-contested` VERBATIM (ocre de charte, bordure PLEINE).
   contraste mesuré : #8A6D2F sur #FBF6EE = 4,53:1 */
.badge.beta { background: #FBF6EE; color: #8A6D2F; border: 1px solid #F0E2C8; }

/* MATURITÉ ACQUISE — présente, sans alerte. `.gk-superseded` VERBATIM.
   contraste mesuré : --gris-txt sur --gris-bg = 5,12:1 */
.badge.stable {
  background: var(--gris-bg);
  color: var(--gris-txt);
  border: 1px solid var(--gris-bord);
}

/* FAIT INFORMATIF — le plus léger : contour seul, aucun remplissage.
   C'est ce qui le distingue de `stable` sans changer de teinte.
   contraste mesuré : --gris-txt sur --blanc (fond de `.pack`) = 5,57:1 */
.badge.defaut {
  background: transparent;
  color: var(--gris-txt);
  border: 1px solid var(--gris-bord);
}

/* ═══ STORY-376 — LES DERNIÈRES ═══════════════════════════════════════════════════
   ⚠️ Trois classes ont été RETIRÉES du balisage plutôt que stylées (mortes : ni
   règle, ni crochet, ni `id`, ni test dans les trois médiums). Trois autres sont
   EXEMPTÉES : la cascade les style déjà, et leur écrire une règle de classe serait
   INERTE — le prédicat de la garde est par NOM, il ne voit pas la cascade. */

/* frère : `.mg-d-o-name` (STORY-374) — même rôle à une autre échelle : l'une nomme
   le nœud sélectionné, l'autre l'autre extrémité d'une relation.
   ⚠️ Je l'avais classée « sans frère » : ce frère a été écrit deux commits plus tôt,
   dans le même épic. */
.mg-d-name { color: var(--noir); font-weight: 700; }

/* frères : `.stx-grad-x{text-anchor:middle}` / `.stx-grad-y{text-anchor:end}` — le
   couple d'ancrage existait DÉJÀ pour les graduations.
   ⚠️ PAS de `fill` : `.stx-titre` le porte, et ces classes l'accompagnent toujours
   (`class="stx-titre stx-titre-x"`) — le re-déclarer serait redondant. Ce qui
   distingue un titre d'axe X d'un titre d'axe Y, c'est l'ANCRAGE. */
/* ⚠️ REVUE D'ÉPIC : ma première rédaction posait `dominant-baseline: hanging` sur l'axe
   Y — une propriété qui n'existe NULLE PART ailleurs dans cette feuille, donc une
   INVENTION, contre la justification « dérivé des frères » de cette même règle. Et sur
   un `<text transform="… rotate(-90)">`, `hanging` décale le glyphe VERS le graphe :
   la garde aux étiquettes de graduation tombait de ~13 à ~5,5 px, et « 1 200 k » entrait
   en collision.
   ⚠️ Les deux titres portent le même ancrage — c'est leur `transform` qui les distingue,
   pas le CSS. Une règle qui n'ajoute rien au frère `.stx-titre` est INUTILE : seul
   `text-anchor` mérite d'être posé, et il l'est déjà par `.stx-titre` ? Non — vérifié,
   `.stx-titre` porte `text-anchor:middle`. Ces deux règles sont donc RETIRÉES. */

/* frère : `.sx-proj` — `sx-periode` l'accompagne TOUJOURS
   (`class="sx-proj sx-periode"`).
   ⚠️ REVUE D'ÉPIC : ma première rédaction REDÉCLARAIT `display`, `flex-wrap`, `gap` et
   `align-items` — à SPÉCIFICITÉ ÉGALE et PLUS BAS, donc elle GAGNAIT : le `gap` passait
   de 18 à 8 px et l'alignement de `flex-end` à `center`, décollant les deux boutons
   `.sx-refresh` (~28 px) du bas des champs de date (~49 px). ⚠️ Et son commentaire
   annonçait « borne la largeur » alors qu'elle ne déclarait AUCUNE largeur.
   ⚠️ Un modificateur ne REDÉCLARE pas son socle : il n'ajoute que ce qui le distingue.
   Ici, rien à ajouter — le bloc de période est un bloc de projection ordinaire, et la
   classe sert de crochet de sélection. Elle est donc RETIRÉE du CSS ; l'inventaire la
   verra comme un modificateur du socle `.sx-proj`, ce qu'elle est. */

/* LE SEUL ACTE DE CONCEPTION de la story — `st-num` n'a aucun frère.
   ⚠️ Sa cascade est PARTIELLE : `.st-toggle input:focus` le matche DÉJÀ (il vit dans
   un `<label class="st-toggle">`), donc le focus est traité et n'est PAS redéclaré.
   Seule la base se décide, et `.sx-proj input` est le précédent d'input habillé de
   cette feuille.
   contraste mesuré : --noir sur --blanc = 14,70:1 */
.st-num {
  width: 90px;
  padding: 4px 6px;
  border: 1px solid var(--gris-bord);
  border-radius: 6px;
  font-family: var(--font);
  font-size: 13px;
  color: var(--noir);
}
