/* ============================================================
   CaptainContext — thème "carte marine"
   Papier froid, encre marine, accent sarcelle, mono = journal de bord
   ============================================================ */

:root {
  --paper: #eef1ee;
  --card: #ffffff;
  --ink: #182b3a;
  --ink-2: #53636f;
  /* V8.57 — `--ink-3` ÉTAIT SOUS LE SEUIL D'ACCESSIBILITÉ, ET DEPUIS TOUJOURS.
     #8795a0 sur blanc donne 3,07:1 ; WCAG AA demande 4,5:1 pour du texte
     courant. Ce jeton habille les en-têtes de tableau, les textes d'aide, les
     dates, les libellés secondaires — c'est-à-dire beaucoup de choses qu'on
     lit vraiment. Le défaut n'a rien à voir avec le thème sombre ; c'est le
     banc de contraste écrit pour LUI (tests/v8.57_theme.mjs) qui l'a trouvé,
     en mesurant aussi le thème clair. On assombrit d'un cran : 4,95:1 sur le
     blanc des cartes, 4,61:1 sur les surfaces enfoncées. La nuance reste
     nettement plus pâle que `--ink-2`, donc la hiérarchie visuelle ne bouge
     pas — seule la lisibilité monte. */
  --ink-3: #64727d;
  --line: #d4dcd9;
  --line-soft: #e4e9e7;
  --accent: #0f7583;
  --accent-fonce: #0b5a65;
  --accent-pale: #e2eff0;
  --danger: #a03d2c;
  --danger-pale: #f6e8e4;
  --ok: #3d7a46;

  --st-ouvert: #8a6a16;
  --st-actif: #0f7583;
  --st-resolu: #3d7a46;
  --st-abandonne: #8a4b3b;
  --st-remplace: #6b6f76;

  /* ============================================================
     V8.57 — LES JETONS QUI MANQUAIENT POUR QUE LE THÈME SOMBRE TIENNE.

     Le thème sombre existait depuis la V8.33 (app2.css) et ne redéfinissait
     que des JETONS — c'était la bonne méthode. Elle supposait seulement que
     les règles en utilisent. Or cette feuille en contenait DEUX CENT
     QUATRE-VINGT-CINQ couleurs écrites en dur, invisibles tant qu'on reste en
     clair, et qui ne suivaient rien.

     ⚠ ET UNE INVERSION, QUI EXPLIQUE LE PIRE DÉFAUT VISIBLE. `.topbar` posait
       `background: var(--ink)` — l'ENCRE comme fond, ce qui est juste tant que
       l'encre est sombre. En thème sombre, `--ink` devient CLAIR (#e7edf0) :
       le bandeau devenait donc blanc, seule surface éclatante de l'écran, et
       le nom du produit — écrit en blanc — y disparaissait. Un jeton nommé
       d'après ce qu'il EST (« l'encre ») employé pour ce qu'il VAUT (« du
       foncé ») : la confusion se paie exactement au moment où la palette
       s'inverse. D'où `--topbar` et `--topbar-txt`, nommés par leur rôle.

     Les noms sont ceux qu'app2.css emploie déjà pour la v2 — on n'invente pas
     un second vocabulaire, on complète celui-ci pour que la base le parle
     aussi. Valeurs identiques au thème clair : rien ne change à l'écran
     aujourd'hui, tout devient inversable demain.
     ============================================================ */
  --sunk: #f6f7f6;          /* survol, en-tête de tableau, surface enfoncée */
  --sunk-2: #eff1ef;        /* pastille, bouton fantôme au survol */
  --side-bg: #182b3a;       /* la navigation (foncée en v1, claire en v2) */
  --input-bg: #ffffff;      /* le fond des champs de saisie */
  --topbar: #182b3a;        /* le bandeau — un RÔLE, pas « l'encre » */
  --topbar-txt: #e9eef0;
  --topbar-ligne: #3b5062;  /* les bordures DANS le bandeau */
  --topbar-attenue: #90a3b0;/* les placeholders et icônes du bandeau */
  --topbar-vif: #7fc6ce;    /* le survol et la 2ᵉ moitié du mot-marque */
  --warn: #8a6a16;
  --warn-pale: #f7f0dd;
  --ok-pale: #e6efe7;
  --live: #2f9e5c;          /* présence : quelqu'un est là maintenant */
  /* ⚠ `--accent-plein` N'EST PAS UN DOUBLON DE `--accent`, ET C'EST LE THÈME
     SOMBRE QUI L'A RÉVÉLÉ. `--accent` sert à DEUX choses opposées : peindre du
     texte et des filets sur le papier (il doit alors être FONCÉ pour se
     détacher), et remplir des boutons pleins sous du texte blanc (il doit
     alors être assez foncé pour que le blanc s'y lise). En thème clair, une
     seule valeur satisfait les deux. En sombre, l'accent doit s'éclaircir pour
     rester lisible sur fond marine — et le blanc posé dessus tombe alors à
     2,9:1, sous le seuil d'accessibilité. Deux emplois, deux jetons : les
     boutons pleins prennent `--accent-plein`, identique à `--accent` en clair
     et volontairement plus profond en sombre. */
  --accent-plein: #0f7583;
  --sur-accent: #ffffff;    /* le texte posé SUR --accent-plein */

  --prive: #6b4f9e;         /* le privé — violet, V5.6 */
  --prive-pale: #f2eefa;
  --ombre: 0 1px 2px rgba(24, 43, 58, .05);
  --ombre-flot: 0 8px 28px rgba(24, 43, 58, .14);

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --r: 6px;
  --sidebar-w: 292px;

  /* ⚠ `color-scheme` N'EST PAS DÉCORATIF. Il dit au NAVIGATEUR quel thème est
     en vigueur, et c'est lui — pas nos règles — qui repeint ce que la CSS ne
     touche pas : le menu déroulant natif d'un `<select>` ouvert, les
     ascenseurs, le curseur de saisie, l'autofill, les cases à cocher, le fond
     par défaut d'un `<input>`. Sans lui, un thème sombre garde des listes
     déroulantes blanches et des ascenseurs clairs, et aucune quantité de CSS
     n'y change quoi que ce soit. La valeur sombre est posée avec les autres
     jetons du thème (app2.css). */
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink);
  background: var(--paper);
  /* lignes de sonde très discrètes, façon carte marine */
  background-image: linear-gradient(transparent 31px, rgba(24, 43, 58, 0.025) 32px);
  background-size: 100% 32px;
}
a { color: var(--accent-fonce); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font: inherit; cursor: pointer; }
/* ⚠ UN CHAMP SANS `background` N'EST PAS TRANSPARENT : LE NAVIGATEUR LUI EN
   POSE UN BLANC. C'était l'un des défauts les plus visibles du thème sombre —
   champs éclatants, texte pâle dedans, illisible — et il ne venait d'aucune
   règle de cette feuille, mais de leur absence : on ne peut pas corriger ce
   qu'on n'a jamais écrit. On habille donc ici TOUS les champs, une fois.

   ⚠ ON RESTE À LA SPÉCIFICITÉ D'UN SÉLECTEUR D'ÉLÉMENT (pas de `:not()`, qui
     la ferait monter) : des dizaines de règles plus bas reposent sur le fait
     que celle-ci cède, à commencer par les champs transparents du tableur et
     par `input:disabled` (lecture seule). La ligne d'après suffit à rendre aux
     cases à cocher et aux boutons radio leur fond natif — eux sont dessinés
     par le navigateur (`color-scheme`) et un fond imposé écrase l'état coché. */
/* V8.57 — LE FOND, LA COULEUR *ET* LA TEINTE DU TRAIT.
   Sans `background`, un champ garde le blanc que le navigateur lui donne :
   c'était l'un des trois défauts visibles du thème sombre (champ blanc, texte
   pâle dedans, illisible). Et sans `border-color`, il garde le trait par
   DÉFAUT du navigateur — que `color-scheme: dark` éclaircit, ce qui cerne
   chaque champ d'un liseré blanc sur fond marine. On ne touche ni à l'épaisseur
   ni au style du trait : seulement à sa teinte, pour ne pas déplacer d'un pixel
   les centaines de champs qui posent déjà leur propre bordure. */
input, select, textarea {
  font: inherit; color: var(--ink); background: var(--input-bg); border-color: var(--line);
}
input[type="checkbox"], input[type="radio"] { background: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

/* ---------- Coquille ---------- */
#app { display: flex; height: 100vh; }

.topbar {
  position: fixed; top: 0; left: 0; right: 0; height: 52px; z-index: 40;
  display: flex; align-items: center; gap: 14px; padding: 0 16px;
  background: var(--topbar); color: var(--topbar-txt);
  border-bottom: 3px solid var(--accent);
}
/* V8.54 — LE MOT-MARQUE N'EST PLUS EN MONOSPACE.
   `var(--mono)` est une PILE, pas une police : elle rend SF Mono sur macOS,
   Consolas sur Windows, Liberation Mono sur Linux. Trois dessins, trois
   chasses, trois largeurs pour le même mot — et celui qu'on voit le plus
   souvent, Consolas, donne au nom du produit l'allure d'un chemin de fichier.
   Un mot-marque doit avoir UNE forme, la même partout.

   La pile sans est déjà celle de toute l'interface, et ses polices (Segoe UI,
   SF, Roboto) sont dessinées pour être lues en gras à petite taille. On
   resserre l'interlettrage — un mot-marque se soude, il ne s'espace pas — et
   on monte d'un point pour compenser la chasse plus étroite du sans.

   ⚠ LA MONO NE BOUGE PAS AILLEURS. Codes de publication, identifiants,
     chemins, formules : là elle dit « ceci se recopie caractère par
     caractère », et c'est son emploi exact. Ce n'était simplement pas ce que
     disait le nom du produit.

   V8.55 — L'INTERLETTRAGE REVIENT À ZÉRO. Non, ce n'étaient pas des films :
   -0.015em à 16 px fait bien un quart de pixel de moins entre chaque lettre,
   et « relieo » est le pire mot possible pour ça — l·i·e sont trois traits
   verticaux consécutifs, et les resserrer les fait lire comme un seul signe.
   Le resserrement est une règle de mot-marque en CAPITALES ou en très grand ;
   à 16 px en bas-de-casse, sur fond sombre (où le texte clair « bave » déjà
   optiquement vers l'extérieur), il ne gagne rien et coûte la lisibilité.
   Reste le corps à 16 px, qui était l'essentiel du gain. */
.marque {
  font-family: var(--sans); font-size: 16px; font-weight: 700;
  /* V8.57 — CE BLANC RESTE UN BLANC. Le reste du bandeau est passé aux jetons
     `--topbar*`, mais le mot-marque est du TEXTE POSÉ SUR UNE SURFACE SOMBRE
     dans les deux thèmes : lui donner un jeton de texte le ferait virer au
     foncé le jour où la palette s'inverse — invisible. Même raison partout
     ailleurs dans cette feuille pour un `#fff` sur accent, danger ou bandeau.
     Il est aussi volontairement plus vif que `--topbar-txt` : le nom du
     produit passe devant les libellés qui l'entourent. */
  color: #fff; letter-spacing: 0; white-space: nowrap;
}
/* V7.1 (RELI-430) — le nom du site est SAISI par les gens, il peut être long :
   on borne l'AFFICHAGE (ellipse) plutôt que la saisie — le bandeau ne doit
   jamais céder sous un nom, quel qu'il soit. ~18 caractères visibles ici,
   moins encore à l'écran étroit (media query plus bas). */
.topbar .marque { max-width: 230px; overflow: hidden; text-overflow: ellipsis; }
.marque a { color: inherit; }
.marque .cap { color: var(--topbar-vif); }
.topbar .recherche-globale { flex: 1; max-width: 460px; position: relative; }
.topbar .recherche-globale input {
  width: 100%; padding: 6px 10px 6px 30px; border-radius: var(--r);
  /* V6.2 — `#223càd` (valeur corrompue, ignoree par le parseur) supprimee. */
  border: 1px solid var(--topbar-ligne);
  /* V8.57 — le champ de recherche est un CREUX dans le bandeau : il doit
     s'assombrir avec lui. Aucun jeton ne dit « creux du bandeau », et on n'en
     crée pas un pour un seul emploi : on teinte le fond du bandeau d'un peu de
     sa propre encre claire, ce qui redonne exactement le décrochage d'avant
     dans un thème comme dans l'autre. */
  background: color-mix(in srgb, var(--topbar) 82%, var(--topbar-txt));
  color: var(--topbar-txt); font-size: 13px;
}
.topbar .recherche-globale input::placeholder { color: var(--topbar-attenue); }
.topbar .recherche-globale::before {
  content: "◎"; position: absolute; left: 9px; top: 5px; color: var(--topbar-attenue); font-size: 13px;
}
.topbar .espace { flex: 1; }
.topbar .btn-quitter { background: none; border: 1px solid var(--topbar-ligne); color: var(--topbar-attenue); border-radius: var(--r); padding: 5px 10px; font-size: 12.5px; }
.topbar .btn-quitter:hover { border-color: var(--topbar-vif); color: var(--topbar-txt); }
/* V7.1 (RELI-430) — boutons réservés à l'écran étroit : la loupe (recherche en
   surcouche) et le menu qui recueille compte, Équipe, Admin, thème, Quitter.
   Invisibles au grand écran — le bandeau y est exactement celui d'avant.
   V8.57 — le second porte désormais la VIGNETTE du compte et non un « ⋮ » :
   voir ccBtnMenuMobile() (js/app.js) pour le pourquoi. Il perd donc son
   remplissage horizontal, qui écraserait la vignette. */
.btn-rech-mobile, .btn-menu-mobile {
  display: none; background: none; border: 1px solid var(--topbar-ligne); color: var(--topbar-attenue);
  border-radius: var(--r); padding: 4px 9px; font-size: 15px; line-height: 1.3;
  align-items: center; justify-content: center; /* V7.1b — centre la loupe SVG */
}
.btn-menu-mobile { padding: 3px; border-radius: 50%; }
/* ⚠ La vignette est ronde et pleine : le cadre du bouton ferait un double
   contour. Il n'apparaît qu'au survol et au focus, où il sert vraiment. */
.btn-menu-mobile:has(.cc-avatar) { border-color: transparent; }
.btn-menu-mobile:hover, .btn-menu-mobile:focus-visible { border-color: var(--topbar-vif); }
.btn-rech-mobile:hover, .btn-menu-mobile:hover,
.topbar.rech-ouverte .btn-rech-mobile { border-color: var(--topbar-vif); color: var(--topbar-txt); }

/* ---------- Barre latérale : l'arbre ---------- */
.sidebar {
  width: var(--sidebar-w); min-width: var(--sidebar-w);
  margin-top: 52px; height: calc(100vh - 52px);
  background: var(--card); border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
}
.sidebar-tete {
  padding: 10px 12px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: space-between;
}
.sidebar-tete .eyebrow { margin: 0; }
.eyebrow {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3);
}
.arbre { flex: 1; overflow: auto; padding: 6px 6px 40px; }

.noeud-ligne {
  display: flex; align-items: center; gap: 4px;
  padding: 3px 6px 3px 2px; border-radius: 5px;
  cursor: pointer; user-select: none; position: relative;
  border: 1px solid transparent;
}
.noeud-ligne:hover { background: var(--line-soft); }
.noeud-ligne.actif { background: var(--accent-pale); border-color: var(--line); }
.noeud-ligne.actif .noeud-nom { color: var(--accent-fonce); font-weight: 600; }
/* V2.4 — flèches déplier/replier agrandies (retour d'usage : cible de clic
   trop petite) : zone 26×26 px, glyphe 14 px, survol plus visible. */
.noeud-ligne .pli {
  width: 26px; height: 26px; line-height: 24px; text-align: center;
  color: var(--ink-3); font-size: 14px; border: none; background: none; padding: 0;
  flex: none; border-radius: 5px; cursor: pointer;
}
.noeud-ligne .pli:hover { background: var(--line); color: var(--ink); }
.noeud-ligne .pli.vide { visibility: hidden; }
.noeud-nom { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; }
.noeud-badge {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  background: var(--line-soft); border-radius: 8px; padding: 0 6px; flex: none;
}
.arbre ul { list-style: none; margin: 0; padding: 0 0 0 14px; border-left: 1px solid var(--line-soft); }
.arbre > ul { border-left: none; padding-left: 0; }

/* zones de drop */
.noeud-ligne.drop-into { background: var(--accent-pale); border: 1px dashed var(--accent); }
.noeud-ligne.drop-avant::before, .noeud-ligne.drop-apres::after {
  content: ""; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent);
}
.noeud-ligne.drop-avant::before { top: -1px; }
.noeud-ligne.drop-apres::after { bottom: -1px; }
.noeud-ligne.en-deplacement { opacity: 0.4; }
.drop-racine {
  margin: 10px 8px; padding: 8px; border: 1px dashed var(--line);
  border-radius: var(--r); text-align: center; color: var(--ink-3); font-size: 12px;
  display: none;
}
.drop-racine.visible { display: block; }
.drop-racine.drop-into { border-color: var(--accent); color: var(--accent-fonce); background: var(--accent-pale); }

.sidebar-pied { padding: 10px 12px; border-top: 1px solid var(--line-soft); }

/* ---------- Contenu principal ---------- */
.contenu {
  flex: 1; margin-top: 52px; height: calc(100vh - 52px);
  overflow: auto; padding: 22px 28px 80px;
}
.cap-chemin {
  font-family: var(--mono); font-size: 12px; color: var(--ink-2); margin-bottom: 6px;
}
.cap-chemin a { color: var(--ink-2); }
.cap-chemin a:hover { color: var(--accent-fonce); }
.cap-chemin .sep { color: var(--ink-3); padding: 0 4px; }

h1.titre-page {
  margin: 0 0 4px; font-size: 24px; font-weight: 700; letter-spacing: -0.01em;
  /* V6.2 (RELI-322) — le titre porte desormais des actions a sa droite
     (« Suivre »). Sans flex, le champ en width:100% les repoussait a la ligne.
     .titre-avec-icone posait deja exactement cette regle de son cote.
     PAS de `gap` ici : il ecraserait celui de .titre-avec-icone (h1.titre-page
     est plus specifique), et les libelles portent deja leur espace litteral. */
  display: flex; align-items: center;
}
h1.titre-page input {
  font: inherit; border: none; background: transparent; width: 100%;
  border-bottom: 1px dashed transparent; padding: 0; min-width: 0;
}
/* Les actions de titre restent a droite et ne se laissent pas comprimer. */
.titre-actions { flex: none; display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
/* V6.2 — jeton d'une valeur selectionnee que l'editeur ne sait pas nommer
   (compte proprietaire, collection privee d'un collegue). Volontairement terne
   et en chiffres : il dit « il y a quelque chose ici que je ne peux pas
   afficher », pas « voici une valeur normale ». */
.type-pill.inconnu { background: var(--line-soft); color: var(--ink-3); font-family: var(--mono); font-size: 11px; }
.titre-actions .btn-mini { font-size: 12px; font-weight: 500; letter-spacing: 0; }
@media (max-width: 700px) { .btn-suivre-tete .btn-suivre-txt { display: none; } }
h1.titre-page input:hover { border-bottom-color: var(--line); }
h1.titre-page input:focus { border-bottom-color: var(--accent); outline: none; }
.type-pill {
  display: inline-block; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-fonce);
  background: var(--accent-pale); padding: 2px 8px; border-radius: 9px; vertical-align: middle;
}

.carte {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 14px 16px; margin-bottom: 16px;
}
.carte h3 { margin: 0 0 8px; font-size: 13px; }
.carte h3 .eyebrow { display: block; }

/* V8.15.1 — TROIS COLONNES EN DUR, POUR TROIS CARTES QUI N'EXISTENT PLUS.
   Contexte, Vocabulaire et Ontologie se partageaient cette grille. Depuis que
   les deux dernières sont devenues une vue et une couche du graphe, il ne reste
   qu'une carte — qui continuait d'occuper un tiers de la largeur, avec deux
   colonnes vides à côté. `auto-fit` règle le cas sans rien décider d'avance :
   une carte prend toute la largeur, deux se partagent, trois se rangent en
   trois — et le jour où l'on en rajoute une, personne n'aura à y penser. */
.grille-contexte { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 12px; }
.zone-editable textarea {
  width: 100%; min-height: 84px; resize: vertical; border: 1px solid var(--line-soft);
  border-radius: var(--r); padding: 8px; font-size: 13px; background: var(--input-bg);
}
.zone-editable textarea:focus { border-color: var(--accent); outline: none; background: var(--input-bg); }

/* ---------- Onglets ---------- */
.onglets { display: flex; gap: 2px; border-bottom: 2px solid var(--line); margin: 18px 0 14px; }
.onglet {
  border: none; background: none; padding: 7px 14px; font-size: 13.5px;
  color: var(--ink-2); border-bottom: 2px solid transparent; margin-bottom: -2px;
}
.onglet:hover { color: var(--ink); }
.onglet.actif { color: var(--accent-fonce); font-weight: 600; border-bottom-color: var(--accent); }

/* ---------- Boutons ---------- */
.btn {
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: var(--r); padding: 6px 12px; font-size: 13px;
}
.btn:hover { border-color: var(--ink-3); }
.btn-primaire { background: var(--accent-plein); border-color: var(--accent-plein); color: var(--sur-accent); }
.btn-primaire:hover { background: var(--accent-fonce); border-color: var(--accent-fonce); }
.btn-danger { color: var(--danger); border-color: var(--danger-pale); }
.btn-danger:hover { background: var(--danger-pale); }
.btn-mini { padding: 2px 8px; font-size: 12px; border-radius: 4px; }
.btn-lien { border: none; background: none; color: var(--accent-fonce); padding: 0; font-size: 12.5px; }
.btn-lien:hover { text-decoration: underline; }
/* V4.7 — boutons d'action icône : zone de clic confortable + retour au survol
   (les icônes seules restent, mais on ne « chasse » plus un glyphe de 12 px) */
.btn-lien.btn-mini { font-size: 14px; padding: 3px 6px; border-radius: 5px; line-height: 1.2; }
.btn-lien.btn-mini:hover { background: var(--accent-pale); text-decoration: none; }
/* V4.7 — icônes SVG (Lucide) : alignées sur le texte, couleur héritée */
.cc-icone { vertical-align: -2px; }
button .cc-icone, a .cc-icone { pointer-events: none; }

/* V4.9 — type checklist : jauge X/Y (orange < 50 %, jaune 50-99 %, vert 100 %) */
.jauge-checklist {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap;
}
.jauge-checklist .barre {
  width: 46px; height: 6px; border-radius: 3px; background: var(--line-soft, rgba(0,0,0,.12)); overflow: hidden;
}
.jauge-checklist .barre i { display: block; height: 100%; border-radius: 3px; }
.jauge-checklist .mention-attente { font-size: 13px; cursor: help; }

/* V4.12 — tableur : sélection de plage + couleurs de cellules */
.bloc-tableur td.sel { outline: 2px solid var(--accent); outline-offset: -2px; background: var(--accent-pale); }
.bloc-tableur td input { background: transparent; font-weight: inherit; }
.bloc-tableur th { cursor: pointer; user-select: none; position: relative; }
/* V4.12b — glisser-sélectionner, redimensionner les colonnes */
.bloc-tableur { table-layout: fixed; }
.bloc-tableur td { overflow: hidden; }
.bloc-tableur.drag-sel, .bloc-tableur.drag-sel input { user-select: none; cursor: cell; }
.bloc-tableur th .redim {
  position: absolute; top: 0; right: -3px; width: 7px; height: 100%;
  cursor: col-resize; z-index: 2;
}
.bloc-tableur th .redim:hover { background: var(--accent); opacity: .5; }
/* V4.13 — présence : pastilles flottantes + bloc/cellule occupés */
#cc-presence { position: fixed; top: 62px; right: 14px; z-index: 850; display: flex; flex-direction: column; gap: 5px; align-items: flex-end; pointer-events: none; }
.presence-pill {
  display: inline-flex; align-items: center; gap: 6px; pointer-events: auto;
  background: var(--card, #fff); border: 1px solid var(--line); border-radius: 14px;
  padding: 3px 10px; font-size: 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
}
.presence-point { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.presence-detail { color: var(--ink-3); font-size: 11px; }
.bloc-ligne.bloc-occupe { position: relative; outline: 2px dashed rgba(245, 158, 11, .55); outline-offset: 2px; border-radius: 4px; }
.bloc-ligne.bloc-occupe::after {
  content: '✏ ' attr(data-occupant); position: absolute; top: -9px; right: 4px;
  font-size: 10px; line-height: 1.5; background: #f59e0b; color: #fff;
  border-radius: 8px; padding: 0 6px; pointer-events: none; z-index: 5;
}
td.cellule-occupee { position: relative; outline: 2px dashed #f59e0b; outline-offset: -2px; }
td.cellule-occupee::after {
  content: '✏ ' attr(data-occupant); position: absolute; top: -9px; right: 2px;
  font-size: 10px; line-height: 1.5; background: #f59e0b; color: #fff;
  border-radius: 8px; padding: 0 6px; pointer-events: none; z-index: 5;
}

/* V4.12h — cellules référencées par la formule en cours d'édition */
/* ⚠ CES CINQ COULEURS SONT UNE DONNÉE, PAS UN THÈME. Elles numérotent les
   références d'une formule et doivent rester cinq teintes distinctes et
   reconnaissables dans les deux thèmes — les passer aux jetons les ramènerait
   à trois nuances de la même sarcelle. Idem l'orange de « cellule occupée »
   juste au-dessus. On n'y touche pas. */
.bloc-tableur td.ref-0 { box-shadow: inset 0 0 0 2px #3b82f6; }
.bloc-tableur td.ref-1 { box-shadow: inset 0 0 0 2px #ef4444; }
.bloc-tableur td.ref-2 { box-shadow: inset 0 0 0 2px #22c55e; }
.bloc-tableur td.ref-3 { box-shadow: inset 0 0 0 2px #a855f7; }
.bloc-tableur td.ref-4 { box-shadow: inset 0 0 0 2px #f59e0b; }

/* V4.10 — bloc « cases à cocher » */
.bloc-cases-ligne { display: flex; align-items: center; gap: 8px; padding: 1px 0; }
.bloc-cases-ligne input[type="checkbox"] { flex: none; }
.bloc-cases-texte { flex: 1; border: none; background: none; font: inherit; padding: 2px 0; outline: none; }
.bloc-cases-ligne.fait .bloc-cases-texte { text-decoration: line-through; color: var(--ink-3); }

/* V4.10 — planning « semaine type » (champ horaires) */
.semaine-type { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-top: 10px; }
.semaine-entete { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); padding: 4px 2px; text-align: center; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.semaine-col { min-height: 60px; }
.semaine-chip {
  display: block; width: 100%; text-align: left; margin: 3px 0; padding: 4px 6px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--card);
  font-size: 11.5px; cursor: pointer; line-height: 1.35;
}
.semaine-chip:hover { border-color: var(--accent); background: var(--accent-pale); }
.semaine-chip strong { color: var(--accent-fonce); }

/* V4.9 — type horaires : chips de jours dans l'éditeur */
.jour-chip {
  border: 1px solid var(--line); background: var(--card); border-radius: 10px;
  padding: 2px 7px; font-size: 11px; cursor: pointer; text-transform: capitalize;
}
.jour-chip.actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent-fonce); font-weight: 600; }

/* ---------- Tableau (vue base) ---------- */
.barre-outils { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.chip-filtre {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-pale); color: var(--accent-fonce);
  border: 1px solid var(--line); border-radius: 12px; padding: 2px 8px; font-size: 12px;
}
.chip-filtre button { border: none; background: none; color: inherit; padding: 0; font-size: 13px; line-height: 1; }

.enveloppe-tableau { overflow-x: auto; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); }
table.base { border-collapse: collapse; width: 100%; min-width: 640px; }
table.base th, table.base td {
  border-bottom: 1px solid var(--line-soft); border-right: 1px solid var(--line-soft);
  padding: 6px 10px; text-align: left; font-size: 13px; vertical-align: top;
}
table.base th {
  background: var(--sunk); font-family: var(--mono); font-size: 11px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2);
  cursor: pointer; user-select: none; white-space: nowrap; position: sticky; top: 0;
}

/* ============================================================
   V8.30 — EN-TÊTE DE TABLEAU FIGÉ AU DÉFILEMENT
   ------------------------------------------------------------
   ⚠ LE `position: sticky` CI-DESSUS EXISTE DEPUIS LONGTEMPS ET NE SERVAIT À
   RIEN. Il faut comprendre pourquoi avant de lire le correctif, sinon celui-ci
   a l'air arbitraire.

   `position: sticky` se cale sur le PLUS PROCHE ANCÊTRE QUI DÉFILE. Ici, cet
   ancêtre n'est pas `.contenu` (le vrai port de défilement de la page) mais
   `.enveloppe-tableau` : elle porte `overflow-x: auto`, et la spécification
   CSS dit qu'un `overflow` non-`visible` sur UN axe force l'autre à `auto`.
   L'enveloppe est donc, techniquement, une boîte qui défile — sauf qu'elle
   n'a aucune hauteur maximale, donc elle grandit avec le tableau et ne défile
   jamais verticalement. L'en-tête restait « collé » en haut d'une boîte qui ne
   bougeait pas : parfaitement immobile, et parfaitement inutile.

   Le correctif ne touche donc pas au `th` : il donne à l'enveloppe la hauteur
   qui lui manquait, ce qui en fait le port de défilement qu'elle prétendait
   déjà être.
   ============================================================ */
.enveloppe-tableau.entete-fige {
  /* La hauteur disponible sous la barre du haut (52 px), le fil d'Ariane et
     la barre d'outils de la vue, moins la marge basse de `.contenu`. Le
     `min-height` protège les petits écrans : mieux vaut déborder un peu que
     réduire le tableau à deux lignes et demie. */
  max-height: calc(100vh - var(--entete-fige-marge, 210px));
  overflow: auto;
}
/* Le plancher ne vaut que sur un écran assez haut pour se le permettre : posé
   sans condition, il réservait 240 px de vide sous une collection de deux
   fiches, cadre et bordure compris. */
@media (min-height: 700px) {
  .enveloppe-tableau.entete-fige { min-height: 240px; }
}
.enveloppe-tableau.entete-fige table.base th {
  /* ⚠ `border-collapse: collapse` (déclaré sur table.base) FAIT DÉFILER LES
     BORDURES AVEC LE CORPS : elles appartiennent alors à la table, pas aux
     cellules, et l'en-tête figé se retrouve sans trait sous lui dès la
     première ligne dépassée. On les redessine en ombre interne, qui, elle,
     est peinte avec la cellule. */
  /* V8.57 — les deux replis divergeaient du `:root` (#dbe4e6 / #e8eeef pour
     #d4dcd9 / #e4e9e7) : on les remet d'aplomb, un repli faux ne se voit que
     le jour où il sert. */
  box-shadow: inset 0 -1px 0 var(--line, #d4dcd9), inset -1px 0 0 var(--line-soft, #e4e9e7);
  /* Au-dessus des cellules qui passent dessous — et des contrôles qu'elles
     contiennent (interrupteurs, champs de saisie en cours d'édition). */
  z-index: 3;
}
.enveloppe-tableau.entete-fige table.base th.th-poignee,
.enveloppe-tableau.entete-fige table.base th:first-child { z-index: 4; }

/* ⚠ PAS D'EN-TÊTE FIGÉ SOUS 800 px, QUEL QUE SOIT LE RÉGLAGE. Sur un
   téléphone, la hauteur d'écran est la ressource rare : figer une bande de
   30 px en haut d'une zone qui en fait 400 coûte proportionnellement bien
   plus cher que sur un écran de bureau, et la double barre de défilement
   (page + tableau) y devient franchement pénible au doigt. Le réglage reste
   coché dans les préférences — il reprend effet dès qu'on élargit la fenêtre. */
@media (max-width: 800px) {
  .enveloppe-tableau.entete-fige { max-height: none; min-height: 0; overflow-x: auto; overflow-y: visible; }
  .enveloppe-tableau.entete-fige table.base th { box-shadow: none; z-index: auto; }
}

/* ⚠ ET SURTOUT : PAS D'EN-TÊTE FIGÉ À L'IMPRESSION. C'est la régression que la
   relecture adverse a attrapée, et elle était silencieuse. Le réglage étant
   ACTIF PAR DÉFAUT, la boîte gardait à l'impression son `max-height` et son
   `overflow: auto` — or aucun navigateur n'imprime ce qui dépasse d'un
   conteneur à défilement. Une collection de 300 fiches sortait donc sur UNE
   page au lieu de dix, sans le moindre avertissement, là où la V8.29 imprimait
   tout. On rend donc la boîte à sa hauteur naturelle, et l'en-tête à sa
   position statique — un en-tête « collé en haut de l'écran » n'ayant de toute
   façon aucun sens sur du papier. */
@media print {
  .enveloppe-tableau.entete-fige {
    max-height: none !important; min-height: 0 !important; overflow: visible !important;
  }
  .enveloppe-tableau.entete-fige table.base th {
    position: static !important; box-shadow: none !important; z-index: auto !important;
  }
}
table.base th .fleche-tri { color: var(--accent-fonce); }
table.base th.th-plus { cursor: default; width: 40px; text-align: center; }
table.base td.cellule-editable { cursor: text; }
/* V7.0 (RELI-390) — « des fois je vois mal la souris, surtout sur le tableau ».
   Le seul retour visuel sous le curseur était CE survol de cellule — un
   #f4f9f9 sur fond blanc, quasi indiscernable — et rien au niveau de la
   ligne : perdre le curseur des yeux, c'était le perdre tout court. Deux
   renforts : la LIGNE survolée se teinte (on retrouve la souris d'un coup
   d'œil, même entre deux cellules), et la CELLULE éditable passe à l'accent
   pâle, franchement visible. Les fonds spéciaux (ligne-nouvelle, formules)
   sont recouverts PENDANT le survol seulement : c'est le but — dire où l'on
   est — et tout revient en repartant. */
table.base tbody tr:hover td { background: var(--sunk); }
table.base td.cellule-editable:hover,
table.base tbody tr:hover td.cellule-editable:hover { background: var(--accent-pale); }
table.base td input, table.base td select {
  width: 100%; border: 1px solid var(--accent); border-radius: 3px; padding: 2px 5px; font-size: 13px; background: var(--input-bg);
}
table.base td .valeur-multi { display: inline-block; background: var(--line-soft); border-radius: 8px; padding: 0 7px; margin: 0 3px 2px 0; font-size: 12px; }
table.base td .booleen { font-family: var(--mono); }
td.cellule-titre a { font-weight: 600; }
tr.ligne-nouvelle td { background: var(--sunk); }
tr.ligne-nouvelle input { border: 1px solid var(--line); }
tr.ligne-nouvelle input:focus { border-color: var(--accent); }
.desc-courte-cellule { color: var(--ink-2); }

/* popover ajout colonne / multiselect */
.popover {
  position: fixed; z-index: 90; background: var(--card); border: 1px solid var(--line); /* V3.1 : au-dessus des modales (palette couleurs dans « Gérer les options ») */
  border-radius: var(--r); box-shadow: var(--ombre-flot); padding: 12px; min-width: 230px;
  max-height: calc(100vh - 24px); overflow-y: auto; /* V3.2 : jamais coupé — défilement interne en dernier recours */
  /* V8.40 — PLAFOND DE LARGEUR, ET C'EST UN CORRECTIF, PAS UN RAFFINEMENT.
     Un popover est en position fixe SANS `width` : sa largeur est celle de son
     contenu. Il y avait donc un `max-height` pour la hauteur et RIEN pour la
     largeur — asymétrie qui n'avait pas de raison d'être. Un contenu qui porte
     un paragraphe d'aide un peu long l'étirait jusqu'au bord de l'écran :
     mesuré à 1430 px sur un écran de 1440, et 1910 px sur un écran de 1920,
     pour le réglage d'une colonne « nombre ». La plupart des popovers posaient
     un `min-width` de 220 à 340 px et ne s'en approchaient jamais — d'où un
     défaut resté invisible des années, jusqu'à ce qu'on ouvre le même écran
     cinq fois de suite avec cinq contenus différents.
     520 px laisse toute leur place aux plus larges (le sélecteur de type,
     l'éditeur de formules) sans qu'aucun puisse prendre l'écran. Le
     `calc(100vw - 24px)` couvre le téléphone, où 520 px déborderait. */
  max-width: min(520px, calc(100vw - 24px));
}
/* V8.23 — un popover ouvert DEPUIS un autre passe au-dessus de lui, et le dit
   d'un liseré : sans repère visuel, deux panneaux superposés se lisent comme
   un seul panneau devenu incohérent. */
.popover-enfant { z-index: 95; border-color: var(--accent); box-shadow: 0 10px 30px rgba(24, 43, 58, 0.24); }
.popover label { display: block; font-size: 12px; color: var(--ink-2); margin: 8px 0 3px; }
.popover input[type="text"], .popover select, .popover textarea {
  width: 100%; border: 1px solid var(--line); border-radius: 4px; padding: 5px 7px; font-size: 13px;
}
.popover .actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
.popover .case { display: flex; align-items: center; gap: 6px; font-size: 13px; margin: 3px 0; }

/* V8.48 — le choix de portée de « Lier les fiches… ». Encadré, parce que ce
   n'est pas un réglage de plus dans une pile de réglages : c'est la question
   « sur quoi ça va porter ? », et elle doit se lire avant le type de lien.
   ⚠ `.popover label { display:block }` ci-dessus s'applique aussi aux deux
     lignes de choix : sans le `display:flex` ici, le bouton radio se mettrait
     au-dessus de son libellé. */
.popover .cc-portee-lien {
  border: 1px solid var(--line); border-radius: 6px;
  padding: 2px 9px 8px; margin: 8px 0 2px; background: var(--paper);
}
.popover .cc-portee-lien > label:first-child { margin-top: 6px; font-weight: 600; color: var(--ink); }
.popover label.cc-portee-choix {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--ink); margin: 4px 0 0; cursor: pointer;
}
.popover label.cc-portee-choix input[type="radio"] { width: auto; flex: none; margin: 0; }
.popover label.cc-portee-choix em { font-style: normal; color: var(--ink-3); font-size: 11.5px; }

/* ---------- Kanban ---------- */
.kanban { display: flex; gap: 12px; overflow-x: auto; align-items: flex-start; padding-bottom: 10px; }
.kanban-col {
  min-width: 230px; width: 230px; background: var(--sunk); border: 1px solid var(--line);
  border-radius: var(--r); padding: 8px; flex: none;
}
.kanban-col.drop-into { border-color: var(--accent); background: var(--accent-pale); }
.kanban-col h4 {
  margin: 0 0 8px; font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-2); display: flex; justify-content: space-between;
}
.kanban-carte {
  background: var(--card); border: 1px solid var(--line); border-radius: 5px;
  padding: 8px 10px; margin-bottom: 8px; cursor: grab;
}
.kanban-carte:active { cursor: grabbing; }
.kanban-carte .t { font-weight: 600; font-size: 13px; }
.kanban-carte .d { color: var(--ink-2); font-size: 12px; margin-top: 2px; }
.kanban-carte.en-deplacement { opacity: 0.4; }

/* ---------- Notes ---------- */
.note-item {
  display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line-soft);
  align-items: baseline;
}
.note-item:last-child { border-bottom: none; }
.badge-type {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 1px 7px; border-radius: 8px; flex: none;
}
.badge-type.decision { background: var(--accent-pale); color: var(--st-actif); }
.badge-type.question { background: var(--warn-pale); color: var(--st-ouvert); }
.badge-type.assumption { background: var(--prive-pale); color: var(--prive); }
.badge-type.todo { background: var(--ok-pale); color: var(--st-resolu); }
.badge-statut { font-family: var(--mono); font-size: 10.5px; flex: none; }
.badge-statut::before { content: "● "; font-size: 8px; vertical-align: 1px; }
.badge-statut.ouvert { color: var(--st-ouvert); }
.badge-statut.actif { color: var(--st-actif); }
.badge-statut.resolu { color: var(--st-resolu); }
.badge-statut.abandonne { color: var(--st-abandonne); }
.badge-statut.remplace { color: var(--st-remplace); }
.note-contenu { flex: 1; }
.note-contenu .remplacement { color: var(--ink-2); font-size: 12px; margin-top: 2px; }
.note-contenu .origine { font-size: 11.5px; color: var(--ink-3); font-family: var(--mono); }
.note-actions { display: flex; gap: 6px; flex: none; }
.note-actions select { font-size: 11.5px; border: 1px solid var(--line); border-radius: 4px; padding: 1px 3px; }
.note-date { font-family: var(--mono); font-size: 11px; color: var(--ink-3); flex: none; }

.form-note { display: flex; gap: 8px; margin-top: 10px; }
.form-note select { border: 1px solid var(--line); border-radius: var(--r); padding: 5px; font-size: 13px; }
.form-note input { flex: 1; border: 1px solid var(--line); border-radius: var(--r); padding: 5px 9px; font-size: 13px; }

/* V7.2 (RELI-440) — carte Notes : onglets par type, recherche, réponse,
   et les notes multi-lignes (ADR) qui se lisent en lignes. */
.notes-outils { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 10px 0; }
.notes-onglets { display: flex; flex-wrap: wrap; gap: 4px; }
.note-onglet {
  border: 1px solid var(--line); background: var(--card); border-radius: 12px;
  padding: 2px 10px; font-size: 12px; color: var(--ink-2); cursor: pointer;
}
.note-onglet:hover { border-color: var(--accent); }
.note-onglet.actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent-fonce); font-weight: 600; }
.note-onglet-nb { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); }
.note-onglet.actif .note-onglet-nb { color: var(--accent-fonce); }
.note-recherche { flex: 1; min-width: 160px; border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px; font-size: 13px; }
.note-item .cc-texte-lecture { white-space: pre-line; }
.note-reponse { font-size: 13px; color: var(--st-resolu); margin-top: 2px; white-space: pre-line; }

/* ---------- Fiche détail ---------- */
.fiche-grille { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 18px; align-items: start; }
@media (max-width: 1050px) { .fiche-grille { grid-template-columns: 1fr; } }
.detail-long textarea { min-height: 220px; font-size: 13.5px; line-height: 1.55; }
.rattachement-bloc { border: 1px solid var(--line-soft); border-radius: var(--r); padding: 10px 12px; margin-bottom: 10px; }
.rattachement-bloc .chemin { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.champ-ligne { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
.champ-ligne label { width: 110px; flex: none; font-size: 12.5px; color: var(--ink-2); }
.champ-ligne input, .champ-ligne select {
  flex: 1; border: 1px solid var(--line); border-radius: 4px; padding: 4px 7px; font-size: 13px; min-width: 0;
}
.lien-item { display: flex; gap: 8px; padding: 5px 0; font-size: 13px; align-items: baseline; }
.lien-item .rel { font-family: var(--mono); font-size: 11.5px; color: var(--accent-fonce); background: var(--accent-pale); border-radius: 8px; padding: 1px 7px; flex: none; }
.fichier-item { display: flex; gap: 8px; align-items: baseline; padding: 4px 0; font-size: 13px; }
.fichier-item .taille { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

/* ---------- Export : le manifeste ---------- */
.export-grille { display: grid; grid-template-columns: 330px minmax(0, 1fr); gap: 18px; align-items: start; }
@media (max-width: 1000px) { .export-grille { grid-template-columns: 1fr; } }
.export-form label.bloc { display: block; font-size: 12.5px; color: var(--ink-2); margin: 12px 0 4px; }
.export-form .cases { display: flex; flex-direction: column; gap: 4px; }
.export-form .case { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.export-form select, .export-form input[type="text"], .export-form input[type="number"] {
  width: 100%; border: 1px solid var(--line); border-radius: 4px; padding: 5px 8px; font-size: 13px;
}
.filtre-ligne { display: flex; gap: 6px; margin-bottom: 6px; }
.filtre-ligne select, .filtre-ligne input { flex: 1; min-width: 0; }

.manifeste {
  background: #10222f; color: #d7e4e6; border-radius: var(--r);
  border-left: 4px solid var(--accent);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.6;
  padding: 0; overflow: hidden;
}
.manifeste-tete {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 8px 14px; background: #0b1922; border-bottom: 1px solid #24404d;
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: #7fa6ad;
}
.manifeste-tete .stats span { margin-left: 12px; color: #a9c6ca; }
.manifeste pre {
  margin: 0; padding: 14px 16px; overflow: auto; max-height: 62vh;
  white-space: pre-wrap; word-break: break-word;
}
.manifeste .vide { padding: 30px; text-align: center; color: #6d8a91; }

/* ---------- Recherche ---------- */
.resultat-groupe h3 { font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); margin: 18px 0 6px; }
.resultat-item { padding: 7px 0; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; }
.resultat-item .extrait { color: var(--ink-2); font-size: 12.5px; }

/* ---------- Connexion ---------- */
.page-connexion {
  /* #app est en display:flex — sans flex:1 la page se réduit à la largeur
     de la boîte et laisse le fond blanc à droite. */
  flex: 1 1 100%; width: 100%;
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  /* V8.57 — MÊME INVERSION QUE LE BANDEAU. Cet écran est sombre par CHOIX,
     dans les deux thèmes : son fond demandait « du foncé », pas « l'encre ».
     `var(--ink)` devenant clair en sombre, la page virait au blanc sous une
     tache marine (le dégradé, lui, resté en dur). `--topbar` dit le rôle. */
  background: var(--topbar);
  background-image: radial-gradient(circle at 20% 20%, #22394a 0, transparent 45%),
                    linear-gradient(transparent 31px, rgba(255,255,255,0.03) 32px);
  background-size: auto, 100% 32px;
}
.boite-connexion {
  background: var(--card); border-radius: 8px; padding: 30px 32px; width: 360px;
  border-top: 4px solid var(--accent);
}
.boite-connexion .marque { color: var(--ink); font-size: 21px; letter-spacing: -0.01em; }
.boite-connexion .marque .cap { color: var(--accent-fonce); }
.boite-connexion .sous-titre { color: var(--ink-2); font-size: 12.5px; margin: 4px 0 20px; }
.boite-connexion label { display: block; font-size: 12.5px; color: var(--ink-2); margin: 12px 0 4px; }
.boite-connexion input {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r); padding: 8px 10px; font-size: 14px;
}
.boite-connexion .btn-primaire { width: 100%; margin-top: 18px; padding: 9px; }
.erreur-connexion { color: var(--danger); font-size: 13px; margin-top: 10px; min-height: 18px; }

/* ---------- V8.18 : connexion externe (Google / Microsoft) ----------
   Volontairement SOBRES et identiques entre eux : ni bleu Google ni bleu
   Microsoft. Reproduire les boutons officiels imposerait leurs polices, leurs
   logos et leurs règles de marque — et ferait de l'écran d'entrée un patchwork
   qui change d'allure selon le fournisseur configuré. Ici, la marque du
   fournisseur est dans le TEXTE ; le bouton, lui, appartient à Relieo. */
.boite-connexion .btn-sso {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; box-sizing: border-box; margin-top: 10px; padding: 9px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--card); color: var(--ink); font-size: 14px; cursor: pointer;
}
/* V8.57 — `--fond-2` N'EXISTE NULLE PART : ce n'était pas un jeton avec un
   repli, c'était un blanc cassé écrit en dur derrière un nom de jeton. Le rôle
   est celui de `--sunk` (surface enfoncée, survol). */
.boite-connexion .btn-sso:hover { border-color: var(--accent); background: var(--sunk); }
.boite-connexion .sso-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 3px;
  background: var(--sunk); color: var(--ink-2);
  font-weight: 700; font-size: 12px; line-height: 1;
}
/* Le « ou » : un trait coupé par un mot, plutôt qu'un mot posé dans le vide. */
.boite-connexion .sso-ou {
  display: flex; align-items: center; gap: 10px;
  margin: 18px 0 2px; color: var(--ink-3); font-size: 12px;
}
.boite-connexion .sso-ou::before,
.boite-connexion .sso-ou::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* ---------- Toast ---------- */
#toasts { position: fixed; bottom: 18px; right: 18px; z-index: 100; display: flex; flex-direction: column; gap: 8px; }
.toast {
  /* V8.57 — même inversion : un toast est une surface sombre à texte clair.
     En sombre, `var(--ink)` clair + texte clair donnait un toast illisible. */
  background: var(--topbar); color: var(--topbar-txt); border-left: 3px solid var(--accent);
  border-radius: 5px; padding: 9px 14px; font-size: 13px; max-width: 340px;
  box-shadow: 0 6px 18px rgba(24,43,58,0.3);
}
.toast.erreur { border-left-color: var(--danger); }

/* ---------- Divers ---------- */
.vide-etat { color: var(--ink-3); font-size: 13px; padding: 14px 0; }
.ligne-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.mt { margin-top: 14px; }
.confirm-suppr { color: var(--danger); font-size: 12.5px; }

@media (max-width: 800px) {
  .sidebar { position: fixed; left: 0; z-index: 30; transform: translateX(-100%); transition: transform 0.18s; }
  .sidebar.ouverte { transform: none; box-shadow: 4px 0 20px rgba(0,0,0,0.15); }
  .btn-burger { display: inline-block !important; }
  .contenu { padding: 16px 14px 80px; }
}
.btn-burger { display: none; background: none; border: none; color: var(--topbar-txt); font-size: 18px; padding: 4px; }


/* ---------- V2 : Vue Graphe ---------- */
.graphe-outils { align-items: center; gap: 10px; flex-wrap: wrap; }
.graphe-outils .case { gap: 5px; font-size: 12.5px; }
.graphe-conteneur {
  height: 64vh; min-height: 380px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.graphe-legende { font-size: 12px; color: var(--ink-3); margin-top: 6px; }

/* ---------- V2.6 : Vue Carte (Leaflet + OpenStreetMap) ---------- */
.carte-outils { align-items: center; gap: 10px; flex-wrap: wrap; }
.carte-statut { font-size: 12.5px; color: var(--ink-2); }
.carte-conteneur {
  height: 64vh; min-height: 380px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  z-index: 0; /* garde la carte sous les popovers / la barre latérale de l'app */
}
.carte-echecs { margin-top: 8px; }

/* Épingle personnalisée (divIcon) — pas d'image marqueur à charger */
.cc-pin-wrap { background: none; border: none; }
.cc-pin {
  display: block; position: relative; width: 22px; height: 22px;
  margin: 0 auto;
  background: var(--accent);
  border: 2px solid #fff;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.cc-pin::after {
  content: ''; position: absolute;
  top: 7px; left: 7px; width: 8px; height: 8px;
  background: #fff; border-radius: 50%;
}
.cc-pin-multi { background: var(--accent-fonce); }
.cc-pin-multi::after {
  content: attr(data-n);
  top: 0; left: 0; width: 22px; height: 22px;
  background: none; color: #fff;
  transform: rotate(45deg);
  display: flex; align-items: center; justify-content: center;
  font: 700 11px/1 var(--sans);
}

/* Popup au thème « carte marine » */
.cc-popup { font-family: var(--sans); }
.cc-popup-tete { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); margin-bottom: 6px; }
.cc-popup-item + .cc-popup-item { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.cc-popup-titre { font-weight: 700; color: var(--ink); font-size: 14px; }
.cc-popup-lieu { font-size: 12.5px; color: var(--ink-2); margin: 3px 0; }
.cc-popup-col { color: var(--ink-3); }
.cc-popup-desc { font-size: 12px; color: var(--ink-2); margin: 3px 0 6px; }
.cc-popup-lien { display: inline-block; margin-top: 4px; }
.leaflet-popup-content { margin: 12px 14px; }
.leaflet-popup-content-wrapper { border-radius: var(--r); }

/* ---------- V2.6 : Vue Calendrier ---------- */
.cal-outils { align-items: center; gap: 8px; flex-wrap: wrap; }
.cal-titre { font-weight: 600; color: var(--ink); margin-left: 8px; font-size: 14px; }
.cal-bascule { display: inline-flex; gap: 4px; }
.cal-bascule .btn.actif { background: var(--accent-plein); color: var(--sur-accent); border-color: var(--accent-plein); }
.cal-champ-lbl { font-size: 12.5px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; }
.cal-champ { border: 1px solid var(--line); border-radius: 4px; padding: 2px 6px; font-size: 12.5px; }
.cal-grille { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.cal-entete { background: var(--accent-pale); color: var(--ink-2); font-size: 11.5px; font-weight: 600;
  text-align: center; padding: 5px 2px; text-transform: uppercase; letter-spacing: .03em; }
.cal-cell { background: var(--card); min-height: 94px; padding: 4px; display: flex; flex-direction: column; gap: 3px; }
.cal-cell-sem { min-height: 320px; }
.cal-hors { background: var(--sunk); }
.cal-hors .cal-num { color: var(--ink-3); }
.cal-auj { box-shadow: inset 0 0 0 2px var(--accent); }
.cal-num { font-size: 12px; color: var(--ink-2); font-weight: 600; }
.cal-entete-sem { background: none; text-align: left; padding: 2px 0 4px; }
.cal-cell-evts { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.cal-evt { display: block; background: var(--accent-plein); color: var(--sur-accent); font-size: 11.5px; border-radius: 4px;
  padding: 1px 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none; }
.cal-evt:hover { background: var(--accent-fonce); }
.cal-plus { font-size: 11px; color: var(--ink-3); padding-left: 4px; }

/* ---------- V2.6 : Vue Planning / Gantt ---------- */
.plan-outils { align-items: center; gap: 10px; flex-wrap: wrap; }
.plan-champ-lbl { font-size: 12.5px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; }
.plan-champ-lbl select { border: 1px solid var(--line); border-radius: 4px; padding: 2px 6px; font-size: 12.5px; }
.plan-periode { border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px; font-size: 12px; }
.plan-conteneur { --plan-label: 190px; border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; background: var(--card); }
.plan-entete { display: flex; align-items: stretch; border-bottom: 1px solid var(--line); background: var(--accent-pale); }
.plan-label { width: var(--plan-label); flex: 0 0 var(--plan-label); box-sizing: border-box;
  padding: 6px 10px; font-size: 12.5px; color: var(--ink); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid var(--line); }
a.plan-label:hover { color: var(--accent); }
.plan-label-tete { font-weight: 600; color: var(--ink-2); }
.plan-axe { position: relative; flex: 1; height: 26px; }
.plan-tick-lbl { position: absolute; top: 5px; transform: translateX(-50%); font-size: 10.5px; color: var(--ink-2); white-space: nowrap; }
.plan-corps { position: relative; }
.plan-grille { position: absolute; top: 0; bottom: 0; left: var(--plan-label); right: 0; pointer-events: none; }
.plan-grille-l { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line-soft); }
.plan-row { display: flex; align-items: center; min-height: 30px; border-bottom: 1px solid var(--line-soft); }
.plan-row:last-child { border-bottom: none; }
.plan-track { position: relative; flex: 1; height: 30px; }
.plan-bar { position: absolute; top: 5px; height: 20px; min-width: 8px; background: var(--accent);
  border-radius: 4px; display: flex; align-items: center; text-decoration: none; box-shadow: var(--ombre); }
.plan-bar:hover { background: var(--accent-fonce); }
.plan-bar-txt { color: #fff; font-size: 11px; padding: 0 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- V2.8 : autocomplétion des formules ---------- */
.formule-ac {
  position: absolute; z-index: 3000; max-height: 240px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .14); font-size: 12.5px; min-width: 220px;
}
.formule-ac-item { display: flex; align-items: baseline; gap: 7px; padding: 4px 9px; cursor: pointer; }
.formule-ac-item.actif, .formule-ac-item:hover { background: var(--accent-pale); }
.formule-ac-nom { font-family: var(--mono); font-weight: 600; color: var(--accent-fonce); white-space: nowrap; }
.formule-ac-sig { color: var(--ink-3); font-family: var(--mono); font-size: 11px; white-space: nowrap; }
.formule-ac-aide { color: var(--ink-2); font-size: 11px; margin-left: auto; text-align: right; padding-left: 10px; }

/* ---------- V2 : Équipe ---------- */
.btn-lien-topbar {
  /* V6.2 (RELI-322) — `background: none` MANQUAIT, et c'etait tres visible.
     Equipe et Admin sont des <a> (transparents par defaut) ; la brique
     Messages est le seul <button> a porter cette classe, et un <button> garde
     le `buttonface` gris clair du navigateur. Resultat : un pave gris avec du
     texte #c4d0d7 dans une topbar bleu nuit — la brique avait l'air desactivee.
     Toutes les autres classes de bouton du fichier posent ce reset
     (.btn-quitter, .btn-burger, .btn-compte, .btn-lien) ; celle-ci l'a rate. */
  background: none; -webkit-appearance: none; appearance: none;
  color: var(--topbar-attenue); font-size: 12.5px; margin-right: 12px;
  border: 1px solid var(--topbar-ligne); border-radius: var(--r);
  /* Pas de `gap` : les libelles sont ecrits ' Equipe', ' Admin', ' Messages',
     espace compris — un gap s'y ajouterait au lieu de le remplacer. */
  padding: 3px 9px; display: inline-flex; align-items: center;
}
.btn-lien-topbar:hover { color: var(--topbar-txt); border-color: var(--topbar-vif); }
.equipe-table td { vertical-align: middle; }
.equipe-table select { max-width: 240px; }
.compte-inactif td { opacity: .5; }
.form-equipe {
  display: grid; grid-template-columns: 110px 1fr; gap: 8px 12px;
  align-items: center; max-width: 560px; margin-bottom: 10px;
}
.form-equipe label { font-size: 12.5px; color: var(--ink-2); }

/* ---------- V2 : lecture seule ---------- */
input:disabled, textarea:disabled, select:disabled {
  background: transparent; color: var(--ink); opacity: 1; cursor: default;
}
.titre-page input:disabled { border-color: transparent; }

/* ============================================================
   V2.1 — retours d'usage : enregistrement auto, colonnes
   redimensionnables/masquables, gestion des options, duplication
   ============================================================ */
/* -- Indicateur d'enregistrement (carteTexteAutosave) -- */
.carte h3 { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.entete-sauve { display: inline-flex; align-items: center; gap: 6px; font-weight: 400; text-transform: none; letter-spacing: normal; }
.statut-sauve {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.04em; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 4px;
}
.statut-sauve::before { content: "\25CF"; font-size: 8px; }
.statut-sauve.enregistre { color: var(--ok); }
.statut-sauve.enregistrement { color: var(--st-ouvert); }
.statut-sauve.non-enregistre { color: var(--danger); }
.bouton-disquette {
  border: 1px solid var(--line); background: var(--card); border-radius: 4px;
  font-size: 12px; line-height: 1; padding: 3px 6px; cursor: pointer;
}
.bouton-disquette:hover { border-color: var(--accent); background: var(--accent-pale); }

/* -- Colonnes redimensionnables + retour à la ligne / troncature -- */
table.base { table-layout: fixed; }
table.base th { overflow: hidden; padding-right: 14px; }
table.base th .poignee-resize {
  position: absolute; top: 0; right: 0; width: 8px; height: 100%; cursor: col-resize;
  user-select: none; touch-action: none;
}
table.base th .poignee-resize:hover, table.base th .poignee-resize:active { background: var(--accent); opacity: .35; }
table.base td.cellule-souple { white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
table.base td.cellule-tronque { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* V2.4 — boutons d'action du tableau espacés et grossis (anti-misclic) */
table.base td.cellule-actions { white-space: nowrap; text-align: center; }
table.base td.cellule-actions .btn-lien {
  font-size: 15px; padding: 4px 6px; margin: 0 1px; border-radius: 5px; color: var(--accent-fonce);
  vertical-align: middle;
}
table.base td.cellule-actions .btn-lien:hover { background: var(--accent-pale); text-decoration: none; }
table.base th.th-plus .btn { padding: 4px 10px; }

/* ---------- V2.4 : formules ---------- */
table.base td.cellule-formule {
  color: var(--accent-fonce); background: var(--sunk);
  font-variant-numeric: tabular-nums; cursor: default;
}
.formule-erreur { color: var(--danger); cursor: help; }
.valeur-formule { color: var(--accent-fonce); font-variant-numeric: tabular-nums; }

.formules-noeud { margin: 0 0 12px; }
.formules-entete { display: flex; align-items: center; gap: 10px; }
.formules-toggle { font-size: 13px; font-weight: 600; text-decoration: none; }
.formules-toggle:hover { text-decoration: none; opacity: .8; }
.formules-cartes { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.formule-carte {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 12px; min-width: 130px; max-width: 320px;
}
.formule-titre {
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-2); display: flex; align-items: center; gap: 6px;
}
.formule-carte .formule-editer { opacity: 0; transition: opacity .1s; }
.formule-carte:hover .formule-editer { opacity: 1; }
.formule-resultat {
  font-size: 19px; font-weight: 600; color: var(--accent-fonce);
  margin-top: 2px; font-variant-numeric: tabular-nums;
}
.formule-resultat .mini-graphe { font-weight: 400; }

/* ---------- V8.0 (RELI-451) : bandeau des scénarios ---------- */
/* Le bandeau se lit comme une SUITE du panneau ∑ : mêmes cartes, même en-tête,
   même repli. Ce sont deux moitiés d'une seule idée — les leviers et ce qu'ils
   font bouger — et un langage visuel distinct les aurait fait passer pour deux
   fonctionnalités sans rapport. D'où la réutilisation de .formules-entete et de
   .formule-titre plutôt qu'une famille de classes parallèle. */
.scenarios-noeud { margin: -4px 0 12px; }
.scenarios-cartes { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.scenario-carte {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 12px; min-width: 150px; max-width: 320px;
  display: flex; flex-direction: column; gap: 4px;
}
/* Une valeur surchargée localement DOIT se distinguer d'une valeur partagée :
   sans cela on croit avoir changé le tableau pour l'équipe — ou l'inverse, et
   c'est pire. Un liseré, comme .bandeau-partage, plutôt qu'une couleur de fond :
   la carte reste lisible et la différence se voit du coin de l'œil. */
.scenario-carte.surcharge { border-left: 3px solid var(--accent); background: var(--accent-pale); }
.scen-ctrl {
  width: 100%; font: inherit; font-variant-numeric: tabular-nums;
  padding: 3px 6px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--input-bg); color: var(--ink);
}
.scen-bornes { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.scen-orphelin {
  font-size: 10px; text-transform: none; letter-spacing: 0;
  color: var(--ink-3); border: 1px dashed var(--line); border-radius: var(--r);
  padding: 0 4px; font-weight: 400;
}
.scen-a-parametrer { font-size: 12px; color: var(--danger); font-style: italic; }
.scenario-carte .scen-partager { align-self: flex-start; }
.scenario-carte .formule-editer { opacity: 0; transition: opacity .1s; }
.scenario-carte:hover .formule-editer { opacity: 1; }
/* Sur une fiche, le scénario se LIT et ne se règle pas : la mention est
   volontairement discrète — elle explique un nombre, elle n'invite pas à agir. */
.scen-mention { font-size: 11px; color: var(--ink-3); margin-left: 6px; }
/* Éditeur : le libellé et son expression sur une ligne, l'expression prenant la
   place restante — c'est elle qu'on relit. */
.scen-options { margin-top: 6px; display: grid; gap: 4px; }
.scen-option-ligne { display: flex; align-items: center; gap: 4px; font-size: 12px; }
.scen-option-ligne input:last-of-type { flex: 1; min-width: 0; }

.mini-graphe { display: grid; gap: 3px; min-width: 190px; margin-top: 4px; }
.mini-graphe-ligne { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.mini-graphe-label {
  flex: none; width: 84px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--ink-2); text-transform: none; letter-spacing: 0;
}
.mini-graphe-barre-zone { flex: 1; background: var(--line-soft); border-radius: 3px; height: 10px; overflow: hidden; }
.mini-graphe-barre { display: block; height: 100%; background: var(--accent); border-radius: 3px; min-width: 2px; }
.mini-graphe-nb { flex: none; font-family: var(--mono); font-size: 11px; color: var(--ink-2); min-width: 22px; text-align: right; }

/* -- Titre : icône crayon au survol (découvrabilité de l'édition inline) -- */
.icone-edit { opacity: 0; color: var(--ink-3); font-size: 11px; transition: opacity .1s; }
td.cellule-titre:hover .icone-edit { opacity: 1; }

/* -- Popover : aide -- */
.popover .aide-modal { font-size: 12px; color: var(--ink-2); margin: 0 0 10px; }

/* -- Modal centrée (ex. gestion des options d'un champ) -- */
/* V8.57 — le voile et l'ombre portée de la modale restent en dur : un voile est
   du NOIR translucide dans les deux thèmes (il assombrit ce qu'il couvre, il ne
   suit pas la palette), et l'ombre `0 20px 50px` n'a d'équivalent ni dans
   `--ombre` ni dans `--ombre-flot` — on ne crée pas un jeton par ombre. */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(16, 28, 38, 0.45);
  display: flex; align-items: center; justify-content: center; z-index: 80; padding: 20px;
}
.modal {
  background: var(--card); border-radius: 8px; width: 100%; max-width: 440px;
  max-height: 82vh; display: flex; flex-direction: column;
  box-shadow: 0 20px 50px rgba(16, 28, 38, 0.35);
}
.modal-tete {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--line-soft);
}
.modal-tete h3 { margin: 0; font-size: 14px; }
.modal-fermer { font-size: 18px; line-height: 1; color: var(--ink-2); }
.modal-corps { padding: 14px 16px; overflow-y: auto; }

/* ⚠ V8.51 — CES RÈGLES N'AVAIENT JAMAIS EXISTÉ, ET ÇA SE VOYAIT.
   `.popover label` est habillé depuis toujours (ligne 478), `.form-edition >
   label` depuis la V3.4b, `.cc-modal-colonne label` a reçu ses jumelles en
   V8.42 — mais `.modal-corps`, le corps de TOUTES les modales génériques
   (`modalSaisie`, `modalChoix`, le guichet du support…), n'avait AUCUNE règle
   de formulaire. Un <label> y restait donc `display:inline`, collé à son
   champ — « Nom|ex. Restaurants » — et l'<input> gardait la largeur par
   défaut du navigateur, qui n'a aucun rapport avec celle de la modale.
   ⚠ CE N'EST PAS UNE RÉGRESSION : ça n'a jamais été écrit. Le correctif de
     la V8.42 portait sur la modale de COLONNE, qui est un autre écran avec
     ses propres sélecteurs — d'où l'impression que « c'était corrigé ».
   ⚠ ENFANTS DIRECTS (`>`) ET TYPES ÉNUMÉRÉS : le même corps accueille des
     modales très différentes (comparaison de brouillons, historique, listes
     d'options). On habille ce qui est POSÉ LÀ, jamais ce qui descend d'un
     composant qui a déjà ses règles. */
.modal-corps > label:not(.case) {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2);
  margin: 12px 0 4px;
}
.modal-corps > label:not(.case):first-child { margin-top: 0; }
.modal-corps > input[type="text"]:not(.copier-zone),
.modal-corps > input[type="email"], .modal-corps > input[type="password"],
.modal-corps > input[type="number"], .modal-corps > input[type="search"],
.modal-corps > input[type="url"], .modal-corps > input[type="date"],
.modal-corps > select,
.modal-corps > textarea:not(.copier-zone) {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line);
  border-radius: 6px; padding: 8px 10px; font-size: 13.5px; font-family: inherit;
}

.aide-modal { font-size: 12px; color: var(--ink-2); margin: 0 0 12px; }
.options-liste { display: flex; flex-direction: column; gap: 6px; max-height: 44vh; overflow-y: auto; }
.option-ligne { display: flex; gap: 6px; align-items: center; }
.option-ligne input[type="text"] { flex: 1; border: 1px solid var(--line); border-radius: 4px; padding: 4px 7px; font-size: 13px; }

/* -- Métadonnées (créé/modifié le & par) -- */
.carte-meta { font-size: 12.5px; color: var(--ink-2); }
.carte-meta .meta-ligne { display: flex; gap: 8px; padding: 3px 0; }
.carte-meta .meta-libelle { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-3); width: 70px; flex: none; }

/* ============================================================
   V2.3 — Éditeur à blocs (« Détail long », façon Notion)
   ============================================================ */
.carte-blocs { padding-bottom: 6px; }
.blocs-editeur { position: relative; font-size: 13.5px; line-height: 1.55; }
.blocs-zone { min-height: 120px; }
.blocs-pied { height: 48px; cursor: text; }

.bloc-ligne { display: flex; align-items: flex-start; position: relative; border-radius: 4px; }
.bloc-ligne.bloc-cache { display: none; }
.bloc-marge { width: 24px; flex: none; display: flex; justify-content: center; padding-top: 4px; }
.bloc-corps { flex: 1; min-width: 0; padding: 2px 0; }

.bloc-poignee {
  opacity: 0; border: 0; background: none; cursor: grab; color: var(--ink-3);
  font-size: 13px; padding: 1px 3px; border-radius: 4px; line-height: 1;
}
.bloc-ligne:hover .bloc-poignee { opacity: 1; }
.bloc-poignee:hover { background: var(--line-soft); color: var(--ink-2); }
.bloc-en-deplacement { opacity: .4; }
.bloc-drop-avant { box-shadow: 0 -2px 0 var(--accent); }
.bloc-drop-apres { box-shadow: 0 2px 0 var(--accent); }

/* -- texte riche -- */
.bloc-texte { outline: none; min-height: 1.5em; word-break: break-word; }
/* ⚠ V8.61 — L'INVITE NE S'AFFICHE QUE SUR LA LIGNE OÙ L'ON EST.
   Elle s'affichait sur CHAQUE bloc vide : cinq lignes vides, c'était cinq
   fois « Écrivez, ou tapez "/" … » empilés en gris dans la page. Ce n'était
   pas un défaut de rendu — c'est ce que la règle demandait — mais l'effet
   était celui d'un document qui répète une consigne au lieu d'attendre. Et
   le texte perd son sens en se répétant : une invite s'adresse à l'endroit
   où le curseur est, pas à cinq endroits à la fois.

   Deux cas la font apparaître, et deux seulement :
     · `:focus` — la ligne où l'on écrit. C'est le moment où elle sert.
     · `.bloc-invite` — posée par js/blocs.js sur l'unique bloc d'un document
       ENTIÈREMENT vide. Une page blanche sans un mot n'a l'air de rien : on
       ne sait ni si elle est prête, ni où cliquer. C'est le seul endroit où
       l'invite doit parler avant qu'on la sollicite.

   Les blocs vides non focalisés gardent leur hauteur (`min-height` ci-dessus)
   : la page ne saute pas quand le focus se déplace. */
.bloc-texte:empty:focus::before,
.bloc-texte.bloc-invite:empty::before,
.bloc-legende:empty::before {
  content: attr(data-placeholder); color: var(--ink-3); pointer-events: none;
}
.lecture-seule .bloc-texte:empty::before { content: ''; }
.bloc-texte a { color: var(--accent); }
.bloc-titre1 { font-size: 21px; font-weight: 700; margin-top: 10px; }
.bloc-titre2 { font-size: 17px; font-weight: 700; margin-top: 8px; }
.bloc-titre3 { font-size: 14.5px; font-weight: 700; margin-top: 6px; }
.bloc-avec-repli { display: flex; align-items: baseline; gap: 2px; }
.bloc-avec-repli .bloc-texte { flex: 1; min-width: 0; }
/* V2.4 — flèche agrandie (cible de clic confortable dans les documents) */
.bloc-repli {
  border: 0; background: none; cursor: pointer; color: var(--ink-3); flex: none;
  font-size: 15px; padding: 2px 6px; border-radius: 4px;
  transition: transform .12s; opacity: 0;
}
.bloc-repli:hover { background: var(--line-soft); color: var(--ink); }
.bloc-ligne:hover .bloc-repli, .bloc-repli.replie { opacity: 1; }
.bloc-repli.replie { transform: rotate(-90deg); color: var(--accent); }

.bloc-liste-ligne { display: flex; gap: 8px; }
.bloc-puce { flex: none; color: var(--ink-2); min-width: 14px; text-align: right; user-select: none; }
.bloc-liste-ligne .bloc-texte { flex: 1; min-width: 0; }

.bloc-citation { border-left: 3px solid var(--ink-2); padding-left: 12px; font-style: italic; color: var(--ink-2); }
/* V8.31 — LA CITATION EST DEVENUE UN CONTENEUR de blocs (comme l'encadré en
   V5.0e). Le filet et le retrait restent ceux de la citation d'avant ; ce qui
   change est que le corps peut désormais contenir des paragraphes, des listes,
   des titres, une image.
   ⚠ `font-style: italic` est posé sur le CONTENEUR et non sur le texte : les
   blocs enfants en héritent, et l'on peut donc redresser un mot en gras ou un
   bloc de code à l'intérieur sans se battre contre une règle plus spécifique. */
.bloc-citation-conteneur {
  border-left: 3px solid var(--ink-2); padding-left: 12px; margin: 0;
  font-style: italic; color: var(--ink-2);
}
/* Un bloc de code cité n'est pas de la prose : il ne s'italise pas. */
.bloc-citation-conteneur .bloc-code, .bloc-citation-conteneur pre { font-style: normal; }

.bloc-callout { display: flex; gap: 8px; border-radius: var(--r); padding: 10px 12px; align-items: flex-start; }
.bloc-callout .bloc-texte { flex: 1; min-width: 0; }
.bloc-callout-emoji { border: 0; background: none; cursor: pointer; font-size: 16px; line-height: 1.3; padding: 0; }
.bloc-palette-emoji { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px; }
.bloc-palette-emoji button { font-size: 16px; padding: 3px; }

/* ⚠ V8.57 — LE BLOC DE CODE EST DÉLIBÉRÉMENT SOMBRE, DÉJÀ EN THÈME CLAIR. Ce
   n'est pas une couleur oubliée, c'est la convention de tous les éditeurs, et
   elle reste lisible quand la palette s'inverse. Le fond, l'encre et les deux
   voiles blancs du bouton « copier » — qui se posent SUR ce fond sombre et non
   sur la page — restent donc écrits en dur. */
.bloc-code-enveloppe { position: relative; }
.bloc-code {
  font-family: var(--mono); font-size: 12.5px; background: #1d2b36; color: #dfe8ee;
  border-radius: var(--r); padding: 8px 34px 8px 12px; white-space: pre-wrap; outline: none;
  min-height: 1.5em; word-break: break-word; /* V3.1 : compact, grandit avec le contenu */
}
.bloc-code-copier {
  position: absolute; top: 6px; right: 6px; border: 0; border-radius: 4px;
  background: rgba(255, 255, 255, 0.12); color: #dfe8ee; cursor: pointer;
  font-size: 12px; padding: 3px 6px; opacity: 0; transition: opacity .1s;
}
.bloc-code-enveloppe:hover .bloc-code-copier { opacity: 1; }
.bloc-code-copier:hover { background: rgba(255, 255, 255, 0.24); }

.bloc-separateur { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }

/* -- tableau -- */
.bloc-tableau-enveloppe { position: relative; padding-right: 22px; padding-bottom: 22px; overflow-x: auto; }
/* V4.2 — bloc formule */
.bloc-formule { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: var(--line-soft); border-radius: 8px; }
.bloc-formule-sig { font-style: italic; font-weight: 700; color: var(--accent); }
.bloc-formule-eq { color: var(--ink-3); }
.bloc-formule-expr { flex: 1; padding: 5px 8px; border: 1px solid var(--line); border-radius: 6px; font-family: ui-monospace, monospace; font-size: 13px; }
.bloc-formule-res { font-weight: 600; }
.bloc-formule-res.err { color: var(--danger); font-weight: 400; font-size: 13px; }

/* V4.2 — bloc tableur (mini-Excel) */
.bloc-tableur { border-collapse: collapse; margin: 2px 0; }
.bloc-tableur th { background: var(--line-soft); border: 1px solid var(--line); padding: 2px 6px; font-size: 12px; color: var(--ink-3); font-weight: 600; text-align: center; min-width: 34px; }
.bloc-tableur th.coin, .bloc-tableur th.num { position: sticky; left: 0; }
.bloc-tableur td { border: 1px solid var(--line); padding: 0; }
.bloc-tableur td input { border: 0; outline: none; padding: 4px 6px; width: 100%; box-sizing: border-box; font-size: 13px; background: transparent; color: inherit; } /* V4.12h — suit la largeur de la colonne */
.bloc-tableur td input.f { color: var(--accent); font-weight: 600; }
.bloc-tableur td.f { color: var(--accent); font-weight: 600; padding: 4px 6px; }
.bloc-tableur td input:focus { box-shadow: inset 0 0 0 2px var(--accent); }
.bloc-tableur-barre { display: flex; gap: 6px; margin-top: 4px; }
/* V8.25 — la barre RÉDUITE du lecteur : seulement 💬 et sa consigne. Discrète,
   parce qu'elle vit sous un bloc qu'on ne peut pas modifier. */
.bloc-tableur-barre-lecture { align-items: center; opacity: .75; }
.bloc-tableur-barre-lecture:hover { opacity: 1; }
.bloc-tableur-barre-lecture .aide-inline { font-size: .82em; color: var(--ink-3); }

/* V5.1a — DÉPLACER une colonne / une ligne : poignée ⠿ dans le repère, révélée
   au survol, et trait d'insertion pendant le glisser. Le repère garde ses autres
   rôles (clic = sélection, bord droit = redimensionnement). */
.bloc-tableur th { position: relative; }
.bloc-tableur th .deplacer {
  position: absolute; left: 1px; top: 50%; transform: translateY(-50%);
  font-size: 9px; line-height: 1; color: var(--ink-3); cursor: grab;
  opacity: 0; transition: opacity .12s ease; padding: 2px 1px;
}
.bloc-tableur th.num .deplacer { left: 50%; top: 1px; transform: translateX(-50%); }
.bloc-tableur th:hover .deplacer { opacity: .75; }
.bloc-tableur th .deplacer:hover { opacity: 1; color: var(--accent); }
.bloc-tableur th .deplacer:active { cursor: grabbing; }
.bloc-tableur th.en-deplacement { opacity: .5; }
.bloc-tableur th.depot-avant { box-shadow: inset 2px 0 0 var(--accent); }
.bloc-tableur th.depot-apres { box-shadow: inset -2px 0 0 var(--accent); }
.bloc-tableur th.num.depot-avant { box-shadow: inset 0 2px 0 var(--accent); }
.bloc-tableur th.num.depot-apres { box-shadow: inset 0 -2px 0 var(--accent); }

/* V5.1 (RELI-449) — barre d'ONGLETS du tableur, posée au-dessus de la grille.
   Le « ＋ » reste une pastille discrète (même parti pris que le bloc colonnes)
   et le chevron ⌄ n'apparaît que sur l'onglet actif. */
/* ⚠ V8.57 — `var(--fond-2, #f7f9f9)` N'ÉTAIT PAS UN JETON. `--fond-2` n'est
   défini nulle part dans le dépôt : la valeur de repli s'appliquait donc
   toujours, et un blanc cassé écrit en dur se faisait passer pour un jeton
   thémable. Remplacé par `--sunk`, dont c'est exactement le rôle (surface
   enfoncée) — même rendu en clair, et il suit enfin le thème. */
.tableur-onglets { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; margin: 0 0 -1px; }
.tableur-onglet {
  border: 1px solid var(--line); background: var(--sunk); color: var(--ink-2);
  border-bottom-color: var(--line); border-radius: 6px 6px 0 0;
  padding: 3px 10px; font-size: 12.5px; max-width: 200px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; cursor: pointer;
}
.tableur-onglet:hover { border-color: var(--accent); color: var(--ink); }
.tableur-onglet.actif { background: var(--card, #fff); color: var(--ink); font-weight: 600; border-bottom-color: var(--card, #fff); }
.tableur-onglet-nom { border: 1px solid var(--accent); border-radius: 4px; padding: 1px 4px; font-size: 12.5px; width: 130px; }
.tableur-onglet-menu {
  border: none; background: none; color: var(--ink-3); cursor: pointer;
  padding: 0 4px; font-size: 13px; line-height: 1; border-radius: 4px; margin-left: -2px;
}
.tableur-onglet-menu:hover { background: var(--accent-pale); color: var(--accent); }
.tableur-onglet-plus {
  border: none; background: none; color: var(--ink-3); cursor: pointer;
  padding: 1px 6px; font-size: 13px; line-height: 1.2; border-radius: 5px; opacity: .3; transition: opacity .12s ease;
}
.bloc-ligne:hover .tableur-onglet-plus, .tableur-onglet-plus:hover, .tableur-onglet-plus:focus-visible { opacity: 1; color: var(--accent); }
.tableur-onglet-plus:hover { background: var(--accent-pale); }

/* V5.1 (RELI-448) — palette à deux étages : teintes, puis nuances de la teinte. */
.tableur-teintes { display: flex; gap: 5px; flex-wrap: wrap; align-items: center; max-width: 252px; }
.tableur-nuances { display: none; gap: 5px; flex-wrap: wrap; align-items: center; max-width: 252px; margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line); }
.tableur-nuances.ouvert { display: flex; }
.tableur-nuances .bloc-pastille { width: 22px; height: 22px; }
.tableur-nuances .bloc-pastille.actif { outline: 2px solid var(--accent); outline-offset: 1px; }
.tableur-pipette { width: 26px; height: 22px; padding: 0; border: 1px solid var(--line); border-radius: 5px; background: none; cursor: pointer; }

.bloc-tableau { border-collapse: collapse; width: calc(100% - 2px); }
.bloc-tableau td {
  border: 1px solid var(--line); padding: 5px 8px; min-width: 70px;
  outline: none; vertical-align: top;
}
.bloc-tableau.entete-ligne tr:first-child td { background: var(--line-soft); font-weight: 600; }
.bloc-tableau.entete-colonne td:first-child { background: var(--line-soft); font-weight: 600; }
.bloc-tab-plus {
  position: absolute; border: 1px dashed var(--line); background: var(--card);
  color: var(--ink-3); cursor: pointer; border-radius: 4px; opacity: 0; font-size: 12px;
}
.bloc-tableau-enveloppe:hover .bloc-tab-plus { opacity: 1; }
.bloc-tab-plus:hover { color: var(--accent); border-color: var(--accent); }
.bloc-tab-plus.col { top: 0; right: 0; bottom: 22px; width: 18px; }
.bloc-tab-plus.ligne { left: 0; right: 22px; bottom: 0; height: 18px; }

/* V5.0m — « ＋ » discret du bloc « Colonnes / cartes » : avant, le bouton
   d'ajout occupait une case entière de la grille (grosse boîte en pointillés
   large comme une colonne). Il vit désormais sous la grille, effacé tant qu'on
   ne survole pas le bloc. */
.bloc-cartes-barre { margin-top: 3px; line-height: 1; }
.bloc-cartes-plus {
  opacity: .22; transition: opacity .12s ease;
  padding: 1px 6px; font-size: 13px; color: var(--ink-3);
}
.bloc-ligne:hover .bloc-cartes-plus,
.bloc-cartes-plus:hover,
.bloc-cartes-plus:focus-visible { opacity: 1; color: var(--accent); }

/* -- médias -- */
.bloc-placeholder-media {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: var(--line-soft); border-radius: var(--r); padding: 10px 12px; color: var(--ink-2);
}
.bloc-placeholder-media input { flex: 1; min-width: 160px; border: 1px solid var(--line); border-radius: 4px; padding: 4px 8px; }
.bloc-placeholder-media .ou { font-size: 12px; color: var(--ink-3); }
/* V3.2 — taille par défaut raisonnable (420 px max) + poignée de redimensionnement */
.bloc-image { margin: 4px 0; max-width: 420px; position: relative; }
.bloc-image img { max-width: 100%; width: 100%; border-radius: var(--r); display: block; }
/* V8.57 — l'anneau blanc des poignées de redimensionnement se pose sur une
   IMAGE ou une vidéo, pas sur une surface du thème : il reste `#fff` dans les
   deux thèmes, c'est ce qui détache la poignée d'un fond quelconque. Même
   raison pour le noir de `.bloc-video`, qui est le fond d'une vidéo. */
.bloc-img-poignee {
  position: absolute; right: -4px; bottom: 18px; width: 14px; height: 14px;
  border-radius: 4px; background: var(--accent); border: 2px solid #fff;
  cursor: ew-resize; opacity: 0; transition: opacity .1s;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
}
.bloc-image:hover .bloc-img-poignee { opacity: 1; }
.bloc-legende { font-size: 12px; color: var(--ink-3); margin-top: 4px; outline: none; }
.bloc-video { position: relative; padding-top: 56.25%; border-radius: var(--r); overflow: hidden; background: #000; }
.bloc-video iframe, .bloc-video video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* -- V8.19 : bloc PDF — lecteur intégré, hauteur réglable à la poignée -- */
.bloc-pdf { position: relative; margin: 4px 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--card); }
.bloc-pdf iframe { width: 100%; height: calc(100% - 26px); border: 0; display: block; }
.bloc-pdf-lien { display: block; height: 26px; line-height: 26px; padding: 0 10px; font-size: 12px; color: var(--ink-3); text-decoration: none; border-top: 1px solid var(--line); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bloc-pdf-lien:hover { color: var(--accent); }
.bloc-pdf-poignee {
  position: absolute; left: 50%; bottom: -2px; transform: translateX(-50%);
  width: 44px; height: 10px; border-radius: 5px; background: var(--accent); border: 2px solid #fff;
  cursor: ns-resize; opacity: 0; transition: opacity .1s; box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
}
.bloc-pdf:hover .bloc-pdf-poignee { opacity: 1; }

/* -- V8.19 : bloc AVIS + type avis (popover, cellules) -- */
.bloc-avis { position: relative; border: 1px solid var(--line); border-radius: var(--r); padding: 10px 12px; background: var(--card); margin: 4px 0; }
/* V8.23 — le ⚙ des réglages : invisible tant qu'on ne s'approche pas. Un bloc
   de sondage doit ressembler à un sondage. Il reste atteignable au clavier
   (focus-visible) et au doigt (écran tactile : pas de :hover, donc visible). */
.bloc-avis-reglage {
  position: absolute; top: 6px; right: 6px; border: 0; background: transparent; cursor: pointer;
  font-size: 14px; line-height: 1; padding: 3px 5px; border-radius: 5px; color: var(--ink-3);
  opacity: 0; transition: opacity .12s;
}
.bloc-avis:hover .bloc-avis-reglage, .bloc-avis-reglage:focus-visible { opacity: 1; }
.bloc-avis-reglage:hover { background: var(--accent-pale); color: var(--ink); }
@media (hover: none) { .bloc-avis-reglage { opacity: .55; } }
.bloc-avis-question { width: 100%; font-weight: 600; border: 0; border-bottom: 1px dashed var(--line); border-radius: 0; padding: 4px 0; background: transparent; }
.bloc-avis-question-lect { font-weight: 600; margin-bottom: 6px; }
.bloc-avis-config { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 6px 0; font-size: 12px; color: var(--ink-3); }
.bloc-avis-note { font-size: 12px; color: var(--ink-3); margin: 6px 0 0; }
.bloc-avis-resultat { font-weight: 600; margin-top: 6px; }
.avis-choix { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.avis-choix-colonne { flex-direction: column; align-items: flex-start; gap: 3px; }
.avis-btn { letter-spacing: 2px; }
.avis-btn-actif { background: var(--accent-plein); color: var(--sur-accent); border-color: var(--accent-plein); }
.avis-repartition { margin-top: 6px; display: grid; gap: 2px; }
.avis-rep-ligne { display: grid; grid-template-columns: minmax(40px, auto) 1fr 26px; gap: 6px; align-items: center; font-size: 12px; }
.avis-rep-label { color: var(--ink-3); white-space: nowrap; }
.avis-rep-zone { background: var(--sunk); border-radius: 4px; height: 8px; overflow: hidden; }
.avis-rep-barre { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.avis-rep-nb { text-align: right; color: var(--ink-3); }
.cellule-avis .avis-vide { color: var(--ink-3); font-size: 12px; }

/* -- V8.19 : type image (vignettes) + date relative + formule surchargée -- */
.cellule-image { max-height: 42px; max-width: 120px; border-radius: 6px; display: block; object-fit: cover; }
.cellule-image-apercu { max-width: 200px; max-height: 140px; border-radius: var(--r); display: block; margin-bottom: 6px; object-fit: cover; }
.kanban-image { width: 100%; max-height: 140px; object-fit: cover; border-radius: 6px; margin: 4px 0; display: block; }
.date-relative { white-space: nowrap; }
.formule-surcharge { color: var(--accent); font-size: 11px; }
.gln-verdict { font-size: 13px; white-space: nowrap; }

/* ============================================================
   V8.28 (point 3) — LE MARQUEUR GS1 EST UN PSEUDO-ÉLÉMENT.
   ------------------------------------------------------------
   Le drapeau du pays émetteur (et le ⚠ des codes invalides) était un NŒUD DE
   TEXTE dans la cellule : une sélection à la souris suivie de Ctrl+C emportait
   « 🇫🇷 3017620422003 ». C'était le SEUL canal du produit par lequel une
   déduction de pays sortait — les seize autres (export CSV, PDF, DOCX, IA,
   MCP, API, page publiée, bouton « copier la ligne ») ne l'ont jamais fait,
   parce que le serveur ne sait pas ce qu'est un préfixe GS1.

   Le glyphe arrive par la propriété personnalisée `--cc-gln`, posée en JS
   (ccGlnMarqueur, js/api.js). Le contenu d'un `::before` n'entre JAMAIS dans
   le presse-papiers, quel que soit le navigateur — là où `user-select: none`
   sur un <span> ne tient pas partout sur une sélection de tableau.
   `user-select: none` est tout de même posé : ceinture et bretelles, et il
   empêche le double-clic de sélectionner « autour » du marqueur.

   Le marqueur est un INDICE DE SAISIE, pas une donnée : il ne s'imprime pas
   (cf. @media print plus bas), et il est `aria-hidden` — l'infobulle du code
   porte déjà la phrase complète, y compris ce que le préfixe ne dit PAS.
   ============================================================ */
.gln-marqueur {
  /* `inline-block` de largeur nulle : le marqueur ne pousse rien, c'est son
     ::before qui occupe la place. Sans cela, une cellule sans drapeau (plage
     non attribuée) et une cellule avec drapeau ne s'alignent pas. */
  display: inline-block;
  user-select: none; -webkit-user-select: none;
  font-size: 13px; line-height: 1;
}
.gln-marqueur::before {
  content: var(--cc-gln, '');
  margin-right: 4px;
  /* Les emojis drapeaux sont des glyphes en couleur : ils ne suivent pas
     `color`, et sont donc identiques en thème clair et en thème sombre. Le ⚠,
     lui, est un glyphe de texte : il HÉRITE de la couleur de la cellule, comme
     le nœud de texte qu'il remplace — aucune couleur n'est posée ici, pour que
     rien ne change de teinte dans aucun des deux thèmes. */
}

/* -- menu « / » -- */
.bloc-menu-slash {
  position: fixed; z-index: 300; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--ombre-flot);
  width: 290px; max-height: 320px; overflow-y: auto; padding: 4px;
}
.bloc-menu-titre { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); padding: 5px 8px 3px; }
/* V8.61 — le pied du menu « / » : les autres sigles. Discret par construction
   (pas de gras, pas d'icône, un filet au-dessus) : c'est un rappel, pas un
   sixième choix — il ne doit jamais se lire comme une ligne cliquable. */
.bloc-menu-pied {
  font-size: 11.5px; color: var(--ink-3); line-height: 1.5;
  padding: 6px 8px 2px; margin-top: 4px; border-top: 1px solid var(--line);
}
.bloc-menu-item {
  display: flex; gap: 10px; align-items: center; width: 100%; text-align: left;
  border: 0; background: none; cursor: pointer; padding: 6px 8px; border-radius: 4px;
}
.bloc-menu-item.sel, .bloc-menu-item:hover { background: var(--accent-pale); }
.bloc-menu-item .ic {
  flex: none; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 4px; background: var(--card); font-size: 12px; font-weight: 600;
}
.bloc-menu-item strong { display: block; font-size: 13px; }
.bloc-menu-item small { color: var(--ink-3); font-size: 11px; }

/* -- V4.7 : sélecteur de type de colonne (même langage visuel que le menu « / ») -- */
.champ-type { position: relative; }
.champ-type-bouton {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 6px 8px;
}
.champ-type-bouton:hover { border-color: var(--accent); }
.champ-type-bouton .ic {
  flex: none; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 4px; background: var(--card); font-size: 12px; font-weight: 600;
}
.champ-type-bouton strong { display: block; font-size: 13px; }
.champ-type-bouton small { display: block; color: var(--ink-3); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.champ-type-bouton .chevron { margin-left: auto; color: var(--ink-3); }

/* -- barre de mise en forme -- */
/* ⚠ V8.57 — MÊME INVERSION QUE `.topbar` : la barre posait `background:
   var(--ink)`, c'est-à-dire l'ENCRE employée pour ce qu'elle VAUT (« du
   foncé ») et non pour ce qu'elle EST. En thème sombre `--ink` devient clair :
   la barre flottante serait devenue blanche et ses boutons — écrits en clair —
   y auraient disparu. Elle prend donc `--topbar`, le jeton des surfaces qui
   restent foncées, et ses boutons `--topbar-txt`. Le survol reste un voile
   blanc : il se pose sur cette surface foncée, pas sur la page. */
.bloc-barre-fmt {
  position: absolute; z-index: 250; display: none; align-items: center; gap: 2px;
  background: var(--topbar); border-radius: 6px; padding: 3px 4px; box-shadow: 0 6px 18px rgba(24,43,58,.3);
}
.bloc-barre-fmt.visible { display: flex; }
.fmt-btn {
  border: 0; background: none; color: var(--topbar-txt); cursor: pointer; min-width: 26px;
  padding: 3px 6px; border-radius: 4px; font-size: 13px;
}
.fmt-btn:hover { background: rgba(255,255,255,.14); }
.fmt-couleur { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
.fmt-palette {
  display: none; position: absolute; top: 100%; left: 0; margin-top: 4px; z-index: 251;
  background: var(--card); border: 1px solid var(--line); border-radius: 6px; padding: 6px; gap: 4px;
}
.fmt-palette.ouverte { display: flex; }
.bloc-pastille {
  width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--line); cursor: pointer; padding: 0;
}
.bloc-pastille.sel { outline: 2px solid var(--accent); outline-offset: 1px; }
.bloc-palette { display: flex; gap: 6px; margin: 4px 0 8px; }

/* -- menus poignée / lien -- */
.bloc-menu-poignee { min-width: 230px; }
.bloc-menu-transfo { display: flex; flex-wrap: wrap; gap: 2px 8px; margin: 4px 0 8px; max-width: 340px; } /* V5.1 — le tableur y pose 7 boutons : on force le retour à la ligne plutôt qu'un popover démesuré */
.bloc-lien-resultats { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; max-height: 160px; overflow-y: auto; margin-top: 4px; }

/* la carte détail n'a plus de textarea : neutralise l'ancienne règle */
.detail-long .blocs-zone { min-height: 220px; }

/* ---------- V2.5 : liens, lieux, drag & drop colonnes, formules per() ---------- */
td .cellule-lien { color: var(--accent-fonce); text-decoration: underline; text-underline-offset: 2px; }
td .cellule-lieu-pin { text-decoration: none; font-size: 13px; }
.champ-lien-ctrl { display: inline-flex; gap: 6px; align-items: center; }
.champ-lien-ctrl input { flex: 1; }

/* colonnes du tableau : indicateur de dépôt pendant le glisser-déposer */
table.base th[draggable="true"] { cursor: grab; }
/* V7.0 (RELI-390) — pendant le glisser, la main se FERME, comme sur toutes les
   autres poignées du produit (.kanban-carte, .tache-poignee) : l'en-tête de
   colonne était la seule à garder la main ouverte. */
table.base th[draggable="true"]:active, th .col-grip:active { cursor: grabbing; }
table.base th.col-drop-avant { box-shadow: inset 3px 0 0 var(--accent); }
table.base th.col-drop-apres { box-shadow: inset -3px 0 0 var(--accent); }

/* bloc tableau (éditeur de documents) : poignées lignes / colonnes
   V3.1 — les poignées vivent dans l'enveloppe (superposition), plus dans les
   cellules éditables : le caret peut à nouveau se poser partout. */
.bloc-tab-drag {
  position: absolute; z-index: 6; border: 0; background: var(--card); color: var(--ink-3);
  font-size: 11px; line-height: 1; padding: 2px 3px; border-radius: 4px;
  cursor: grab; opacity: 0; transition: opacity .1s; user-select: none;
  box-shadow: 0 0 0 1px var(--line);
}
.bloc-tab-drag.colonne { transform: rotate(90deg); }
.bloc-tableau-enveloppe:hover .bloc-tab-drag { opacity: 1; }
.bloc-tableau td.tab-drop-haut { box-shadow: inset 0 3px 0 var(--accent); }
.bloc-tableau td.tab-drop-bas { box-shadow: inset 0 -3px 0 var(--accent); }
.bloc-tableau td.tab-drop-gauche { box-shadow: inset 3px 0 0 var(--accent); }
.bloc-tableau td.tab-drop-droite { box-shadow: inset -3px 0 0 var(--accent); }
.bloc-tableau-enveloppe { padding-left: 22px; padding-top: 20px; }

/* ---------- V2.9 : éditeur de cellule flottant (texte long visible) ---------- */
td.cellule-en-edition { position: relative; overflow: visible; }
textarea.editeur-cellule {
  position: absolute; top: 1px; left: 1px; z-index: 25;
  min-height: 32px; max-height: 220px; padding: 6px 8px; box-sizing: border-box;
  font: inherit; font-size: 13px; line-height: 1.45;
  border: 1.5px solid var(--accent); border-radius: 5px;
  background: var(--card); color: var(--ink);
  box-shadow: 0 8px 22px rgba(24, 43, 58, 0.18);
  resize: none; overflow-y: auto; white-space: pre-wrap;
}

/* ---------- V2.9 : formules de nœud — bloc large + vues de répartition ---------- */
.formule-carte.large { flex: 1 1 100%; max-width: none; }
.mini-graphe-reste { font-size: 11px; color: var(--ink-3); margin-top: 2px; font-weight: 400; }
.rep-zone { display: flex; align-items: center; gap: 14px; margin-top: 6px; flex-wrap: wrap; }
.rep-camembert { width: 92px; height: 92px; flex: none; }
.rep-legende { display: grid; gap: 3px; font-size: 12px; font-weight: 400; min-width: 160px; flex: 1; }
.rep-legende-ligne { display: flex; align-items: center; gap: 6px; }
.rep-pastille { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.rep-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 170px; color: var(--ink); }
.rep-nb { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--ink-2); white-space: nowrap; }
.rep-barre { display: flex; height: 14px; border-radius: 4px; overflow: hidden; margin: 8px 0 6px; min-width: 190px; }
.rep-barre-seg { display: block; min-width: 2px; }

/* réglages d'affichage dans le popover de formule */
.popover .ligne-affichage { display: flex; align-items: center; gap: 6px; font-size: 12.5px; flex-wrap: wrap; margin-top: 6px; color: var(--ink-2); }
.popover .ligne-affichage select, .popover .ligne-affichage input[type="number"] { width: auto; }

/* ---------- V3 : recherche du tableau + actions de ligne ---------- */
.recherche-tableau {
  border: 1px solid var(--line); border-radius: 6px; padding: 5px 9px;
  font-size: 13px; width: 220px; background: var(--card);
}
.recherche-tableau:focus { border-color: var(--accent); outline: none; }
.nb-resultats { font-size: 12px; color: var(--ink-3); font-family: var(--mono); }
.cellule-actions { white-space: nowrap; }
.cellule-actions .action-suppr:hover { color: var(--danger); }

/* ---------- V3 : kanban enrichi ---------- */
.kanban-col h4.reordonnable { cursor: grab; }
.kanban-col h4.reordonnable:active { cursor: grabbing; }
.kanban-col.kcol-drop-avant { box-shadow: inset 3px 0 0 var(--accent); }
.kanban-col.kcol-drop-apres { box-shadow: inset -3px 0 0 var(--accent); }
.kanban-ajout {
  width: 100%; box-sizing: border-box; border: 1px dashed var(--line);
  border-radius: 5px; padding: 5px 8px; font-size: 12.5px;
  background: transparent; color: var(--ink); margin-top: 6px;
}
.kanban-ajout::placeholder { color: var(--ink-3); }
.kanban-ajout:focus { border-style: solid; border-color: var(--accent); outline: none; background: var(--card); }
.kanban-champ { font-size: 12px; color: var(--ink-2); margin-top: 2px; }
.kanban-champ-nom { color: var(--ink-3); font-size: 11px; }

/* ---------- V3.1 : sauts de ligne visibles (description courte, cellules texte) ---------- */
.desc-courte-cellule, td.cellule-souple, .kanban-carte .d { white-space: pre-line; }

/* ---------- V3.1 : sélecteur d'emojis ---------- */
.emoji-selecteur { min-width: 292px; }
.emoji-selecteur input[type="search"] { width: 100%; margin-bottom: 6px; }
.emoji-groupes { display: flex; gap: 2px; margin-bottom: 6px; flex-wrap: wrap; }
.emoji-groupe-btn {
  border: 1px solid transparent; background: none; font-size: 15px; padding: 2px 5px;
  border-radius: 5px; cursor: pointer;
}
.emoji-groupe-btn:hover { background: var(--line-soft); }
.emoji-groupe-btn.actif { border-color: var(--accent); background: var(--accent-pale); }
.emoji-grille {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  max-height: 240px; overflow-y: auto;
}
.emoji-btn {
  border: 0; background: none; font-size: 19px; padding: 3px; border-radius: 5px;
  cursor: pointer; line-height: 1.2;
}
.emoji-btn:hover { background: var(--accent-pale); }

/* ---------- V3.1 : couleurs (fiche + options de select) ---------- */
.palette-couleurs { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.pastille-couleur {
  width: 26px; height: 26px; border-radius: 7px; border: 1px solid var(--line);
  cursor: pointer; padding: 0;
}
.pastille-couleur.sel { outline: 2px solid var(--accent-fonce); outline-offset: 1px; }
.pastille-couleur.mini { width: 16px; height: 16px; border-radius: 5px; flex: none; }
.pastille-couleur.mini.vide { background: repeating-linear-gradient(45deg, var(--card), var(--card) 3px, var(--line-soft) 3px, var(--line-soft) 6px); }
.option-ligne { display: flex; align-items: center; gap: 6px; }
.titre-avec-icone { display: flex; align-items: center; gap: 8px; }
.fiche-icone-btn {
  border: 1px solid transparent; background: none; font-size: 24px; line-height: 1;
  padding: 3px 5px; border-radius: 7px; cursor: pointer; flex: none;
}
.fiche-icone-btn:hover { border-color: var(--line); background: var(--line-soft); }
.fiche-icone-btn.vide { opacity: 0.35; }
.fiche-icone-btn:disabled { cursor: default; }
.fiche-couleur-btn {
  width: 16px; height: 16px; border-radius: 5px; border: 1px solid var(--line);
  background: repeating-linear-gradient(45deg, var(--card), var(--card) 3px, var(--line-soft) 3px, var(--line-soft) 6px);
  cursor: pointer; flex: none; padding: 0;
}
.fiche-couleur-btn:disabled { cursor: default; }
/* V8.57 — la pastille est peinte par l'UTILISATEUR (attribut `style`) : sa
   couleur est une donnée, et les teintes proposées sont claires. L'encre doit
   donc rester sombre dans les DEUX thèmes — `var(--ink)` la rendrait claire en
   sombre, illisible sur une pastille restée pâle. */
td .valeur-multi[style] { color: #182b3a; } /* pill colorée : texte sombre lisible */
.cellule-id { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }

/* ---------- V3.1 : bloc Mermaid ---------- */
.bloc-mermaid { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.bloc-mermaid-onglets { display: flex; gap: 0; border-bottom: 1px solid var(--line-soft); background: var(--line-soft); }
.bloc-mermaid-onglet {
  border: 0; background: none; padding: 5px 12px; font-size: 12px; cursor: pointer;
  color: var(--ink-2); border-right: 1px solid var(--line-soft);
}
.bloc-mermaid-onglet.actif { background: var(--card); color: var(--ink); font-weight: 600; }
.bloc-mermaid-diag { padding: 12px; overflow-x: auto; background: var(--card); text-align: center; }
.bloc-mermaid-diag svg { max-width: 100%; height: auto; }
.bloc-mermaid-err { color: var(--danger); font-size: 12.5px; text-align: left; }
.bloc-mermaid .bloc-code { border-radius: 0; }
.bloc-mermaid-aide { margin: 0; padding: 5px 10px; font-size: 11.5px; color: var(--ink-3); background: var(--card); }
/* V8.6 — cadre redimensionnable du diagramme. Sans largeur réglée, on garde le
   comportement V3.1 (taille naturelle, débordement en défilement horizontal) ;
   avec une largeur, le SVG s'étire pour la remplir — c'est ce qui permet
   d'AGRANDIR un petit schéma et pas seulement de contenir un grand. */
.bloc-mermaid-cadre { position: relative; }
.bloc-mermaid-cadre.dimensionne .bloc-mermaid-diag { overflow: visible; }
.bloc-mermaid-poignee { right: 2px; bottom: 6px; }
.bloc-mermaid-cadre:hover .bloc-mermaid-poignee { opacity: 1; }

/* ---------- V3.1 : code inline dans les textes ---------- */
.blocs-editeur code, .bloc-texte code {
  font-family: var(--mono); font-size: 0.88em; background: var(--sunk); color: var(--danger);
  padding: 1px 5px; border-radius: 4px;
}

/* ---------- V3.2 : affordance colonnes du tableau + pagination ---------- */
th .col-grip {
  opacity: 0; cursor: grab; color: var(--ink-3); font-size: 10px;
  margin-right: 5px; transition: opacity .1s; user-select: none;
}
th:hover .col-grip { opacity: 1; }
th .col-menu-btn {
  opacity: 0; border: 0; background: none; cursor: pointer; color: var(--ink-3);
  font-size: 11px; padding: 0 3px; margin-left: 4px; border-radius: 4px; transition: opacity .1s;
}
th:hover .col-menu-btn { opacity: 1; }
th .col-menu-btn:hover { background: var(--line-soft); color: var(--ink); }
.sel-pagination { border: 1px solid var(--line); border-radius: 5px; padding: 4px 6px; font-size: 12px; background: var(--card); }
.pagination { display: inline-flex; align-items: center; gap: 6px; }
.pagination-info { font-size: 12px; font-family: var(--mono); color: var(--ink-2); }

/* menu « / » : liste plus haute et défilable sans se fermer */
/* V8.2 — …mais jamais plus haute que la fenêtre : sur un portable en 720 px de
   haut, un menu ouvert au deux tiers de la page débordait sous le bord. */
.bloc-menu-slash { max-height: min(420px, calc(100vh - 24px)); }
/* Variante large : la palette de modèles montre une liste ET un aperçu. */
.bloc-menu-large { width: auto; max-width: min(620px, calc(100vw - 24px)); }

/* ---------- V3.2 : notes — Tâche (échéance/assigné), Fact (source), Idée ---------- */
/* V8.57 — le bleu de « fait » reste en dur : aucun jeton bleu n'existe, et le
   passer à l'accent le rendrait indistinguable de `.badge-type.decision`, déjà
   en pâle sarcelle. Or ces badges sont un CODE de catégorie : ils doivent
   rester distincts entre eux avant d'être thémables. Le couple fond clair /
   encre foncée se suffit et reste lisible en sombre. */
.badge-type.fact { background: #dcebf5; color: #2d5f86; }
.badge-type.idee { background: var(--warn-pale); color: var(--warn); }
.note-extras { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 3px; font-size: 12px; color: var(--ink-2); }
.note-echeance.retard { color: var(--danger); font-weight: 600; }
.note-assigne { color: var(--ink-2); }
.note-source { color: var(--accent-fonce); text-decoration: none; }
.note-source:hover { text-decoration: underline; }
.form-note-extras { display: inline-flex; gap: 6px; align-items: center; }
.form-note-extras input[type="date"], .form-note-extras select, .form-note-extras input[type="url"] {
  border: 1px solid var(--line); border-radius: 5px; padding: 4px 6px; font-size: 12px;
}

/* ---------- V3.3 : bloc tableau lié ---------- */
.bloc-tablie-barre { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.bloc-tablie-titre { font-size: 12.5px; font-weight: 600; color: var(--accent-fonce); text-decoration: none; }
.bloc-tablie-titre:hover { text-decoration: underline; }
.bloc-tablie-info { font-size: 11.5px; color: var(--ink-3); }
.bloc-tablie-env { padding-left: 0; padding-top: 0; }
.bloc-tableau.tablie td { font-size: 12.5px; }

/* ---------- V3.3b : indicateur de section repliée ---------- */
.bloc-replie-info {
  margin-left: 30px; padding: 2px 8px; font-size: 11.5px; color: var(--ink-3);
  cursor: pointer; border-radius: 4px; user-select: none;
}
.bloc-replie-info:hover { background: var(--line-soft); color: var(--ink-2); }

/* ---------- V3.4 : gestion des formulaires ---------- */
.form-item { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin-bottom: 10px; }
.form-item-tete { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.form-item-lien { display: flex; gap: 6px; margin-bottom: 6px; }
.form-item-lien input { flex: 1; border: 1px solid var(--line); border-radius: 5px; padding: 4px 8px; font-size: 12px; font-family: var(--mono); color: var(--ink-2); }

/* ---------- V3.4b : mise en forme des formulaires de saisie en modale ---------- */
.form-edition > label:not(.case) {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2);
  margin: 14px 0 4px; text-transform: uppercase; letter-spacing: 0.04em;
}
.form-edition > label:first-child { margin-top: 0; }
.form-edition > input[type="text"], .form-edition > textarea, .form-edition > select {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 10px; font-size: 13.5px; font-family: inherit;
}
.form-edition .form-section {
  border: 1px solid var(--line-soft); border-radius: 8px;
  padding: 10px 12px; margin-top: 14px; background: var(--sunk);
}
.form-edition .form-section > label:not(.case) {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2);
  margin: 0 0 6px; text-transform: uppercase; letter-spacing: 0.04em;
}
.form-edition .case { display: flex; align-items: flex-start; gap: 8px; font-size: 13.5px; margin: 6px 0; }
.form-edition .case input[type="checkbox"], .form-edition .case input[type="radio"] { margin-top: 2px; flex: none; }
.form-mode-aide { color: var(--ink-3); font-weight: 400; font-size: 12px; }
.form-sous-bloc { margin: 8px 0 2px 24px; }
.form-sous-bloc label:not(.case) { display: block; font-size: 12px; color: var(--ink-2); margin-bottom: 4px; }
.form-sous-bloc textarea,
.form-sous-bloc input[type="text"], .form-sous-bloc input[type="url"], .form-sous-bloc select {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line); border-radius: 6px;
  padding: 7px 9px; font-size: 13px; font-family: inherit; background: var(--input-bg);
}
/* V8.29 — le message de fin est une zone de texte de plein droit dans sa
   section, pas un sous-bloc indenté : il se saisit comme l'introduction. */
.form-edition .form-section > textarea {
  width: 100%; box-sizing: border-box; border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 10px; font-size: 13.5px; font-family: inherit;
}
/* V8.29 — LA LISTE DES CHAMPS PASSE SUR UNE COLONNE. Deux colonnes tenaient
   tant qu'une ligne portait une case et un nom ; avec la question reformulée
   ET la case « obligatoire », 200 px les écrasaient l'une sur l'autre. Une
   ligne = un champ, ses trois réglages alignés, et on lit la colonne
   « obligatoire » d'un seul coup d'œil vertical. */
.form-liste-champs {
  max-height: 240px; overflow-y: auto; display: block;
}
.form-champ-ligne {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 4px 2px; font-size: 13.5px;
}
.form-champ-ligne + .form-champ-ligne { border-top: 1px solid var(--line-soft); }
.form-champ-ligne > .case:first-child { min-width: 150px; flex: 0 0 auto; }
.form-champ-ligne input[type="text"] {
  border: 1px solid var(--line); border-radius: 5px; padding: 5px 8px; font-family: inherit; background: var(--input-bg);
}
.form-champ-ligne input[type="text"]:disabled { background: var(--sunk); color: var(--ink-3); }
.form-req.desactive { opacity: .45; }
.form-edition .actions .btn { padding: 8px 18px; font-size: 14px; }

/* la modale des formulaires est un peu plus large */
.modal { max-width: 560px; }

/* ===== V3.5 — configuration des vues d'un nœud (popover ⚙) ===== */
.cfg-vue-ligne { display: flex; align-items: center; gap: 4px; padding: 2px 0; }
.cfg-vue-ligne .btn-mini { padding: 0 5px; font-size: 12px; line-height: 1.4; }
.cfg-vue-ligne .btn-mini:disabled { opacity: 0.3; cursor: default; }
.cfg-vue-ligne .case { font-size: 13px; }

/* V3.5 — valeurs relationnelles cliquables (navigation vers la fiche liée) */
.valeur-rel { cursor: pointer; text-decoration: underline; text-decoration-color: var(--ink-3); text-underline-offset: 2px; }
.valeur-rel:hover { filter: brightness(0.95); text-decoration-color: currentColor; }
.champ-rel-ctrl { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.rel-liens { display: inline-flex; flex-wrap: wrap; gap: 4px; }

/* V3.5 — réordonner les formules de nœud (‹ › sur les cartes) */
.formule-bouger { display: inline-flex; gap: 0; opacity: 0; transition: opacity 0.12s; }
.formule-carte:hover .formule-bouger { opacity: 1; }
.formule-bouger .btn-mini { padding: 0 3px; }
.formule-bouger .btn-mini:disabled { opacity: 0.3; cursor: default; }

/* V3.5 — smart text : jetons $valeur et @mention dans l'éditeur à blocs */
/* V8.61 — même bande que `.cc-ref` (voir le commentaire de cette règle) : ces
   jetons cohabitent dans la même phrase, deux alignements différents s'y
   verraient. */
.cc-valeur, .cc-mention {
  display: inline-block; padding: 0 5px; border-radius: 4px; vertical-align: middle;
  font-size: 0.92em; line-height: 1.35; white-space: nowrap;
  user-select: all;
}
.cc-valeur { background: var(--accent-pale); color: var(--accent-fonce); border: 1px solid var(--line); }
.cc-mention { background: var(--prive-pale); color: var(--prive); border: 1px solid var(--line); font-weight: 600; }
.bloc-menu-smart .ic { font-weight: 700; }

/* V3.6 — sélecteur d'organisation (topbar) */
.sel-organisation {
  background: rgba(255,255,255,0.08); color: var(--topbar-txt);
  border: 1px solid var(--topbar-ligne); border-radius: 6px;
  padding: 4px 8px; font-size: 12.5px; max-width: 180px;
  cursor: pointer;
}
.sel-organisation option { color: var(--ink); background: var(--card); }

/* V3.7 — mini logo de la marque (emoji ou image) */
.marque-logo { margin-right: 6px; font-size: 1.05em; vertical-align: -2px; }
img.marque-logo { height: 20px; width: auto; border-radius: 4px; }

/* V3.7 — champ mot de passe avec œil */
.champ-mdp { position: relative; display: block; }
.champ-mdp input { width: 100%; box-sizing: border-box; padding-right: 34px; }
.btn-oeil {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer; font-size: 14px; padding: 4px;
  opacity: 0.65;
}
.btn-oeil:hover { opacity: 1; }
.lien-mdp-oublie { margin-top: 10px; font-size: 12.5px; }
.erreur-connexion.info { color: var(--ok, #3d7a46); }
.btn-compte {
  background: none; border: none; cursor: pointer;
  font-size: 12.5px; color: var(--topbar-attenue); padding: 4px 6px; border-radius: 6px;
}
.btn-compte:hover { background: rgba(255,255,255,0.08); }

/* V3.7 — onglet Rôles (Équipe) */
.role-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 8px; }
.role-grille > div > label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }
.role-liste { max-height: 180px; overflow-y: auto; border: 1px solid var(--line-soft); border-radius: 6px; padding: 6px 8px; }
.role-liste .case { margin: 3px 0; font-size: 13px; }
@media (max-width: 700px) { .role-grille { grid-template-columns: 1fr; } }

/* V3.7 — bandeau licence (sous-sites) */
.bandeau-licence { padding: 7px 14px; font-size: 13px; text-align: center; }
.bandeau-licence.grace { background: var(--warn-pale); color: var(--warn); }
.bandeau-licence.suspendu, .bandeau-licence.resilie { background: var(--danger-pale); color: var(--danger); font-weight: 600; }

/* V5.5 — bandeau « mise à jour en cours » (mode lecture seule de l'instance).
   Rayures discrètes : on reconnaît un chantier au premier coup d'œil, sans
   crier à la panne — le site fonctionne, il ne s'écrit simplement plus. */
.bandeau-maintenance {
  padding: 7px 14px; font-size: 13px; text-align: center; font-weight: 600;
  color: var(--warn); background: var(--warn-pale);
  background-image: repeating-linear-gradient(135deg, rgba(122, 92, 18, .07) 0 10px, transparent 10px 20px);
  border-bottom: 1px solid var(--line);
}
.page-connexion .bandeau-maintenance { border-radius: 8px; margin-bottom: 12px; border: 1px solid var(--line); }

/* V5.5 — état des interrupteurs d'instance (panneau super admin) */
.etiquette {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 600; margin-right: 6px;
}
.etiquette-ok { background: var(--ok-pale); color: var(--ok); }
.etiquette-alerte { background: var(--danger-pale); color: var(--danger); }
.carte-interrupteurs { border-left: 3px solid var(--warn); }

/* V7.1 (RELI-430) — BANDEAU MOBILE, REFAIT. L'ancien essai (V3.7) posait
   `flex-wrap` sur un bandeau à HAUTEUR FIXE de 52 px : dès que la deuxième
   rangée naissait, tout ce qu'elle contenait débordait du bandeau et
   s'éparpillait PAR-DESSUS le contenu de la page — les captures d'écran du
   ticket montrent exactement ça. La règle inverse est la bonne : UNE SEULE
   rangée de 52 px, toujours, et ce qui n'y tient pas change de forme au lieu
   de déborder — la recherche devient une surcouche à la demande (bouton 🔍),
   les briques Tâches/Messages gardent icône et bulle mais perdent leur
   libellé, et Équipe / Admin / compte / Quitter déménagent dans le menu ⋮.
   Même seuil (800 px) que le tiroir latéral : un seul « mode étroit ». */
@media (max-width: 800px) {
  .topbar { gap: 8px; padding: 0 10px; }
  .topbar .marque { max-width: 30vw; }
  .sel-organisation { max-width: 26vw; }
  .btn-rech-mobile, .btn-menu-mobile { display: inline-flex; }
  /* V8.57 — LE BOUTON DE THÈME DESCEND DANS LE MENU SUR ÉCRAN ÉTROIT.
     La rangée était pleine : loupe, thème, Tâches, Messages, et le menu du
     compte en dernier — c'est-à-dire le premier à sortir du cadre sur un
     téléphone étroit, ou à passer inaperçu au milieu de ses voisins. Le thème
     se règle une fois de temps en temps ; le compte se cherche. Celui qui se
     cherche reste, celui qui se règle descend d'un cran. Le choix reste
     complet dans le menu (ccLigneThemeMobile, js/app.js). */
  .btn-topbar-nav, .topbar .btn-compte, .topbar .btn-quitter, .topbar .btn-theme { display: none; }

  /* ⚠ ET LE MENU DU COMPTE NE SE FAIT PLUS ÉCRASER. `.marque` pouvait se
     réduire à zéro pendant que le dernier bouton sortait du cadre : sur un
     écran de 320 px, le nom du site disparaissait ET le menu devenait
     inatteignable. Le menu ne rétrécit jamais ; le nom du site, si — un nom
     tronqué reste un nom, un bouton absent n'est plus rien. */
  .topbar .btn-menu-mobile, .topbar .btn-rech-mobile, .topbar .btn-burger { flex: none; }
  .topbar .marque { min-width: 0; }
  .btn-lien-topbar { margin-right: 0; padding: 4px 7px; }
  .btn-lien-topbar .brique-txt { display: none; }
  /* la recherche quitte la rangée : surcouche sous le bandeau, à la demande */
  .topbar .recherche-globale { display: none; }
  .topbar.rech-ouverte .recherche-globale {
    display: block; position: fixed; top: 52px; left: 0; right: 0;
    max-width: none; padding: 8px 10px; background: var(--topbar);
    border-bottom: 1px solid var(--topbar-ligne); z-index: 39;
  }
  .topbar.rech-ouverte .recherche-globale input { padding-left: 32px; }
  .topbar.rech-ouverte .recherche-globale::before { left: 20px; top: 14px; }
}

/* V3.8 — landing / onboarding */
.landing-points { list-style: none; margin: 0 0 16px; padding: 0; }
.landing-points li { font-size: 13.5px; color: var(--ink-2); margin: 6px 0; }
.onboarding h3 { margin: 0 0 8px; font-size: 19px; }
.onboarding-points { display: flex; gap: 6px; justify-content: center; margin: 12px 0; }
.onboarding-point { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.onboarding-point.actif { background: var(--accent); }

/* V3.8 — impression de l'app : contenu seul (Ctrl+P décent partout) */
@media print {
  .topbar, .sidebar, .bandeau-licence, .onglets, .btn, .btn-lien, .btn-mini, .drop-racine { display: none !important; }
  .contenu { margin: 0 !important; padding: 0 !important; }
  body { background: #fff !important; }
  /* V8.0 (RELI-451) — LE BANDEAU DES SCÉNARIOS RESTE À L'IMPRESSION, à plat.
     Un tableau imprimé sous une hypothèse doit dire laquelle : sans cela, deux
     tirages du même tableau donnent deux jeux de chiffres et rien ne les
     distingue. On neutralise seulement l'apparence de formulaire — un <select>
     imprime son option choisie, un <input> sa valeur, donc le texte suffit. */
  .scen-ctrl { border: none !important; background: none !important; padding: 0 !important;
               -webkit-appearance: none; appearance: none; font-weight: 600; }
  .scenario-carte.surcharge { background: none !important; }
  /* V8.25 — la barre réduite du lecteur (💬 + sa consigne) n'a rien à faire sur
     un papier : le bouton était déjà masqué par la règle .btn-mini, restait sa
     phrase « Cliquez une cellule pour la commenter » sous chaque tableur. */
  .bloc-tableur-barre-lecture { display: none !important; }
  /* V8.28 (point 3) — le marqueur GS1 est une aide à la SAISIE : sur un
     tirage papier il n'apporte rien et affirme quelque chose de faux (le
     préfixe dit qui a délivré le code, pas d'où vient le produit). Le code
     nu, lui, reste imprimé tel qu'il est enregistré. */
  .gln-marqueur::before { content: none !important; }
  .gln-marqueur { display: none !important; }
}

/* V3.8b — cartes de paramètres empilées (labels au-dessus, champs pleine largeur) */
.form-empile > label:not(.case) { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2); margin: 12px 0 4px; }
.form-empile > input[type="text"], .form-empile > textarea {
  width: 100%; max-width: 560px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; font-size: 13.5px; font-family: inherit;
}
.form-empile .case { margin: 8px 0; }

/* V3.8b — onboarding : Passer / Suivant bien séparés */
.onboarding .actions { display: flex; justify-content: space-between; align-items: center; margin-top: 6px; }

/* V3.8b — bouton 🌐 quand la page est déjà publiée */
.onglet-config.publie, .btn.publie { color: var(--accent-fonce); font-weight: 700; }

/* V4.4 — panneau « variables disponibles » des blocs formule et tableur */
.bloc-vars { margin: 6px 0 2px; border: 1px solid var(--line); border-radius: 8px; background: var(--sunk); }
.bloc-vars summary { cursor: pointer; padding: 5px 9px; font-size: 12px; color: var(--ink-2); user-select: none; }
.bloc-vars-liste { display: grid; grid-template-columns: 1fr; gap: 2px; max-height: 180px; overflow: auto; padding: 4px 6px 7px; }
.bloc-vars-liste .btn-lien { text-align: left; white-space: normal; }
.bloc-vars-liste code { font-weight: 600; }
.bloc-vars-type { color: var(--ink-3); margin-left: 6px; font-size: 12px; }

/* V4.5 — formulaire d'informations de facturation (Abonnement) */
/* V9.2 — REPRISE DU STYLE. Les champs héritaient du navigateur : hauteurs
   inégales entre <input> et <select>, bordure fine à peine visible, aucun état
   de focus ni d'erreur. Trois conséquences concrètes : la grille paraissait
   bancale, on ne voyait pas où l'on tapait, et un refus du serveur n'avait
   nulle part où s'afficher. `align-items: start` (et non `end`) parce que les
   champs portent désormais une ligne d'erreur sous eux : aligner par le bas
   décalait toute la rangée dès qu'une erreur apparaissait. */
.fact-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 14px; margin: 10px 0; align-items: start; }
.fact-champ label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin: 0 0 5px; }
.fact-champ input, .fact-champ select {
  width: 100%; box-sizing: border-box;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--input-bg); color: var(--ink); font-size: 14px; line-height: 1.3;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.fact-champ select { height: 37px; }   /* même hauteur qu'un input : sans ça, la rangée « Type / Email » est de guingois */
.fact-champ input::placeholder { color: var(--ink-3); opacity: .75; }
.fact-champ input:hover:not(:disabled), .fact-champ select:hover:not(:disabled) { border-color: var(--ink-3); }
.fact-champ input:focus, .fact-champ select:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-pale);
}
/* L'astérisque n'est PAS décorative : c'est la seule marque qui distingue un
   champ dont l'absence bloquera le paiement. Elle doit donc rester lisible. */
.fact-champ .requis, .requis { color: #a03d2c; font-weight: 700; }
.fact-champ input.en-erreur, .fact-champ select.en-erreur { border-color: #a03d2c; background: #fdf6f4; }
.fact-champ input.en-erreur:focus, .fact-champ select.en-erreur:focus { box-shadow: 0 0 0 3px rgba(160, 61, 44, .18); }
.champ-erreur { margin: 5px 0 0; font-size: 12px; line-height: 1.35; color: #a03d2c; }
.champ-erreur[hidden] { display: none; }
.fact-large { grid-column: span 2; }
.fact-petit { max-width: 160px; }
@media (max-width: 640px) {
  .fact-large { grid-column: span 1; }
  .fact-petit { max-width: none; }   /* sur mobile, un champ bridé à 160px au milieu d'une colonne pleine largeur fait accident */
}
[data-theme="sombre"] .fact-champ input.en-erreur, [data-theme="sombre"] .fact-champ select.en-erreur { background: rgba(160, 61, 44, .12); }
[data-theme="sombre"] .fact-champ .requis, [data-theme="sombre"] .requis,
[data-theme="sombre"] .champ-erreur { color: #e9a091; }

/* V9.2 — GRILLE DES OFFRES : deux états visuels, pas un.
   « Votre formule » (ce qu'on paie déjà) et « Sélectionnée » (ce qu'on est en
   train de souscrire) se ressemblaient — le liseré ne bougeait pas au clic sur
   « Choisir », et le formulaire de paiement s'ouvrant plus bas, souvent hors
   écran, rien ne confirmait le choix. */
.grille-offres { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.carte-offre {
  border: 2px solid var(--line); border-radius: 10px; padding: 12px;
  display: flex; flex-direction: column; gap: 2px;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.carte-offre .offre-nom { font-weight: 700; }
.carte-offre .offre-desc { color: var(--ink-3); font-size: 12px; min-height: 30px; }
.carte-offre .offre-prix { font-weight: 600; margin: 6px 0 0; }
.carte-offre .offre-ttc { color: var(--ink-3); font-size: 12px; margin: 0 0 6px; }
.carte-offre .btn, .carte-offre .chip { margin-top: auto; align-self: flex-start; }
.carte-offre.plan-actuel { border-color: var(--accent); }
.carte-offre.plan-choisi {
  border-color: var(--accent); background: var(--accent-pale);
  box-shadow: 0 0 0 3px var(--accent-pale); transform: translateY(-1px);
}
/* Bouton d'une offre qu'on ne peut pas encore souscrire : il reste cliquable
   (le clic explique ce qui manque et emmène au champ), mais il n'a plus l'air
   d'une action prête. */
.btn.btn-attente { opacity: .6; }
.offre-bloquee { color: #a03d2c; }
.offre-bloquee[hidden] { display: none; }
[data-theme="sombre"] .offre-bloquee { color: #e9a091; }

/* ============================================================
   V5.2 (RELI-208) — NŒUDS COMMUNS ENTRE ORGANISATIONS
   Un vocabulaire visuel unique : le même pictogramme dans l'arbre, le même
   liseré dans le bandeau. Turquoise = « chez nous » (nous sommes propriétaires),
   ambre = « chez quelqu'un d'autre » (nous sommes invités) — la nuance qui
   évite de modifier des données hébergées ailleurs sans s'en rendre compte.
   ============================================================ */
/* Pastille générique : le projet utilisait `.chip` sans jamais la définir
   (seule `.chip-filtre` existait). On pose enfin la règle de base — les
   variantes ci-dessous ne font plus que la colorer. */
.chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px;
  border: 1px solid var(--line, #d4dcd9); border-radius: 999px;
  font-size: 12.5px; color: var(--ink-2); background: var(--card); white-space: nowrap;
}
.pastille-partage { display: inline-flex; align-items: center; margin-left: 5px; color: var(--warn); flex: 0 0 auto; }
.pastille-partage.proprio { color: var(--accent-fonce); }
.pastille-partage .cc-icone { vertical-align: -2px; }

.bandeau-partage {
  border: 1px solid var(--line); border-left: 4px solid var(--warn); background: var(--warn-pale);
  border-radius: 9px; padding: 10px 14px; margin: 2px 0 12px; font-size: 13.5px;
}
.bandeau-partage.proprio { border-color: var(--line); border-left-color: var(--accent); background: var(--accent-pale); }
.bandeau-partage .partage-titre { display: flex; align-items: center; gap: 4px; font-size: 14px; }
.bandeau-partage .partage-titre .cc-icone { vertical-align: -3px; }
.partage-corps { display: block; }
.partage-orgs { display: flex; flex-wrap: wrap; gap: 6px; margin: 7px 0 0; }
.chip-proprio { background: var(--accent-fonce); color: #fff; border-color: transparent; }
.partage-sous { color: var(--ink-3); font-size: 12.5px; }
.partage-note { color: var(--ink-2); font-size: 12.8px; line-height: 1.55; margin: 8px 0 0; }
/* Listes de la modale de partage et de l'onglet Équipe → Partages */
.partage-liste { border: 1px solid var(--line, #d4dcd9); border-radius: 8px; overflow: hidden; }
.partage-ligne {
  display: flex; align-items: center; gap: 8px; justify-content: space-between;
  padding: 6px 10px; border-top: 1px solid var(--line, #d4dcd9); font-size: 13.5px; flex-wrap: wrap;
}
.partage-liste .partage-ligne:first-child, .carte > .partage-ligne:first-of-type { border-top: none; }
.partage-ligne.inactif { opacity: 0.55; }
.partage-ligne code { background: var(--sunk); border-radius: 4px; padding: 1px 6px; font-weight: 600; letter-spacing: 0.04em; }
.partage-role { font-size: 12.5px; padding: 2px 6px; }
.partage-regles { margin: 8px 0 0; padding-left: 20px; font-size: 13px; line-height: 1.7; color: var(--ink-2); }

/* Avertissements : partage ouvert à des tiers / hébergement chez le propriétaire.
   Volontairement voyants — ce sont des consentements, pas de la décoration. */
.partage-alerte {
  border: 1px solid var(--warn); background: var(--warn-pale); border-radius: 8px;
  padding: 9px 12px; margin: 10px 0 0; font-size: 13px; line-height: 1.55; color: var(--warn);
}
.partage-erreur { color: var(--danger, #a03d2c); font-size: 13px; min-height: 18px; margin-top: 6px; }

/* V5.3 (RELI-208) — présence FÉDÉRÉE : l'organisation d'origine s'affiche à
   côté du prénom. Sur un nœud commun, « Camille » ne suffit plus à identifier
   quelqu'un — deux organisations peuvent avoir la leur. */
.presence-pill .presence-org {
  margin-left: 5px; padding: 0 6px; border-radius: 999px;
  /* V8.57 — le blanc translucide reste : il se pose SUR la pastille de présence,
     une surface colorée qui ne s'éclaircit dans aucun thème. */
  background: rgba(255, 255, 255, 0.16); font-size: 11px; font-weight: 600; white-space: nowrap;
}

/* V5.3 (RELI-208) — nœud FÉDÉRÉ : la ligne d'état de la copie locale, dans le
   bandeau du nœud partagé (adresse de l'hôte, dernière synchronisation). */
.partage-fed {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 7px; font-size: 12.8px; color: var(--ink-2);
}
.partage-fed a { color: var(--accent-fonce); word-break: break-all; }
.partage-fed .btn-lien { margin: 0; }
/* V5.3 — copie locale d'un nœud fédéré non rafraîchie : la pastille vire au rouge. */
.pastille-partage.desync { color: var(--danger, #a03d2c); }

/* V5.4 — premier démarrage d'une instance (créer / importer) et rapport d'import. */
.boite-install { max-width: 460px; }
.boite-install .onglets { margin-bottom: 12px; }
.install-journal { margin-top: 10px; }
.install-tables {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 2px 12px; margin: 8px 0; font-size: 12.5px; color: var(--ink-2);
}
.install-tables > div { display: flex; justify-content: space-between; border-bottom: 1px dotted var(--line, #d4dcd9); }

/* ============================================================
   V5.6 (RELI-307) — ÉLÉMENTS PRIVÉS DANS UNE ORGANISATION
   Le code couleur prolonge celui du partage V5.2 sans le brouiller :
     · turquoise (--accent-fonce) = chez nous / autorisé  → partage propriétaire
     · ambre (#b07b16)            = chez quelqu'un d'autre → partage invité
     · VIOLET (#6b4f9e)           = restreint aux personnes → PRIVÉ
   Une troisième teinte plutôt qu'une nuance des deux premières : « partagé
   avec une autre organisation » et « caché à mes collègues » sont deux
   affirmations opposées, elles ne doivent jamais se confondre au coin de l'œil.
   ============================================================ */

.pastille-prive { display:inline-flex; align-items:center; margin-left:5px; color:var(--prive); }
.pastille-prive.proprio { color:var(--prive); }
/* V8.57 — l'invité était un second violet écrit en dur, qui restait clair sur fond
   clair en thème sombre. Aucun jeton ne dit « le privé, en atténué » et on n'en
   crée pas : on le DÉRIVE vers le fond de page, donc il s'atténue dans le sens du
   thème en vigueur au lieu d'être figé. */
.pastille-prive:not(.proprio) { color:color-mix(in srgb, var(--prive) 70%, var(--paper)); }   /* invité : je ne suis pas chez moi */
.pastille-prive .cc-icone { vertical-align:-2px; }

.bandeau-prive {
  display:flex; gap:14px; align-items:flex-start; flex-wrap:wrap;
  border:1px solid var(--line); border-left:4px solid var(--prive); background:var(--prive-pale);
  border-radius:8px; padding:10px 14px; margin:0 0 14px;
}
.bandeau-prive.proprio { border-color:var(--line); border-left-color:var(--prive); }
.prive-corps { flex:1 1 320px; min-width:0; }
.prive-titre { display:flex; align-items:center; gap:6px; font-weight:600; color:var(--prive); }
.prive-titre .cc-icone { vertical-align:-2px; }
.prive-orgs { display:flex; flex-wrap:wrap; gap:4px; margin-top:6px; }
.prive-note { font-size:12px; color:var(--ink-3); margin-top:5px; }
.prive-actions { display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
.prive-intro { margin-top:0; font-size:13px; color:var(--ink-3); }
.prive-alerte { font-size:12px; color:var(--danger); margin:6px 0 0; }

.prive-liste { display:flex; flex-direction:column; gap:2px; margin:8px 0; }
.prive-ligne {
  display:flex; align-items:center; gap:10px; justify-content:space-between;
  padding:6px 8px; border-radius:6px;
}
.prive-ligne:nth-child(odd) { background:var(--line-soft); }
.prive-ligne-fin { display:flex; align-items:center; gap:6px; }
.prive-ajout { display:flex; gap:6px; align-items:center; flex-wrap:wrap; margin-top:10px; }
.prive-bloc { margin-bottom:18px; }
.prive-bloc h4 { margin:0 0 2px; }

.chip-prive { background:var(--prive-pale); color:var(--prive); border:1px solid var(--line); }
.prive-note-corbeille { border-left:3px solid var(--prive); padding-left:8px; }

/* La case « Garder privé » de la modale de création. Volontairement discrète :
   elle ne doit pas se lire comme un réglage à trancher, mais comme une option
   qu'on ignore neuf fois sur dix. */
.prive-case {
  display:grid; grid-template-columns:auto 1fr; gap:2px 8px; align-items:center;
  margin:10px 0 4px; padding:8px 10px; border:1px solid var(--line); border-radius:8px;
  background:var(--prive-pale); cursor:pointer; font-size:13px;
}
.prive-case input { margin:0; }
.prive-case > span:nth-of-type(1) { font-weight:600; color:var(--prive); display:flex; align-items:center; gap:5px; }
.prive-case-aide { grid-column:2; font-size:12px; line-height:1.35; }

/* L'interrupteur « créer en privé » de la ligne de nouvelle fiche : éteint il
   se fond dans les actions, allumé il est franchement visible — on ne doit
   jamais créer trois brouillons privés sans s'en rendre compte. */
.bascule-prive { color:var(--ink-3); padding:0 5px; white-space:nowrap; }
.bascule-prive.actif { color:#fff; background:var(--prive); border-radius:5px; }
/* V6.1 (RELI-321) — le bouton porte son nom : une icone de cadenas seule
   passait pour de la decoration, et c'etait le seul moyen de creer une fiche
   privee. Le libelle s'efface sur les ecrans etroits, ou la place manque. */
.bascule-prive-txt { font-size:11px; letter-spacing:.02em; }
.kanban-prive { display:block; margin:2px 0 0 2px; text-align:left; }
/* Pas de `display:none` sous 700px : masquer le libelle ramenerait exactement
   l'icone muette que la V6.1 corrige. On reduit, on ne supprime pas. */
@media (max-width: 700px) { .bascule-prive-txt { font-size:10px; } }

.prive-regles h4 { display:flex; align-items:center; gap:6px; margin:0 0 4px; }

/* ⚠ V8.57 — CE BLOC EST UN SECOND THÈME SOMBRE, ET IL N'ÉCOUTE PAS LE NÔTRE. Il
   suit le réglage du SYSTÈME, alors que le thème du produit se choisit dans
   l'application (`html[data-theme="sombre"]`, app2.css) : sur un poste en sombre, il
   repeint ces quatre règles même quand l'utilisateur a demandé le thème clair. Les
   valeurs restent en dur — les passer en jetons recopierait le thème sombre
   par-dessus lui-même. C'est la règle entière qui est de trop, mais la retirer se
   décide ailleurs que dans un balayage de couleurs. */
/* V8.57 — CE BLOC ÉCOUTAIT LE SYSTÈME, PAS LE RÉGLAGE DU PRODUIT.
   Il datait d'avant le thème (V5.6) et faisait ce qu'on faisait à l'époque :
   un `@media (prefers-color-scheme: dark)`. Depuis que Relieo a son propre
   réglage, cela produit deux défauts opposés et tous deux invisibles à la
   relecture :
     · sur une machine en sombre, il repeignait le privé en violet foncé même
       quand la personne avait explicitement demandé le thème CLAIR ;
     · sur une machine en clair, il ne se déclenchait PAS alors que la personne
       avait demandé le thème sombre — le privé y restait la seule zone claire.
   Il écoute désormais `data-theme`, comme tout le reste. Les valeurs sont
   celles qui étaient là, à ceci près qu'elles passent par les jetons du privé
   quand ceux-ci disent déjà la même chose.
   ⚠ RÈGLE GÉNÉRALE : dans ce dépôt, plus aucun `@media (prefers-color-scheme)`.
     La résolution système ⇄ réglage se fait UNE fois, en JavaScript
     (js/ui.js), et n'a pas à être refaite dans chaque feuille. */
/* ⚠ PAS D'IMBRICATION CSS ICI. Elle serait plus courte à lire, et le reste du
   dépôt n'en emploie nulle part : une feuille qui mélange les deux écritures
   se relit deux fois. Sélecteurs complets, comme partout ailleurs. */
html[data-ui="v2"][data-theme="sombre"] .bandeau-prive { background: var(--prive-pale); border-color: #3d3450; }
html[data-ui="v2"][data-theme="sombre"] .prive-case { background: var(--prive-pale); border-color: #3d3450; }
html[data-ui="v2"][data-theme="sombre"] .prive-titre,
html[data-ui="v2"][data-theme="sombre"] .chip-prive { color: var(--prive); }
html[data-ui="v2"][data-theme="sombre"] .chip-prive { background: #2e2740; border-color: #3d3450; }
html[data-ui="v2"][data-theme="sombre"] .pastille-prive,
html[data-ui="v2"][data-theme="sombre"] .pastille-prive.proprio { color: var(--prive); }

/* ============================================================
   V5.7 (RELI-312) — COMMENTAIRES, MENTIONS ET SUIVIS
   Couleur dédiée : ambre profond. Le turquoise est l'accent du produit, le
   violet appartient au privé (V5.6), l'ambre clair au partage — restait une
   teinte chaude et lisible sur le papier, qui dit « quelqu'un a écrit ici »
   sans crier. Le surlignage reprend le jaune universel du surligneur : ce
   n'est pas l'endroit où être original.
   ============================================================ */
:root {
  --com: #9a6a12;
  --com-pale: #fdf3dc;
  --com-surlignage: #ffe9a8;

  /* ------------------------------------------------------------------
     V8.54 — L'AMBRE DIT « COMMENTAIRE », PAS « MOI ».

     `--com-pale` remplissait DEUX rôles à la fois : la trace d'un commentaire
     (son emploi d'origine, V5.7) et le fond de mes propres messages plus de
     la conversation sélectionnée (V5.8/V6.2). D'où deux défauts qui n'en font
     qu'un.

       1. Un aplat. Sur un fil un peu long, la moitié droite de l'écran devient
          un bloc crème continu : ce n'est plus un accent, c'est un fond. Une
          couleur chaude tient à la CUILLÈRE, pas à la louche.
       2. Le sens s'efface. Si l'ambre est déjà partout où j'écris, elle ne
          signale plus rien quand elle apparaît sur un passage commenté.

     Donc : mes messages et la conversation ouverte prennent un NEUTRE — une
     nuance de l'encre du produit, pas une couleur de plus. L'ambre ne sert
     plus qu'à ce qu'elle a toujours voulu dire : un commentaire, un non-lu.

     ⚠ V8.55 — ET RIEN NE REMPLACE LE CRÈME. La V8.54 avait ajouté, en plus du
       fond neutre, un liseré ambre de 3 px sur chaque bulle et sur la
       conversation ouverte, par réflexe : retirer une couleur semblait exiger
       d'en poser une autre. Ça ne l'exigeait pas. L'alignement, la forme du
       coin et le fond disaient déjà tout ; le liseré n'ajoutait pas une
       information, il ajoutait un ornement — et un ornement qui n'informe pas
       se voit immédiatement pour ce qu'il est. Le jeton `--msg-moi-accent`
       qu'il utilisait a été SUPPRIMÉ plutôt que laissé inutilisé : un jeton
       orphelin finit toujours par être réemployé pour autre chose.

     ⚠ Ce sont des JETONS, pas des valeurs posées dans les règles : le thème
       sombre (app2.css) les redéfinit, ce que `--com-pale` codé en dur
       n'aurait jamais permis — mes messages y étaient d'ailleurs crème vif
       sur fond marine, seule surface claire de l'écran.
     ------------------------------------------------------------------ */
  --msg-moi: #f1f4f5;
  --msg-moi-bord: #dde5e8;
}

/* --- Surlignage d'un passage commenté ---------------------------------
   Posé par la CSS Custom Highlight API, DONC HORS DU DOM : aucune balise
   n'est injectée dans le contenu éditable (sanitiserHtml la supprimerait, et
   contenteditable la réécrirait dans le bloc). */
::highlight(commentaire) { background: var(--com-surlignage); color: inherit; }
/* V8.57 — le surlignage ACTIF était un jaune vif figé : en thème sombre il restait
   éclatant sous un texte devenu clair, donc illisible, là où `--com-surlignage` suit
   déjà le thème. Aucun jeton ne dit « le même, en plus marqué » et on n'en ajoute
   pas : on pousse le surlignage vers l'ambre du commentaire, ce qui l'assombrit en
   clair et l'éclaircit en sombre — dans les deux cas, plus marqué que son voisin. */
::highlight(commentaire-actif) { background: color-mix(in srgb, var(--com-surlignage) 70%, var(--com)); color: inherit; }

/* Repli pour les navigateurs sans CSS Custom Highlight API : le bloc entier
   porte un liseré. Moins précis, jamais destructeur. */
@supports not (selector(::highlight(x))) {
  .bloc-ligne.a-commentaire .bloc-texte { box-shadow: inset 3px 0 0 var(--com-surlignage); }
}
.bloc-ligne.a-commentaire { cursor: pointer; }
tr.tr-commentee > td:first-child { box-shadow: inset 3px 0 0 var(--com); }
tr.tr-commentee { cursor: pointer; }

/* Bloc visé par un lien profond (?b=…) : mis en évidence à l'arrivée. */
.bloc-cible { animation: cc-bloc-cible 2.2s ease-out; border-radius: var(--r); }
@keyframes cc-bloc-cible {
  0%, 60% { background: var(--com-pale); }
  100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) { .bloc-cible { animation: none; background: var(--com-pale); } }

/* --- Brique « Messages » du bandeau et sa bulle ------------------------ */
.btn-messages { position: relative; }
/* V8.57 — ces deux voiles blancs se posent SUR le bandeau, foncé dans les deux
   thèmes (`--topbar`) : ils restent du blanc translucide, pas une surface. */
.btn-messages.actif { background: rgba(255, 255, 255, .14); border-radius: var(--r); }
.topbar-bulle {
  position: absolute; top: 2px; right: -2px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: var(--r); background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center;
}
.topbar-bulle[hidden] { display: none; }

/* --- Barre latérale en mode conversations ------------------------------ */
/* V6.2 (RELI-322) — FIN DU BLANC SUR BLANC. La sidebar est `var(--card)`
   (#ffffff) ; on y posait des cartes `var(--card)` separees par un liseré
   `--line-soft` (#e4e9e7). Nulle part ailleurs l'app ne fait cela : une carte
   est toujours du blanc SUR `--paper`. On donne donc son fond de page au
   panneau, et les lignes redeviennent des cartes. Meme geste pour la bordure :
   `--line`, celle de `.carte`, `.popover` et `.sidebar` — le langage
   « panneau » de l'app — au lieu du `--line-soft` deux crans plus clair. */
.conversations { flex: 1; overflow: auto; padding: 8px; background: var(--paper); }
.conversations[hidden] { display: none; }
.conv-tete { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.conv-ligne {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
  width: 100%; text-align: left; padding: 8px 10px; margin-bottom: 4px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); cursor: pointer;
}
.conv-ligne:hover { border-color: var(--com); }
.conv-ligne.non-lu { border-left: 3px solid var(--com); }
.conv-nom { font-weight: 700; }
.conv-sous { grid-column: 1; font-size: 11px; color: var(--ink-3); }
.conv-bulle {
  grid-row: 1 / span 2; align-self: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r);
  background: var(--com); color: #fff; font-size: 11px; font-weight: 800; line-height: 18px; text-align: center;
}
.conv-separateur { height: 1px; background: var(--line); margin: 10px 0 6px; }
.conv-liste { display: flex; flex-direction: column; gap: 4px; }
.conv-entree {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  text-decoration: none; color: inherit;
}
.conv-entree:hover { border-color: var(--com); }
.conv-entree.non-lu { border-left: 3px solid var(--com); }
.conv-entree-objet { font-size: 11px; font-weight: 700; color: var(--ink-2); }
.conv-entree-passage { font-size: 11px; color: var(--com); font-style: italic; }
.conv-entree-texte { font-size: 12px; }
.conv-entree time { font-size: 10px; color: var(--ink-3); }

/* --- Fil de discussion (popover) et panneau ---------------------------- */
/* V8.34 — `min-width: 320px` est un PLANCHER DE CONFORT, pas une contrainte de
   fonctionnement : un fil de discussion plus étroit se lit mal, mais un fil
   plus large que son parent DÉBORDE, et un plancher en pixels ne se laisse
   jamais comprimer. Sur un téléphone de 360 px, le parent (modale ou panneau)
   fait moins que ça une fois ses marges déduites. `min(320px, 100%)` garde le
   plancher partout où il tient et l'abandonne là où il ne tient pas —
   c'est exactement ce qu'on voulait dire. */
.com-fil { min-width: min(320px, 100%); max-width: 420px; display: flex; flex-direction: column; gap: 8px; }
.com-passage {
  margin: 0; padding: 6px 10px; border-left: 3px solid var(--com-surlignage);
  background: var(--com-pale); border-radius: 0 var(--r) var(--r) 0;
  font-style: italic; font-size: 12px; color: var(--ink-2);
}
.com-passage.orphelin { border-left-color: var(--ink-3); background: var(--line-soft); }
.com-passage.orphelin em { font-style: normal; color: var(--ink-3); font-size: 11px; }
.com-message { padding: 6px 0; border-top: 1px solid var(--line-soft); }
.com-message:first-of-type { border-top: 0; }
.com-message.supprime { color: var(--ink-3); font-size: 12px; }
.com-tete { display: flex; align-items: baseline; gap: 6px; font-size: 12px; }
.com-tete time { color: var(--ink-3); font-size: 11px; margin-left: auto; }
.com-tete em { color: var(--ink-3); font-size: 10px; font-style: normal; }
.com-externe { color: var(--com); font-size: 11px; font-weight: 700; }
.com-corps { white-space: pre-wrap; font-size: 13px; margin-top: 2px; }
.com-actions { display: flex; gap: 6px; margin-top: 2px; }

.com-saisie { position: relative; }
.com-champ { width: 100%; resize: vertical; font: inherit; font-size: 13px; }
.com-jetons { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.com-jeton {
  display: inline-flex; align-items: center; gap: 3px; padding: 1px 6px;
  border-radius: var(--r); background: var(--line-soft); color: var(--ink-2);
  font-size: 11px; font-weight: 600;
}
/* V6.2 — un seul accent dans cet ecran : l'ambre de la V5.7. Une mention
   ordinaire etait en sarcelle (`--accent-pale`), ce qui faisait cohabiter les
   deux accents de l'app sans que rien ne distingue leurs roles. Elle passe au
   NEUTRE, et l'ambre reste ce qu'il a toujours ete ici : le signal.
   ⚠ NE PAS teindre la base en `--com-pale` : le premier jet l'a fait, et
   `.externe` devenait alors indiscernable d'une mention interne — or c'est
   precisement l'information que la V5.8 s'est engagee a toujours donner. */
.com-jeton.externe { background: var(--com-pale); color: var(--com); border: 1px solid var(--com-surlignage); }
.com-jeton em { font-style: normal; opacity: .75; }
.com-mentions-menu {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 320;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  /* V6.2 — ombre TEINTEE ENCRE, celle de .popover, au lieu d'un noir pur. */
  box-shadow: var(--ombre-flot); max-height: 200px; overflow: auto;
}
.com-mentions-menu button { display: block; width: 100%; text-align: left; padding: 5px 10px; }
.com-mentions-menu em { color: var(--com); font-style: normal; font-size: 11px; }

/* V8.34 — MÊME DÉFAUT QUE .com-fil, EN PIRE, ET MESURÉ : la modale hôte fait
   width:100%/max-width:440px moins 40 px de fond et 32 px de gouttières, soit
   280 px sur un écran de 320 et 350 px sur un écran de 390. Ce contenu en
   réclamait 380 : il sortait de sa propre modale de 100 px, sous le voile,
   hors d'atteinte du doigt — la modale ne défile pas horizontalement. */
.com-modale { display: flex; flex-direction: column; gap: 10px; min-width: min(380px, 100%); }
.com-ia { display: flex; align-items: flex-start; gap: 6px; font-size: 12px; flex-wrap: wrap; }
.com-ia em { flex-basis: 100%; color: var(--ink-3); font-size: 11px; font-style: normal; padding-left: 20px; }
.com-ia-mini { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--ink-2); }

.com-panneau-corps { display: flex; flex-direction: column; gap: 6px; }
.com-resume {
  display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left;
  padding: 8px 10px; background: var(--card);
  border: 1px solid var(--line); border-left: 3px solid var(--com-surlignage);
  border-radius: var(--r); cursor: pointer;
}
.com-resume:hover { border-color: var(--com); }
.com-resume.non-lu { border-left-color: var(--com); }
.com-resume.orphelin { border-left-color: var(--ink-3); }
.com-resume-passage { font-size: 12px; font-style: italic; color: var(--com); }
.com-resume-extrait { font-size: 13px; }
.com-resume-pied { font-size: 11px; color: var(--ink-3); }
.com-resume-pied em { font-style: normal; }
.com-resolu { border-top: 1px solid var(--line); padding: 8px 0; }

/* En lecture seule, la barre flottante se réduit au seul bouton
   « Commenter » : commenter n'est pas modifier. */
.bloc-barre-fmt-lecture { padding: 2px; }

/* ============================================================
   V5.8 (RELI-313) — MESSAGERIE : CONVERSATIONS ENTRE PERSONNES
   Aucune couleur nouvelle : la messagerie reprend l'ambre de la V5.7. Les
   deux fonctionnalités forment une seule brique dans le bandeau, une seule
   pastille, une seule liste — leur donner deux teintes suggérerait deux
   endroits, alors qu'il n'y en a qu'un.
   ============================================================ */

/* V8.54 — la conversation ouverte : fond neutre, liseré ambre à gauche.
   V8.55 — et le liseré ambre s'en va aussi. La V8.54 l'avait gardé en pensant
   qu'il fallait remplacer le fond crème par autre chose. Il ne fallait rien
   remplacer : le FOND suffit à dire quelle conversation est ouverte, et
   `.conv-entree.non-lu` a déjà, lui, un liseré ambre qui veut dire quelque
   chose de précis. Deux traits ambre voisins pour deux sens différents, c'est
   un décor, pas une information — et le décor se reconnaît à ce qu'on peut le
   retirer sans rien perdre. */
.conv-entree.actif { border-color: var(--msg-moi-bord); background: var(--msg-moi); }
.conv-externe { font-style: normal; color: var(--com); font-size: 10px; font-weight: 700; }
.conv-entree-objet .conv-bulle { margin-left: auto; }
.conv-entree-objet { display: flex; align-items: center; gap: 4px; }

/* --- Écran d'une conversation ------------------------------------------ */
.msg-carte { display: flex; flex-direction: column; max-height: calc(100vh - 110px); }
.msg-entete { border-bottom: 1px solid var(--line); padding-bottom: 8px; margin-bottom: 8px; }
.msg-participants { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 6px; }
.msg-jeton {
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px;
  border-radius: var(--r); background: var(--line-soft); font-size: 12px;
}
.msg-jeton.externe { background: var(--com-pale); color: var(--com); font-weight: 600; }
/* Un rôle ne ressemble pas à une personne : trait plein, pour qu'on voie du
   premier coup d'œil que la conversation suivra l'équipe. */
.msg-jeton.role { background: var(--card); border: 1px solid var(--com); color: var(--com); font-weight: 700; }
/* Présent VIA un rôle : le contour pointillé dit « pas ajouté nommément ». */
.msg-jeton.via-role { background: transparent; border: 1px dashed var(--line); }
.msg-jeton em { font-style: normal; opacity: .8; }
.msg-jeton button { margin-left: 2px; opacity: .5; }
.msg-jeton:hover button { opacity: 1; }

.msg-fil { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 4px 2px; }
.msg-jour {
  align-self: center; font-size: 11px; color: var(--ink-3);
  background: var(--line-soft); padding: 1px 10px; border-radius: var(--r); margin: 6px 0 2px;
}
.msg-bulle {
  max-width: 78%; align-self: flex-start; padding: 6px 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r) var(--r) var(--r) 2px;
}
/* V6.2 — « mes » messages passent de la sarcelle a l'ambre. L'en-tete du bloc
   V5.8 annonce « aucune couleur nouvelle, la messagerie reprend l'ambre de la
   V5.7 » : ces deux lignes disaient le contraire, et l'ecran melangeait les
   deux accents de l'app sans que rien ne distingue leurs roles. */
/* V8.54 — voir le bloc de jetons plus haut : le fond passe au neutre.
   V8.55 — ET LE LISERÉ AMBRE DISPARAÎT.

   La V8.54 avait remplacé le fond crème par un fond neutre PLUS un liseré de
   3 px sur le bord droit, comme si retirer une couleur exigeait d'en poser une
   autre. Non : trois choses disaient déjà qui parle — l'alignement à droite,
   le coin bas-droit rentré, et le fond gris contre le blanc de la bulle reçue.
   Un quatrième marqueur n'ajoutait aucune information, il ajoutait un ornement,
   et un ornement décoratif se voit toujours pour ce qu'il est.

   La bulle reprend donc une bordure de 1 px, uniforme, comme celle qu'on
   reçoit. Seuls le fond et la forme distinguent — c'est assez, et c'est même
   la raison pour laquelle toutes les messageries font ainsi. */
.msg-bulle.moi {
  align-self: flex-end; background: var(--msg-moi); border-color: var(--msg-moi-bord);
  border-radius: var(--r) var(--r) 2px var(--r);
}
.msg-bulle.supprime { color: var(--ink-3); font-size: 12px; }
.msg-tete { display: flex; align-items: baseline; gap: 6px; font-size: 12px; }
.msg-tete time { color: var(--ink-3); font-size: 11px; margin-left: auto; }
.msg-tete em { color: var(--ink-3); font-size: 10px; font-style: normal; }
.msg-corps { white-space: pre-wrap; font-size: 13px; margin-top: 2px; }

.msg-composeur { display: flex; gap: 8px; align-items: flex-end; border-top: 1px solid var(--line); padding-top: 8px; margin-top: 8px; }
.msg-composeur .com-saisie { flex: 1; }
.msg-composeur .btn { flex: none; }

@media (max-width: 900px) {
  .msg-carte { max-height: none; }
  .msg-bulle { max-width: 92%; }
}

/* ---------- V6.1 (RELI-321) : pilotage des instances dédiées ---------- */
/* Dépassement de sièges dans le tableau de flotte. Rouge, mais pas alarmiste :
   rien n'est cassé, rien n'est suspendu — c'est une info commerciale, pas une
   panne. D'où une teinte, sans fond ni bordure. */
.alerte-quota { color:var(--danger); font-weight:600; }

/* Mention « ouvert parce que vous êtes super admin ». Volontairement discrète
   et non cliquable : elle s'adresse à une seule personne sur toute l'instance,
   et elle ne doit surtout pas ressembler à une alerte destinée au client. */
.cc-exempt {
  display:inline-block; margin-top:6px; padding:2px 7px; border-radius:999px;
  font-size:11px; line-height:1.6; color:var(--warn); background:var(--warn-pale); border:1px solid var(--warn);
}

/* ============================================================
   V6.3 (RELI-323) : annuaire d'équipe, profil, vignettes
   ============================================================ */

/* ---------- Vignettes ----------
   L'INITIALE EST LE CAS NORMAL, pas un état dégradé : la plupart des équipes
   ne mettront jamais de photo. Elle est donc dessinée avec le même soin —
   fond de couleur stable par personne, texte blanc, cercle net. La photo,
   quand elle existe, se pose PAR-DESSUS en position absolue : pas de saut de
   mise en page pendant le chargement, et si l'image échoue (droit refusé,
   fichier perdu) il suffit de la retirer du DOM pour retrouver l'initiale.
   `flex:none` + `align-self:center` : les en-têtes de message alignent leurs
   enfants sur la ligne de base, ce qui ferait flotter un cercle. */
.cc-avatar {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  flex: none; align-self: center; overflow: hidden;
  width: 24px; height: 24px; border-radius: 50%;
  color: #fff; font-weight: 700; line-height: 1; letter-spacing: .2px;
  user-select: none; vertical-align: middle;
}
.cc-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---------- Actions d'un message : le ⋯ ----------
   Deux boutons-texte sous chaque message prenaient, dans un panneau latéral,
   plus de place que les messages. Le ⋯ s'efface au repos et n'apparaît qu'au
   survol — mais il reste TOUJOURS dans le DOM et focalisable : au toucher et
   au clavier, le survol n'existe pas, et un bouton qu'on ne peut pas atteindre
   vaut un bouton absent. */
.com-menu-btn {
  margin-left: 6px; padding: 0 4px; border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-size: 15px; line-height: 1; border-radius: 4px;
  opacity: 0; transition: opacity .12s;
}
.com-message:hover .com-menu-btn,
.msg-bulle:hover .com-menu-btn,
.com-menu-btn:focus-visible { opacity: 1; }
.com-menu-btn:hover { background: var(--sunk-2); color: var(--ink); }
@media (hover: none) { .com-menu-btn { opacity: .55; } }

/* Contenu d'un message supprimé, révélé par un owner : lisible mais
   visiblement à part — ce n'est pas du fil, c'est de la modération. */
.com-supprime-corps {
  margin-top: 4px; padding: 4px 8px; border-left: 2px solid var(--line);
  color: var(--ink-2); font-style: normal; white-space: pre-wrap;
}

.msg-mention-ajout { color: var(--com, #9a6a12); font-style: normal; }

/* ---------- Bandeau de l'annuaire ---------- */
.bandeau-equipe {
  margin: 0 0 12px; padding: 8px 12px; border-radius: var(--r, 10px);
  background: var(--sunk); border: 1px solid var(--line);
  font-size: 13px; line-height: 1.5;
}
.bandeau-equipe .aide-modal { font-size: 12px; }

/* ---------- Page « Mon profil » ---------- */
.profil-tete { display: flex; align-items: center; gap: 14px; }
.profil-vignette .cc-avatar { box-shadow: 0 1px 4px rgba(0, 0, 0, .18); } /* V8.57 — ombre laissée en dur : ni `--ombre` ni `--ombre-flot` n'a ce flou, et on ne crée pas un jeton par ombre */
.profil-nom strong { font-size: 17px; display: block; }
.profil-nom .extrait { margin: 2px 0 0; }
.profil-identite { padding-bottom: 14px; }
.profil-cases { display: flex; flex-wrap: wrap; gap: 4px 14px; }
/* Un champ verrouillé reste AFFICHÉ, en lecture, avec sa raison : le masquer
   ferait croire à un bug, le griser sans un mot ferait croire à une panne. */
.profil-verrouille label { color: var(--ink-3); }
.profil-verrouille .aide-modal { display: block; margin: 2px 0 0; font-size: 11px; }

/* ============================================================
   V6.4 (RELI-324) : mentions @, références #, et « Mes tâches »
   ============================================================ */

/* ---------- Pastilles de mention et de référence ----------
   Trois couleurs pour trois natures, et c'est délibéré : une personne, une
   fiche et une collection ne s'ouvrent pas sur la même chose. La personne
   reprend le violet des mentions de commentaires (V5.7) — c'est déjà le code
   couleur du « quelqu'un » dans le produit ; la fiche prend la sarcelle des
   jetons $valeur, celle du « contenu » ; la collection s'en distingue par un
   fond plus soutenu, parce qu'elle est un contenant. */
/* ⚠ V8.61 — `vertical-align: middle` N'EST PAS COSMÉTIQUE ICI, IL CORRIGE UN
   DÉCALAGE DE 2,3 px ENTRE DEUX PASTILLES VOISINES.

   `.cc-ref` est un `inline-flex`, et la ligne de base d'une boîte inline-flex
   est celle de son PREMIER élément flex. Une pastille de fiche commence par du
   texte : sa ligne de base est celle du texte, elle s'aligne sur la phrase.
   Une pastille de personne commence par un AVATAR — une boîte sans texte, donc
   sans ligne de base propre : le navigateur prend alors son bord inférieur, et
   la pastille entière descend de la hauteur qui sépare ce bord de la ligne de
   base du texte. D'où « @Marceline » posé 2,3 px plus bas que « #v8.21 » dans
   la même phrase, sans qu'aucune règle ne parle jamais de ces 2,3 px.

   Aligner sur le MILIEU rend le calcul indépendant du contenu : avatar ou pas,
   les deux pastilles occupent la même bande. On l'applique aussi aux jetons
   `$valeur` et `@mention` de l'éditeur, qui vivent dans les mêmes phrases —
   trois familles de pastilles alignées entre elles valent mieux que deux.

   · `line-height: 1.35` (au lieu de 1,55) : à 0,92 em dans une ligne à 1,6, la
     pastille faisait 23,4 px pour une ligne de 24 — elle remplissait
     l'interligne et les pastilles de deux lignes voisines se frôlaient. 20,6 px
     laissent respirer sans rien rogner du texte. */
.cc-ref {
  display: inline-flex; align-items: center; gap: 3px; vertical-align: middle;
  padding: 0 6px; border-radius: 4px; text-decoration: none;
  font-size: 0.92em; line-height: 1.35; white-space: nowrap; font-weight: 600;
}
.cc-ref:hover { text-decoration: none; filter: brightness(0.96); }
/* V8.57 — les trois natures tenaient à trois fonds en dur, dont deux sarcelles que
   rien ne sépare une fois ramenées au même `--accent-pale`. On garde la distinction
   là où elle survit au changement de thème : la collection porte le TRAIT de
   l'accent, la fiche un trait neutre. */
.cc-ref-personne   { background: var(--prive-pale); color: var(--prive); border: 1px solid var(--line); }
.cc-ref-fiche      { background: var(--accent-pale); color: var(--accent-fonce); border: 1px solid var(--line); }
.cc-ref-collection { background: var(--accent-pale); color: var(--accent-fonce); border: 1px solid var(--accent); }
/* Une transclusion (#fiche.attribut) affiche une VALEUR, pas un nom : elle se
   fond dans la phrase, avec un simple soulignement pointillé pour dire qu'elle
   vient d'ailleurs et qu'elle suivra sa source. */
.cc-ref-valeur {
  background: none; border: 0; padding: 0; font-weight: 600; color: var(--ink);
  border-bottom: 1px dotted var(--ink-3); border-radius: 0;
}
.cc-ref .cc-avatar { margin-right: 1px; }

/* V7.9 (RELI-450) — la pastille d'un BLOC (span[data-ref], par opposition au
   <a> des champs de texte simple) est cliquable, partout et sans modificateur :
   la main du curseur suffit à le dire, et c'est ce que tout lien promet. On
   avait d'abord distingué édition et lecture par un curseur `alias` (« il faut
   Ctrl ») — un raccourci que rien à l'écran ne peut enseigner, donc un lien
   perçu comme cassé. L'indice est en CSS et non en JavaScript : le HTML d'un
   bloc est enregistré tel quel, un attribut posé à chaud partirait en base et
   jusque dans les exports. */
span.cc-ref[data-ref] { cursor: pointer; }

/* Menu d'autocomplétion — même grammaire visuelle que le menu « / » des blocs. */
.cc-mentions-menu {
  position: fixed; z-index: 700; min-width: 240px; max-width: 320px; max-height: 240px;
  overflow: auto; background: var(--card, #fff); border: 1px solid var(--line);
  border-radius: var(--r, 10px); box-shadow: var(--ombre-flot); padding: 4px;
}
.cc-mentions-item {
  display: flex; align-items: center; gap: 7px; width: 100%; padding: 5px 7px;
  border: 0; background: none; border-radius: 6px; cursor: pointer; text-align: left;
}
.cc-mentions-item:hover, .cc-mentions-item.sel { background: var(--sunk-2); }
.cc-mentions-item .ic { width: 18px; text-align: center; color: var(--ink-3); font-weight: 700; }
.cc-mentions-item small { display: block; color: var(--ink-3); font-size: 11px; }

/* ---------- Champ texte à deux modes ----------
   `pre-wrap` : le contenu reste du texte, retours à la ligne compris — on ne
   le convertit pas en HTML pour l'afficher. Le pointeur en « texte » et le
   liseré au survol disent qu'on peut cliquer pour écrire, sans en faire un
   bouton : ce n'en est pas un. */
.cc-texte-lecture {
  white-space: pre-wrap; word-break: break-word; min-height: 2.4em;
  padding: 6px 8px; border: 1px solid transparent; border-radius: var(--r, 8px);
  line-height: 1.6; box-sizing: border-box;
}
/* V6.5 — la hauteur minimale de la CARTE (contexte, vocabulaire, ontologie,
   description courte) est celle du textarea de `.zone-editable` : passer de la
   lecture à l'écriture ne doit pas faire sauter la carte sous le curseur.
   ⚠ Portée à la carte, et à elle seule : `.cc-texte-lecture` sert AUSSI au
   contenu de chaque note (js/vues.js), une ligne compacte de deux lignes. Une
   règle générale à 84px faisait tenir vingt notes sur cinq écrans. */
.carte-texte > .cc-texte-lecture { min-height: 84px; padding: 8px; }
.cc-texte-lecture.editable { cursor: text; }
.cc-texte-lecture.editable:hover { border-color: var(--line); background: var(--sunk); }
.cc-aide-mentions { margin-top: 6px; }

/* ---------- Mes tâches ---------- */
.taches-liste { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.tache-ligne {
  display: flex; align-items: flex-start; gap: 8px; padding: 7px 6px;
  border-top: 1px solid var(--line-soft); border-radius: 6px;
}
.tache-ligne:first-child { border-top: 0; }
.tache-ligne:hover { background: var(--sunk); }
.tache-ligne.porte { opacity: .45; }
/* Une tâche faite reste LISIBLE et reste en place : la faire disparaître au
   clic prive du seul retour qui compte, et empêche de se corriger. */
.tache-ligne.faite .tache-texte { text-decoration: line-through; color: var(--ink-3); }
.tache-poignee { cursor: grab; color: var(--ink-3); user-select: none; padding-top: 2px; }
.tache-poignee:active { cursor: grabbing; }
.tache-corps { flex: 1; min-width: 0; }
.tache-texte { line-height: 1.5; word-break: break-word; }
.tache-meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 2px; font-size: 11px; }
.tache-origine { color: var(--ink-3); }
.tache-ou { color: var(--ink-2); text-decoration: none; }
.tache-ou:hover { text-decoration: underline; }

/* ---------- V6.6 (RELI-331) : Mes tâches — vues, échéances, activité ---------- */

/* Échéance qui approche : orange à J-seuil (2 par défaut, réglable ⚙).
   Le rouge (.retard) existe depuis la V3.2 et couvre « atteinte ou dépassée ». */
.note-echeance.bientot { color: var(--warn); font-weight: 600; }

/* Brique « Tâches » du bandeau : la bulle compte ce qui reste, pas une alerte —
   elle n'a donc pas le rouge des messages non lus. */
.btn-taches { position: relative; }
.btn-taches .topbar-bulle { background: rgba(255, 255, 255, .28); } /* voile blanc sur le bandeau, voir plus haut */

/* Onglets À faire / Fait / Kanban, avec le ⚙ calé à droite sur la même ligne. */
.taches-onglets { margin: 12px 0 10px; align-items: center; }
.taches-onglets-espace { flex: 1; }

/* La grille d'activité : une colonne par semaine, un carré par jour, la teinte
   monte avec le nombre de tâches accomplies. Volontairement sous l'en-tête et
   au-dessus des onglets : c'est un encouragement, pas un tableau de bord. */
.hm-zone { margin: 8px 0 2px; }
.hm-grille {
  display: grid; grid-auto-flow: column;
  grid-template-rows: repeat(7, 10px); grid-auto-columns: 10px;
  gap: 3px; margin-bottom: 5px; max-width: 100%; overflow-x: auto;
}
.hm-case {
  width: 10px; height: 10px; border-radius: 2px;
  background: var(--sunk-2); display: inline-block; flex: none;
}
/* V8.57 — la rampe était quatre sarcelles figées : en thème sombre elle partait du
   clair pour finir au foncé, soit l'échelle À L'ENVERS — le jour le plus vide y
   paraissait le plus rempli. Les deux échelons du milieu n'ont pas de jeton et on
   n'en crée pas : ils se calculent entre le fond enfoncé et l'accent, donc la rampe
   monte toujours dans le sens du thème. */
.hm-case.n1 { background: color-mix(in srgb, var(--accent) 22%, var(--sunk-2)); }
.hm-case.n2 { background: color-mix(in srgb, var(--accent) 55%, var(--sunk-2)); }
.hm-case.n3 { background: var(--accent); }
.hm-case.n4 { background: var(--accent-fonce); }
.hm-legende { display: inline-flex; gap: 3px; align-items: center; font-size: 11px; color: var(--ink-3); }

/* Le kanban : trois colonnes, des cartes qui se prennent à la main.
   « En cours » est un tri personnel ; déposer dans « Fait » coche pour de vrai. */
.taches-kanban { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 8px; }
.kanban-col { background: var(--sunk); border-radius: 8px; padding: 8px; min-height: 140px; }
.kanban-col h4 {
  margin: 2px 4px 8px; font-size: 11px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-2);
}
.kanban-col.drop-into { outline: 2px dashed var(--accent); outline-offset: -2px; background: var(--accent-pale); }
.kanban-vide { margin: 4px; font-size: 12px; color: var(--ink-3); }
.kanban-carte {
  background: var(--card); border: 1px solid var(--line-soft); border-radius: 6px;
  padding: 7px 8px; margin-bottom: 6px; cursor: grab;
}
.kanban-carte:active { cursor: grabbing; }
.kanban-carte.porte { opacity: .45; }
.kanban-carte.faite .tache-texte { text-decoration: line-through; color: var(--ink-3); }
.kanban-carte-tete { display: flex; gap: 7px; align-items: flex-start; }
.kanban-carte .tache-meta { margin-top: 4px; margin-left: 22px; }
@media (max-width: 700px) { .taches-kanban { grid-template-columns: 1fr; } }

/* ============================================================
   V7.5 (RELI-444) — MISE EN FORME LÉGÈRE ET RÉACTIONS
   ============================================================ */

/* -- barre de sélection des messages --
   Elle vit sur <body> et se place en coordonnées ÉCRAN (le miroir de
   texte_riche.js les calcule) : d'où `fixed`, là où la barre des blocs est
   `absolute` dans la racine de son éditeur. Tout le reste — fond, boutons,
   ombre — est hérité de .bloc-barre-fmt : deux barres qui se ressemblent
   doivent se ressembler vraiment. */
.md-barre { position: fixed; z-index: 260; }

/* V8.49 — LA BARRE FIXE, SOUS LE CHAMP.
   Elle ne peut PAS hériter de .bloc-barre-fmt : cette dernière est une bulle
   sombre posée par-dessus le texte, ce qui a un sens quand elle flotte au ras
   d'une sélection et aucun quand elle est posée à demeure sous un champ — un
   rectangle noir permanent en bas d'un composeur pèserait plus lourd que le
   message qu'on écrit. Même jeu de boutons, poids visuel inverse : c'est une
   rangée d'outils, pas une fenêtre. */
.com-outils { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.com-outils .pj-zone { margin-top: 0; }
.md-barre-fixe { display: flex; align-items: center; gap: 1px; }
.md-barre-fixe .fmt-btn { color: var(--ink-3); min-width: 24px; padding: 2px 5px; }
.md-barre-fixe .fmt-btn:hover { background: var(--line-soft); color: var(--ink); }
.md-barre-fixe .fmt-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* -- puces dans un message (V8.49) --
   `white-space: normal` : le conteneur est en `pre-wrap`, et une puce n'a
   aucune raison de conserver l'indentation tapée devant le tiret — celle-ci a
   déjà servi, c'est elle qui a fait la puce. */
.md-puces { margin: 4px 0; padding-left: 20px; white-space: normal; }
.md-puces li { margin: 1px 0; }

/* -- V8.49 : filtrer et replier une liste de réglages (ccListeFiltrable) -- */
.cc-liste-filtre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 6px 0 10px; }
.cc-liste-filtre input[type="search"] {
  border: 1px solid var(--line); border-radius: 6px; padding: 5px 9px; font-size: 13px;
  flex: 1 1 220px; min-width: 180px; max-width: 320px;
}
.cc-liste-filtre select { border: 1px solid var(--line); border-radius: 6px; padding: 5px 7px; font-size: 13px; }
.cc-liste-reste { display: block; margin: 8px auto 0; }

/* -- V8.50 : « ↓ N de plus » au pied d'une pile (ccPlafonnerListe) --
   ⚠ SANS LA SECONDE LIGNE, `hidden` NE CACHE RIEN. Le `display:none` de
     l'attribut vient de la feuille du NAVIGATEUR ; le `display:inline-flex`
     de `.btn` vient de celle de l'auteur, et gagne. Le bouton resterait donc
     visible, et vide, une fois toute la pile dépliée. Cinquième fois de la
     série (badge publié V8.44, déclencheur de note V8.45…) : tout `hidden`
     posé sur un élément déjà stylé demande sa règle. */
.cc-plus-pile { display: block; width: 100%; margin-top: 6px; font-size: 12px; color: var(--ink-2); }
.cc-plus-pile[hidden] { display: none; }
.taches-liste .cc-plus-pile { width: auto; margin: 8px auto 0; }

/* -- rendu des marques, dans un message comme dans un commentaire -- */
.msg-corps code, .com-corps code {
  background: var(--sunk); border: 1px solid var(--line-soft);
  border-radius: 4px; padding: 0 4px; font-size: 12px;
}
.msg-corps s, .com-corps s { color: var(--ink-3); }
.md-lien { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; word-break: break-word; }

/* -- réactions --
   La rangée ne prend AUCUNE place quand elle est vide : pas de marge, pas de
   hauteur. Un fil sans réaction doit être exactement l'écran de la V7.4. */
.react-rangee { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.react-rangee:not(:empty) { margin-top: 5px; }
.react-pastille {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: 11px;
  padding: 1px 7px; font-size: 12px; line-height: 18px;
}
.react-pastille:hover:not(:disabled) { border-color: var(--accent); }
.react-pastille:disabled { cursor: default; opacity: .75; }
/* Celles où je suis : c'est l'information qui décide du sens du prochain clic. */
.react-pastille.moi { background: var(--accent-pale); border-color: var(--accent); }
.react-nb { color: var(--ink-2); font-size: 11px; font-variant-numeric: tabular-nums; }
.react-pastille.moi .react-nb { color: var(--accent); font-weight: 600; }

/* Le bouton d'ajout ne se montre qu'au survol du message — ou dès qu'il y a
   déjà des réactions, sinon la rangée « saute » de largeur sous le curseur.
   Il reste visible en permanence au doigt : sans survol, un bouton caché est
   un bouton absent. */
.react-ajouter {
  border: 1px dashed var(--line); background: none; color: var(--ink-3);
  border-radius: 11px; padding: 1px 7px; font-size: 11px; line-height: 18px;
  cursor: pointer; opacity: 0; transition: opacity .12s;
}
.msg-bulle:hover .react-ajouter, .com-message:hover .react-ajouter,
.react-ajouter:focus-visible, .react-rangee .react-pastille ~ .react-ajouter { opacity: 1; }
.react-ajouter:hover { color: var(--accent); border-color: var(--accent); }
@media (hover: none) { .react-ajouter { opacity: 1; } }

.react-choix { display: flex; flex-wrap: wrap; gap: 3px; max-width: 220px; }
.react-rapide {
  border: 1px solid transparent; background: none; cursor: pointer;
  border-radius: 6px; padding: 3px 5px; font-size: 17px; line-height: 1.1;
}
.react-rapide:hover { background: var(--accent-pale); }
.react-rapide.moi { border-color: var(--accent); background: var(--accent-pale); }
.react-plus { font-size: 14px; color: var(--ink-3); }

/* -- V7.7 (RELI-447) : recherche dans la barre des conversations -- */
.conv-recherche {
  width: 100%; margin-bottom: 6px; padding: 5px 8px; font-size: 12px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--card);
}
.conv-recherche:focus { outline: none; border-color: var(--com); }
/* L'extrait d'un message trouvé : distinct du dernier message, qu'il remplace,
   sinon on croit lire l'aperçu habituel et on ne comprend pas le classement. */
.conv-trouve { color: var(--ink-2); font-style: italic; }
.conv-trouve em { font-style: normal; color: var(--ink-3); font-size: 11px; }
/* -- V7.8 (RELI-448) : pagination du fil et message ciblé -- */
.msg-plus {
  align-self: center; margin: 2px 0 6px; padding: 3px 10px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card);
}
.msg-plus:hover { border-color: var(--com); }
/* Le message atteint depuis une recherche : signalé assez pour qu'on le
   repère d'un coup d'œil, et la marque s'efface d'elle-même — elle dit « c'est
   ici », pas « ce message est spécial ». */
.msg-cible {
  outline: 2px solid var(--com); outline-offset: 2px; border-radius: 8px;
  background: var(--com-pale);
  animation: msg-cible-pulse 1s ease-out 2;
}
/* La marque NE S'EFFACE PLUS toute seule : dans une conversation courte, rien
   ne défile, et un éclair de deux secondes était le SEUL retour visible —
   raté, on ne comprenait pas où l'on avait atterri. Elle reste jusqu'à ce
   qu'on touche le fil (retirée par le script). */
@keyframes msg-cible-pulse {
  0% { outline-color: transparent; }
  50% { outline-color: var(--com); }
  100% { outline-color: var(--com); }
}
.msg-cible::after {
  content: 'résultat de la recherche';
  display: block; margin-top: 3px;
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--com);
}


/* ============================================================
   V8.2 — APERÇU D'UN MODÈLE (lecture seule)
   Volontairement sobre et compact : c'est une CHARPENTE qu'on lit avant de
   poser un modèle — quels titres, quelles sections, quelles cases — pas une
   reproduction fidèle de la fiche qui en sortira.
   ============================================================ */
.modele-apercu { font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.modele-apercu-titre { font-weight: 700; color: var(--ink); margin: 8px 0 2px; }
.modele-apercu-t1 { font-size: 16px; }
.modele-apercu-t2 { font-size: 14.5px; }
.modele-apercu-t3 { font-size: 13.5px; }
.modele-apercu-p { margin: 2px 0; }
.modele-apercu-cit { border-left: 3px solid var(--line); padding-left: 8px; font-style: italic; }
.modele-apercu-callout { background: var(--sunk); border-radius: 8px; padding: 6px 9px; margin: 6px 0; }
.modele-apercu-code {
  background: var(--sunk); border-radius: 6px; padding: 6px 8px; margin: 6px 0;
  font-size: 12px; white-space: pre-wrap; overflow-x: auto;
}
.modele-apercu-hr { border: 0; border-top: 1px solid var(--line); margin: 8px 0; }
.modele-apercu-bloc { margin: 4px 0; }
.modele-liste .bloc-menu-item { width: 100%; }


/* ============================================================
   V8.3 — REDIMENSIONNEMENT DES COLONNES (blocs « tableau » et « tableau lié »)
   Le bloc « tableur » le savait depuis la V4.2 ; ces deux-là non — alors que
   c'est là qu'on met une colonne « Décision » de trois mots à côté d'une
   colonne « Contexte » de trois lignes.
   ============================================================ */

/* `table-layout: fixed` UNIQUEMENT quand une largeur a été posée. Sans cette
   condition, tous les tableaux déjà écrits changeraient d'aspect au simple
   rechargement : en mode automatique les colonnes suivent leur contenu, en
   mode fixe elles se partagent la largeur à parts égales. Un tableau intact
   doit rester intact. */
.bloc-tableau.largeurs { table-layout: fixed; }
/* La table cesse d'être contrainte à 100 % : sinon, quand la somme des
   largeurs demandées dépasse la place disponible, le navigateur les réduit
   TOUTES proportionnellement — on tire une colonne à 280 px, on en obtient
   230, et les voisines rétrécissent sans qu'on ait rien demandé. En largeur
   `max-content` avec un plancher à 100 %, les colonnes valent exactement ce
   qu'on a réglé et l'enveloppe (déjà en `overflow-x: auto`) défile.
   `width: auto` ne suffit PAS : en disposition fixe, Chromium prend alors la
   largeur disponible et rétrécit les colonnes pour l'occuper — mesuré. */
.bloc-tableau.largeurs { width: max-content; min-width: calc(100% - 2px); max-width: none; }
/* Le plancher de 70 px de `.bloc-tableau td` empêcherait de rétrécir une
   colonne en deçà — on le lève seulement là où l'utilisateur a pris la main. */
/* `overflow-wrap` et NON `overflow: hidden` : couper une URL en plein milieu
   sans le dire est pire que la laisser passer à la ligne, et `hidden` rognait
   au passage les 3 px de la poignée du tableau lié, qui vit DANS la cellule. */
.bloc-tableau.largeurs td { min-width: 0; overflow-wrap: anywhere; }

/* Barre de saisie du bloc « tableau » : en SUPERPOSITION dans l'enveloppe,
   parce que les cellules de la première ligne sont éditables et que leur
   contenu est relu tel quel (même raison que les poignées ⠿ depuis la V3.1). */
.bloc-tab-redim {
  position: absolute; width: 7px; z-index: 3; cursor: col-resize;
  border-radius: 3px; background: transparent; transition: background .12s;
}
.bloc-tab-redim:hover, body.cc-redim-en-cours .bloc-tab-redim:hover { background: var(--accent); opacity: .55; }

/* Bloc « tableau lié » : cellules non éditables, la poignée vit dedans. */
.bloc-tableau.tablie td { position: relative; }
.tablie-redim {
  position: absolute; top: 0; right: -3px; width: 7px; height: 100%;
  z-index: 3; cursor: col-resize; border-radius: 3px; background: transparent; transition: background .12s;
}
.tablie-redim:hover { background: var(--accent); opacity: .55; }

/* Pendant le glissement, tout le curseur de la page passe en col-resize et la
   sélection de texte est neutralisée : sans cela, tirer une colonne
   sélectionne le texte des cellules qu'on survole. */
body.cc-redim-en-cours { cursor: col-resize; user-select: none; }
body.cc-redim-en-cours * { cursor: col-resize !important; }

/* La bande verticale « + colonne » est ancrée au bord droit de l'enveloppe
   (`right: 0`). Tant que la table faisait 100 % de large, elle vivait dans la
   gouttière ; en mode fixe la table déborde et défile, et la bande se
   retrouvait POSÉE SUR les cellules — invisible mais cliquable : viser une
   cellule ajoutait une colonne. Elle est désormais recalée par le script,
   contre le bord droit DU TABLEAU, où qu'il soit ; d'où le `right: auto`
   qu'il pose en même temps que le `left`. */
.bloc-tab-plus.col[style*="left"] { right: auto; }


/* V8.4 — « des modifications ont eu lieu ». Discret et en bas : un bandeau en
   haut aurait poussé toute la page vers le bas, ce qui est exactement le
   déplacement qu'on cherche à éviter pendant une saisie. */
/* Deux bandeaux peuvent coexister — « la collection a changé » et « une
   nouvelle version est en ligne » — et c'est même le moment le plus probable :
   un déploiement. Superposés au même pixel, le second cachait entièrement le
   premier, bouton compris. On les empile. */
.bandeau-maj {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 900;
  display: flex; align-items: center; gap: 10px;
  background: var(--card, #fff); border: 1px solid var(--line);
  border-radius: 999px; padding: 7px 10px 7px 16px; font-size: 13px;
  box-shadow: var(--ombre-flot);
}

/* ============================================================
   V8.4 — VUE GALERIE et ORGANIGRAMME
   Des cartes, pas des colonnes : contrairement au kanban, la position d'une
   carte ne porte aucune donnée — on ne déplace personne d'un service à
   l'autre en la faisant glisser. D'où l'absence totale d'affordance de
   glissement ici.
   ============================================================ */
.galerie {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}
.galerie-carte {
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  background: var(--card, #fff); transition: box-shadow .12s, transform .12s;
}
.galerie-carte:hover { box-shadow: 0 6px 18px rgba(24, 43, 58, .12); transform: translateY(-1px); }
.galerie-photo { aspect-ratio: 4 / 3; background: var(--line-soft); overflow: hidden; }
.galerie-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.galerie-photo-vide {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 34px; font-weight: 700; /* V8.57 — initiale posée sur la couleur stable de la personne : blanc dans les deux thèmes. */
}
.galerie-corps { padding: 8px 10px 10px; }
.galerie-titre { font-weight: 600; font-size: 14px; line-height: 1.25; overflow-wrap: anywhere; } /* V8.8 */
/* V8.8 — un email interminable pliait la grille au lieu de se plier lui-même */
.galerie-champ { font-size: 12.5px; color: var(--ink-2); margin-top: 3px; overflow-wrap: anywhere; }
.galerie-etiquette { color: var(--ink-3); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }

/* ============================================================
   V8.8 — L'ORGANIGRAMME EST UN ARBRE, PAS UNE GRILLE.
   La V8.4 indentait les rattachés de 14 px sous une carte-photo de 180 px :
   l'œil ne voyait qu'une grille (retour de test : « les fiches sont restées
   côte à côte »). Le responsable est maintenant CENTRÉ au-dessus de ses
   rattachés, et des TRAITS les relient : une tige descend de la carte
   (.orga-tige), une barre court au-dessus du rang (::before/::after des
   enfants — moitié gauche, moitié droite, supprimées aux extrémités), et la
   verticale de chaque enfant est le border-left du ::after, posé au centre.
   Défilement horizontal assumé : un arbre large se parcourt, il ne
   s'écrase pas. */
.orga { overflow-x: auto; padding: 8px 0 12px; }
.orga-racines { display: flex; gap: 34px; align-items: flex-start; width: max-content; margin: 0 auto; }
.orga-noeud { display: flex; flex-direction: column; align-items: center; position: relative; }
.orga-tige { width: 2px; height: 18px; background: var(--line); }
.orga-fils { display: flex; align-items: flex-start; }
.orga-fils > .orga-noeud { padding: 18px 7px 0; }
.orga-fils > .orga-noeud::before,
.orga-fils > .orga-noeud::after { content: ''; position: absolute; top: 0; width: 50%; height: 18px; border-top: 2px solid var(--line); }
.orga-fils > .orga-noeud::before { right: 50%; }
.orga-fils > .orga-noeud::after { left: 50%; border-left: 2px solid var(--line); margin-left: -1px; }
.orga-fils > .orga-noeud:first-child::before { border-top: 0; }
.orga-fils > .orga-noeud:last-child::after { border-top: 0; }

/* La carte compacte : avatar rond + nom + champs — dense, lisible à 40 personnes. */
.orga-carte { display: flex; gap: 8px; align-items: center; text-decoration: none; color: inherit;
  border: 1px solid var(--line); border-radius: 10px; background: var(--card, #fff);
  padding: 7px 10px; width: 190px; box-sizing: border-box; transition: box-shadow .12s, transform .12s; }
.orga-carte:hover { box-shadow: 0 4px 14px rgba(24, 43, 58, .12); transform: translateY(-1px); }
.orga-avatar { width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex: none;
  display: flex; align-items: center; justify-content: center; }
.orga-avatar img { width: 100%; height: 100%; object-fit: cover; }
.orga-avatar-vide { color: #fff; font-size: 17px; font-weight: 700; } /* même raison que .galerie-photo-vide */
.orga-corps { display: flex; flex-direction: column; min-width: 0; }
.orga-nom { font-weight: 600; font-size: 13px; line-height: 1.25; overflow-wrap: anywhere; }
.orga-champ { font-size: 11.5px; color: var(--ink-3); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; }

/* V8.12 — annuler / rétablir de l'éditeur de blocs : discret, trouvable */
.blocs-editeur { position: relative; }
.blocs-hist { position: absolute; top: 2px; right: 2px; display: flex; gap: 2px; opacity: .3; transition: opacity .15s; }
.blocs-editeur:hover .blocs-hist, .blocs-hist:focus-within { opacity: 1; }
.blocs-hist-btn { border: 1px solid var(--line); background: var(--card, #fff); border-radius: 6px;
  width: 24px; height: 22px; font-size: 12px; line-height: 1; cursor: pointer; color: var(--ink-2); }
.blocs-hist-btn:hover { color: var(--ink, #182b3a); border-color: var(--accent, #0f7583); }

/* V8.11b — le bouton des vues : le nom de la vue active, accentué discrètement */
.onglet.vue-active { color: var(--accent-fonce); font-weight: 600; }

/* V8.11 (RELI-311) — ordre personnalisé : poignée de ligne et repères de dépôt */
.td-poignee, .th-poignee { width: 28px; text-align: center; padding: 0 2px; color: var(--ink-3); }
.poignee-ligne { cursor: grab; user-select: none; font-size: 13px; opacity: .55; }
tr:hover .poignee-ligne { opacity: 1; }
.ligne-en-deplacement { opacity: .45; }
.ligne-drop-avant td { border-top: 2px solid var(--accent, #0f7583); }
.ligne-drop-apres td { border-bottom: 2px solid var(--accent, #0f7583); }

.bandeau-maj-haut { bottom: 70px; }
.bandeau-maj-bas { bottom: 18px; }

/* ============================================================
   V8.6 — VUE GRAPHIQUE
   Le tracé lui-même est en SVG (js/graphique_svg.js) et n'a besoin d'aucun
   style : tout y est dessiné. Ce qui suit n'habille que ce qu'il y a AUTOUR —
   les onglets de graphes, la carte qui les contient, et la ligne de réglage
   d'une série.
   ============================================================ */
.onglets-graphes { margin-bottom: 6px; }
.onglets-graphes .onglet { font-size: 12.5px; padding: 4px 12px; }
.carte-graphique { padding: 14px 16px 12px; color: var(--ink); }
.cc-graphe { max-width: 100%; }
.graph-series { display: flex; flex-direction: column; gap: 5px; margin: 2px 0 6px; }
.graph-serie-ligne { display: flex; align-items: center; gap: 5px; }
.graph-serie-ligne select { max-width: 130px; }
.popover-graphe label { display: block; margin-top: 8px; font-size: 11.5px; color: var(--ink-3); }
.popover-graphe label.case { display: flex; align-items: center; gap: 5px; margin-top: 2px; font-size: 12.5px; color: var(--ink); }

/* ============================================================
   V8.6 — VERROU DE COLONNE
   Le cadenas doit se voir sans être criard : c'est une information d'état, pas
   une alerte. Assez présent pour qu'on le remarque AVANT de cliquer dans une
   cellule, assez discret pour qu'une colonne gelée reste lisible.
   ============================================================ */
.pastille-verrou {
  border: 0; background: none; padding: 0 0 0 4px; cursor: pointer;
  color: var(--ink-3); vertical-align: middle; line-height: 1;
}
.pastille-verrou:hover { color: var(--ink); }
.pastille-verrou svg { display: inline-block; vertical-align: -1px; }
/* La cellule d'une colonne gelée ne doit pas donner l'impression qu'on peut y
   écrire : ni curseur texte, ni surbrillance au survol. */
th:has(.pastille-verrou) { background: var(--line-soft); }
td.cellule-verrouillee { cursor: default; background: var(--line-soft); }
td.cellule-verrouillee:hover { background: var(--line-soft); }
.champ-ligne.champ-verrouille label { color: var(--ink-3); }
.champ-ligne.champ-verrouille label .pastille-verrou { padding-left: 3px; }
.bloc-verrou { border-left: 3px solid var(--line); }

/* ============================================================
   V8.13.3 (lot A de la V8.14) — L'INDICATEUR DE GLOSSAIRE.
   Discret par construction : il vit SOUS la carte, en 11-12 px, et disparaît
   totalement quand le champ est vide. Un compteur qui crie à chaque frappe
   serait un reproche permanent ; celui-ci ne se colore qu'en cas d'entrée
   réellement ignorée par la recherche.
   ============================================================ */
.cc-analyse { font-size: 11px; color: var(--ink-3); margin: 6px 0 0; display: flex; gap: 8px; align-items: baseline; }
.cc-analyse.ton-ok .cc-analyse-resume { color: var(--ok); }
.cc-analyse.ton-info .cc-analyse-resume { color: var(--ink-2); }
.cc-analyse.ton-avert .cc-analyse-resume { color: var(--st-ouvert); }
.cc-analyse-resume { font-variant-numeric: tabular-nums; }
.cc-analyse-bascule { background: none; border: 0; padding: 0; font: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; }
.cc-analyse-bascule:hover { color: var(--accent-fonce); }
.cc-analyse-detail { list-style: none; margin: 4px 0 0; padding: 0; font-size: 11px; }
.cc-analyse-detail li { display: flex; gap: 6px; align-items: baseline; padding: 3px 0; border-top: 1px solid var(--line-soft); }
.cc-analyse-detail li.ton-avert { color: var(--st-ouvert); }
.cc-analyse-detail li.ton-info { color: var(--ink-2); }
.cc-analyse-num { font-family: var(--mono); font-size: 10px; color: var(--ink-3); flex: none; }
.cc-analyse-texte { font-family: var(--mono); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 40%; flex: none; }
.cc-analyse-note { color: var(--ink-3); }

/* ============================================================
   V8.15.2 — LE VOCABULAIRE EN TABLEAU.
   Il reprend `.tableau` et `.cellule-editable` du tableau des collections :
   même apparence, même geste, rien de nouveau à apprendre. Les lignes héritées
   sont grisées et non cliquables — on voit d'un coup d'œil ce qui appartient à
   cette collection et ce qui vient d'ailleurs.
   ============================================================ */
.carte-glossaire .cc-gloss-entete { display: flex; gap: 10px; align-items: center; justify-content: space-between; margin: 2px 0 8px; }
.cc-gloss-filtre { flex: 1; min-width: 0; font-size: 12px; padding: 4px 8px; border: 1px solid var(--line); border-radius: var(--r); }
.cc-gloss-compte { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; }

.cc-gloss-table td { vertical-align: top; font-size: 13px; }
.cc-gloss-table .cellule-longue { white-space: pre-wrap; }
.cc-gloss-table textarea, .cc-gloss-table input, .cc-gloss-table select {
  width: 100%; font: inherit; font-size: 13px; border: 1px solid var(--accent);
  border-radius: var(--r); padding: 4px 6px; background: var(--input-bg); }
.cc-gloss-tr-herite td { background: var(--line-soft); color: var(--ink-2); }
.cc-gloss-tr-neuf td { background: transparent; border-top: 1px dashed var(--line); }
.cc-gloss-neuf-champ { width: 100%; font: inherit; font-size: 13px; padding: 4px 6px;
  border: 1px dashed var(--line); border-radius: var(--r); background: transparent; }
.cc-gloss-neuf-champ:focus { border-style: solid; border-color: var(--accent); background: var(--input-bg); outline: none; }
.cc-gloss-jeton { display: inline-block; background: var(--accent-pale); color: var(--accent-fonce);
  border-radius: 10px; padding: 0 7px; margin: 0 3px 3px 0; font-size: 11.5px; }
.cc-gloss-vide { color: var(--ink-3); }
.cc-gloss-badge { display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 10px;
  border: 1px solid var(--line); color: var(--ink-2); white-space: nowrap; margin: 0 3px 3px 0; }
.cc-gloss-badge.herite { background: var(--line-soft); }
.cc-gloss-badge.redefini { background: var(--accent-pale); border-color: var(--accent-pale); color: var(--accent-fonce); }
.cc-gloss-badge.afinir { color: var(--st-ouvert); border-color: var(--st-ouvert); }
.cc-gloss-td-actions { white-space: nowrap; text-align: right; }
.cc-gloss-th-actions { width: 90px; }
.cc-gloss-menu { display: grid; gap: 2px; }
.cc-gloss-menu .btn-lien { text-align: left; }
.cc-gloss-menu .aide-modal { margin-bottom: 6px; }
.cc-gloss-ligne { display: flex; gap: 8px; align-items: baseline; padding: 5px 0; border-top: 1px solid var(--line-soft); font-size: 13px; }
.cc-gloss-terme { font-weight: 600; flex: none; min-width: 110px; }
.cc-gloss-def { flex: 1; min-width: 0; }
.cc-gloss-ed { flex: none; font-size: 11px; }
.cc-gloss-ajout { display: block; margin-top: 8px; font-size: 12px; }
.cc-gloss-editeur { border-left: 3px solid var(--accent-pale); padding: 8px 0 8px 10px; margin: 2px 0 6px; display: grid; gap: 6px; }
.cc-gloss-champ { display: grid; gap: 2px; font-size: 11px; color: var(--ink-2); }
.cc-gloss-champ input, .cc-gloss-champ textarea, .cc-gloss-champ select {
  font: inherit; font-size: 13px; color: var(--ink); padding: 4px 6px;
  border: 1px solid var(--line); border-radius: var(--r); width: 100%; background: var(--card); }
.cc-gloss-actions { display: flex; gap: 6px; }
.cc-gloss-texte { width: 100%; min-height: 180px; font-family: var(--mono); font-size: 12px;
  border: 1px solid var(--line); border-radius: var(--r); padding: 8px; resize: vertical; }

/* V8.14.2 (lot F) — l'écran Glossaire de l'organisation. */
.cc-gouv-section { margin-bottom: 14px; }
.cc-gouv-ligne { display: flex; gap: 8px; align-items: baseline; padding: 4px 0; border-top: 1px solid var(--line-soft); font-size: 13px; flex-wrap: wrap; }
.cc-gouv-ligne:first-child { border-top: 0; }
.cc-gouv-txt { color: var(--ink-2); font-size: 12px; }
.cc-gouv-ou { font-size: 11px; color: var(--ink-3); background: var(--line-soft); padding: 1px 6px; border-radius: 10px; white-space: nowrap; }
.cc-gouv-conflit { border-left: 3px solid var(--st-ouvert); padding: 6px 0 6px 10px; margin-bottom: 10px; }
.cc-gouv-tete { display: flex; gap: 10px; align-items: baseline; }
.cc-gouv-def { display: flex; gap: 8px; align-items: baseline; padding: 3px 0; font-size: 13px; flex-wrap: wrap; }

/* V8.14.3 (lot E) — la carte Relations : le calculé au-dessus du déclaré. */
.cc-rel-titre { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); margin: 0 0 4px; }
.cc-rel-titre .aide-modal { display: inline; text-transform: none; letter-spacing: 0; }
.cc-rel-ligne { display: flex; gap: 8px; align-items: baseline; padding: 3px 0; font-size: 13px; flex-wrap: wrap; }
.cc-rel-ligne.calcule { color: var(--ink-2); }
.cc-rel-sujet, .cc-rel-objet { font-weight: 600; }
.cc-rel-ligne.calcule .cc-rel-sujet, .cc-rel-ligne.calcule .cc-rel-objet { font-weight: 500; }
.cc-rel-pred { color: var(--accent-fonce); background: var(--accent-pale); padding: 1px 7px; border-radius: 10px; font-size: 12px; }
.cc-rel-pred.libre { color: var(--st-ouvert); background: transparent; border: 1px dashed var(--st-ouvert); }
.cc-rel-inverse { font-size: 11px; color: var(--ink-3); }
.cc-rel-comm { font-size: 12px; color: var(--ink-2); margin: 0 0 6px 14px; border-left: 2px solid var(--line-soft); padding-left: 8px; white-space: pre-wrap; }
.cc-rel-saisie { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; }
.cc-rel-saisie input { font: inherit; font-size: 13px; padding: 4px 6px; border: 1px solid var(--line); border-radius: var(--r); flex: 1; min-width: 90px; }

/* ============================================================
   V8.14.5 — LE BANDEAU DE MISE À JOUR, LISIBLE SUR TÉLÉPHONE.
   Il était dessiné comme une pastille centrée (`left:50%` + `translateX`),
   ce qui tient sur un écran large et devient illisible sur un téléphone : la
   phrase se casse en colonne de trois mots, et le ✕ finit collé au bouton
   principal, trop petit pour être visé au pouce. Sur mobile il devient donc une
   BARRE PLEINE LARGEUR, en bas, texte sur sa ligne et deux boutons de taille
   normale — et « Plus tard » est écrit en toutes lettres : un ✕ de dix pixels
   n'est pas une sortie, c'est une devinette.
   ============================================================ */
.bandeau-maj-texte { flex: 1; min-width: 0; }
.bandeau-maj-actions { display: flex; gap: 8px; align-items: center; flex: none; }
.bandeau-maj-fermer { background: transparent; }

@media (max-width: 640px) {
  .bandeau-maj, .bandeau-maj-haut, .bandeau-maj-bas {
    left: 8px; right: 8px; transform: none; bottom: 8px;
    /* iOS : ne pas se glisser sous la barre de gestes. */
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    flex-direction: column; align-items: stretch; gap: 8px;
    border-radius: 12px; padding: 12px 14px; font-size: 14px; line-height: 1.35;
  }
  .bandeau-maj-actions { justify-content: flex-end; }
  /* 40 px : la cible minimale qu'un pouce vise sans réfléchir. */
  .bandeau-maj-actions .btn { min-height: 40px; padding: 0 16px; font-size: 14px; }
}

/* V8.15 — le panneau de relations déclarées, sous le graphe. */
.cc-rel-panneau { margin-top: 14px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.cc-rel-ligne.a-rattacher { opacity: .8; }
.cc-rel-select { font: inherit; font-size: 13px; padding: 4px 6px; border: 1px solid var(--line); border-radius: var(--r); }
.cc-gloss-neuf, .cc-gloss-complete { border-left-color: var(--accent); }

/* V8.15.4 — la description textuelle du graphe, repliée par défaut. */
.graphe-texte { margin-top: 8px; }
.graphe-texte-pre { font-family: var(--mono); font-size: 12px; color: var(--ink-2); white-space: pre-wrap;
  background: var(--line-soft); border-radius: var(--r); padding: 10px; margin: 0 0 8px; max-height: 320px; overflow: auto; }
.graphe-ecremage { font-size: 12px; color: var(--ink-2); margin: 0 0 8px; }
.graphe-ecremage .aide-modal { display: inline; }

/* -- V8.20 : bloc qui ne sort pas (exports / pages publiées) -- */
/* Un liseré discret plutôt qu'un bandeau : le bloc reste parfaitement lisible
   et modifiable — on signale une DESTINATION, on ne dégrade pas le contenu. */
.bloc-ligne.bloc-masque { position: relative; }
.bloc-ligne.bloc-masque::before {
  content: ''; position: absolute; left: -10px; top: 2px; bottom: 2px; width: 3px;
  border-radius: 2px; background: repeating-linear-gradient(
    180deg, var(--ink-3, #8795a0) 0 4px, transparent 4px 8px); opacity: .55;
}

/* -- V8.21 : la description courte ne saute plus au clic --
   Le textarea d'édition et la div de lecture doivent partager EXACTEMENT les
   mêmes métriques : sans cela, à contenu égal, les lignes se coupent
   différemment et la boîte change de hauteur au moment précis où l'on clique
   pour corriger un mot. La hauteur, elle, est ajustée au contenu en JS. */
.carte-texte > textarea { font-size: 14px; line-height: 1.6; padding: 8px; overflow-y: hidden; }

/* -- V8.21 : le sélecteur d'emoji ne saute plus pendant la recherche --
   La grille était en `max-height` : dès que les résultats devenaient assez peu
   nombreux (typiquement au 3e caractère), elle rétrécissait de ~180 px, le
   popover se repositionnait et changeait de branche — d'où le saut en haut à
   gauche. Une hauteur FIXE réserve la place ; `scrollbar-gutter` fige aussi la
   largeur, sans quoi la disparition de l'ascenseur élargissait les colonnes. */
.emoji-grille { height: 240px; max-height: none; scrollbar-gutter: stable; }

/* -- V8.21 : « cartes par ligne » veut dire cartes par ligne --
   `repeat(auto-fit, …)` laissait la LARGEUR décider du nombre de colonnes : le
   réglage n'agissait qu'indirectement, et 5 et 6 produisaient exactement le
   même CSS. On demande le nombre exact ; l'empilement mobile passe par une
   media query, qu'un style en ligne ne peut pas porter. */
.bloc-cartes-grille { display: grid; gap: 12px;
  grid-template-columns: repeat(var(--cartes-par-ligne, 3), minmax(0, 1fr)); }
@media (max-width: 720px) { .bloc-cartes-grille { grid-template-columns: 1fr; } }

/* -- V8.21 : la note en étoiles, d'un seul geste (façon Google Maps) --
   Cinq boutons côte à côte n'ont jamais ressemblé à une note : on lisait cinq
   commandes, pas un curseur. Ici une seule rangée, survolée d'un bout à
   l'autre, où l'on clique la énième étoile. Le survol montre le résultat AVANT
   le clic : personne ne doit deviner ce qu'il s'apprête à voter. */
.avis-etoiles { display: inline-flex; gap: 2px; cursor: pointer; user-select: none; line-height: 1; }
.avis-etoiles .et { font-size: 22px; color: var(--line); transition: color .08s, transform .08s; }
.avis-etoiles .et.pleine { color: var(--warn); } /* V8.57 — l'or de l'étoile n'avait pas de jeton : on prend l'ambre du produit plutôt qu'un or qui reste fluo en sombre. */
.avis-etoiles:hover .et { transform: scale(1.06); }
.avis-etoiles.lecture { cursor: default; }
.avis-etoiles.lecture:hover .et { transform: none; }
.avis-note-chiffre { font-weight: 600; margin-left: 8px; }
.avis-note-nb { color: var(--ink-3, #8795a0); font-size: 12px; margin-left: 4px; }
/* Les autres modes gardent des boutons, mais lisibles et alignés. */
.avis-choix .avis-btn { font-size: 17px; line-height: 1; padding: 4px 9px; }
.avis-emojis-aide { font-size: 12px; color: var(--ink-3, #8795a0); margin-top: 4px; }

/* -- V8.22 : pièces jointes dans les conversations -- */
.pj-zone { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.pj-liste { display: inline-flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.pj-jeton { display: inline-flex; align-items: center; gap: 4px; background: var(--sunk);
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 9px; font-size: 12px;
  text-decoration: none; color: inherit; }
.pj-vignette { max-height: 120px; max-width: 200px; border-radius: 8px; display: block; }

/* -- V8.22 : le guichet -- */
.support-fil { display: grid; gap: 8px; margin: 10px 0; }
.support-msg { border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; background: var(--card, #fff); }
.support-msg-externe { border-left: 3px solid var(--accent); background: var(--sunk); }
.support-msg-tete { font-size: 12px; color: var(--ink-3, #8795a0); margin-bottom: 3px; }
.support-msg-corps { white-space: pre-wrap; }
.support-ligne { padding: 6px 4px; border-bottom: 1px solid var(--line); }
.pastille-nb { background: var(--accent-plein); color: var(--sur-accent); border-radius: 999px; /* blanc SUR l'accent : il reste foncé en sombre */
  font-size: 11px; padding: 1px 7px; margin-left: 6px; }

/* ---------- V8.23 : choix cherchable (longue liste) ---------- */
/* Une liste déroulante native est parfaite à vingt entrées et inutilisable à
   trois cents. Ici on tape, ça filtre. */
.choix-cherchable { position: relative; display: inline-block; min-width: 190px; }
.choix-cherchable-champ { width: 100%; border: 1px solid var(--line); border-radius: 4px; padding: 5px 7px; font-size: 13px; }
.choix-cherchable-menu {
  position: absolute; z-index: 120; top: calc(100% + 2px); left: 0; min-width: 100%; max-width: 340px;
  max-height: 240px; overflow-y: auto; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--ombre-flot); padding: 4px;
}
.choix-cherchable-item {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline; width: 100%;
  text-align: left; border: 0; background: transparent; cursor: pointer;
  padding: 5px 7px; border-radius: 4px; font-size: 13px; color: var(--ink);
}
.choix-cherchable-item:hover, .choix-cherchable-item.survol { background: var(--accent-pale); }
.choix-cherchable-detail { font-size: 11px; color: var(--ink-3); white-space: nowrap; }
.choix-cherchable-menu .vide-etat { font-size: 12px; margin: 4px 6px; }

/* ---------- V8.24 : l'interrupteur ---------- */
/* Il remplace la case à cocher partout. Trois exigences : se voir même éteint
   (une valeur jamais renseignée est « éteint », pas « rien »), basculer sous le
   doigt sans attendre le réseau, et rester utilisable au clavier. */
.inter { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; vertical-align: middle; }
.inter-case { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.inter-piste {
  position: relative; flex: none; width: 34px; height: 19px; border-radius: 19px;
  background: var(--line); border: 1px solid var(--line-soft);
  transition: background .14s;
}
.inter-pastille {
  position: absolute; top: 1px; left: 1px; width: 15px; height: 15px; border-radius: 50%;
  background: #fff; box-shadow: var(--ombre); transition: transform .14s; /* V8.57 — le blanc de la pastille est posé SUR la piste, pas sur la page : il reste blanc dans les deux thèmes. */
}
.inter-on .inter-piste { background: var(--accent); }
.inter-on .inter-pastille { transform: translateX(15px); }
.inter-case:focus-visible + .inter-piste { outline: 2px solid var(--accent); outline-offset: 2px; }
.inter-libelle { font-size: 13px; color: var(--ink); }
.inter-fige { opacity: .5; cursor: default; }
/* Pendant l'aller-retour serveur : discret, jamais bloquant — on a déjà
   basculé, on ne fait qu'annoncer que ce n'est pas encore confirmé. */
.inter-attente .inter-piste { opacity: .65; }
.inter-compact .inter-piste { width: 28px; height: 16px; }
.inter-compact .inter-pastille { width: 12px; height: 12px; }
.inter-compact.inter-on .inter-pastille { transform: translateX(12px); }
/* Dans une cellule de tableau : centré, sans marge parasite. */
td .inter { justify-content: flex-start; }

/* ---------- V8.24 : TOUTES les cases à cocher deviennent des interrupteurs ----------
   Il y a 97 cases à cocher dans le produit. Les réécrire une par une en
   composant aurait voulu dire 97 occasions de casser un comportement qui
   marche, pour un gain qui est d'abord VISUEL : une case native est petite,
   son état se lit mal d'un coup d'œil, et sur mobile on la vise mal.

   On style donc la case NATIVE. L'élément reste un <input type="checkbox"> :
   `.checked`, `change`, le clavier, les libellés associés, les tests — rien ne
   change côté code. Seul le dessin change, partout à la fois, y compris dans
   le code écrit demain.

   ⚠ `.inter-case` est EXCLUE : c'est la case cachée de ccInterrupteur, qui
   dessine déjà sa propre piste (elle sert aux cas où il faut en plus basculer
   avant la réponse du serveur et revenir en arrière si elle refuse). */
input[type="checkbox"]:not(.inter-case) {
  appearance: none; -webkit-appearance: none;
  flex: none; position: relative; width: 32px; height: 18px; margin: 0 2px 0 0;
  border-radius: 18px; background: var(--line); border: 1px solid var(--line-soft);
  cursor: pointer; transition: background .14s; vertical-align: middle;
}
input[type="checkbox"]:not(.inter-case)::after {
  content: ""; position: absolute; top: 1px; left: 1px; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; box-shadow: var(--ombre);
  transition: transform .14s;
}
input[type="checkbox"]:not(.inter-case):checked { background: var(--accent); }
input[type="checkbox"]:not(.inter-case):checked::after { transform: translateX(14px); }
input[type="checkbox"]:not(.inter-case):disabled { opacity: .45; cursor: default; }
input[type="checkbox"]:not(.inter-case):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Un interrupteur INDÉTERMINÉ (cocher-tout partiel) : pastille au milieu.
   Aucune case tri-état n'existe aujourd'hui dans le produit ; la règle est là
   pour que la première qui apparaîtra soit dessinée juste du premier coup,
   plutôt qu'en case native au milieu d'interrupteurs. */
input[type="checkbox"]:not(.inter-case):indeterminate { background: var(--ink-3); }
input[type="checkbox"]:not(.inter-case):indeterminate::after { transform: translateX(7px); }
/* Les libellés qui portaient une case sur la même ligne restent alignés. */
label.case, .case { align-items: center; }

/* V8.24 — le champ d'une valeur à copier : monospace, sélectionnable, jamais
   tronqué en silence. */
.copier-zone {
  width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; padding: 7px 8px; border: 1px solid var(--line); border-radius: 4px;
  background: var(--sunk); color: var(--ink); word-break: break-all;
}

/* V8.24 — sélection AU BLOC (plusieurs blocs à la fois). Les navigateurs
   refusent qu'une sélection native traverse deux contenteditable distincts :
   dès que le geste dépasse le bloc de départ, on surligne les blocs entiers.
   Le surlignage doit se lire comme une sélection, pas comme un état de bloc :
   même teinte que la sélection du système, sur toute la largeur. */
.bloc-ligne.bloc-selectionne { background: var(--accent-pale); } /* V8.57 — l'accent à 14 % ne valait que sur du blanc ; le jeton pâle donne la même teinte et suit le thème. */
.blocs-selection-active .bloc-ligne.bloc-selectionne ::selection { background: transparent; }
.blocs-selection-active { caret-color: transparent; }

/* V8.24 — palette de couleur du TEXTE dans le tableur (distincte du fond). */
.tableur-palette { display: flex; flex-wrap: wrap; gap: 5px; max-width: 190px; }
.tableur-palette .bloc-pastille { width: 20px; height: 20px; border-radius: 4px; border: 1px solid var(--line); cursor: pointer; } /* V8.57 — le contour est du châssis ; les couleurs de la palette, elles, sont une donnée et restent en dur. */
.bloc-tableur td a { color: inherit; text-decoration: underline; }
/* ⚠ LA CELLULE EST UN <input>, ET UN <input> N'HÉRITE PAS. Le style est posé
   sur le <td> (c'est lui qui porte la mise en forme de la cellule) ; sans ces
   trois lignes, l'italique et le souligné étaient bien enregistrés et
   parfaitement invisibles — le pire des deux mondes. `text-decoration` ne
   s'hérite jamais d'office : on la reprend explicitement. */
.bloc-tableur td input {
  font: inherit; color: inherit; font-style: inherit; font-weight: inherit;
  text-decoration: inherit; background: transparent;
}

/* V8.25 — cellule de tableur commentée : une pastille dans le coin haut droit,
   comme la marque de commentaire d'un tableur du commerce. Elle ne recouvre pas
   la valeur et ne prend pas le clic de saisie — seul le coin ouvre le fil. */
td.td-commentee { position: relative; }
td.td-commentee::after {
  content: ""; position: absolute; top: 0; right: 0;
  /* ⚠ LA TAILLE DU TRIANGLE DOIT SUIVRE LA ZONE CLIQUABLE (14 px, posée en JS).
     Dessiné à 8 px, il promettait une cible deux fois plus petite que la vraie :
     on cliquait « à côté » du triangle et le fil s'ouvrait quand même. */
  border-width: 0 14px 14px 0; border-style: solid;
  border-color: transparent var(--com) transparent transparent;
  pointer-events: none;
}
/* ⚠ PAS DE GROSSISSEMENT AU SURVOL. Un triangle de 18 px sous un curseur qui
   est, par définition, en survol au moment du clic promettait de nouveau une
   cible plus grande que la zone réelle (14 px) : on cliquait sur le triangle
   sans rien ouvrir. La pastille garde donc sa taille ; c'est la couleur qui
   répond au survol. */
td.td-commentee:hover::after { filter: brightness(1.15); }

/* ============================================================
   V8.26 — POINT 1 : UNE ACTION QU'ON NE PEUT PAS FAIRE
   ------------------------------------------------------------
   L'enveloppe porte l'infobulle (un <button disabled> ne reçoit pas les
   événements de souris sous Chrome : son `title` ne s'afficherait jamais) et
   le curseur « interdit ». Le bouton reste visible, lisible et manifestement
   inopérant : le retirer aurait fait croire à un bug là où il y a une règle.
   ============================================================ */
.action-impossible { display: inline-flex; cursor: not-allowed; }
.action-impossible > .btn:disabled {
  opacity: .45; pointer-events: none;
  /* Le rouge du danger s'éteint aussi : un bouton désactivé qui reste alarmant
     attire l'œil pour rien. */
  filter: grayscale(.6);
}

/* ============================================================
   V8.26 — POINT 5 : BROUILLON LOCAL DE SAISIE
   ------------------------------------------------------------
   Un brouillon qui ressemble à une valeur enregistrée est PIRE que le texte
   perdu : on croit son travail à l'abri. D'où un liseré à gauche de la cellule
   (visible sans être criard, y compris en lecture rapide d'une colonne) et une
   pastille ✎ qui porte l'explication et l'abandon.
   ============================================================ */
:root {
  /* Ocre : ni l'accent du produit (turquoise), ni le privé (violet), ni le
     commentaire (ambre profond), ni le danger (rouge brique). « En cours, pas
     encore posé » — la teinte d'une note au crayon. */
  --brouillon: #b8863a;
  --brouillon-fond: rgba(184, 134, 58, .07);
}
td.cellule-brouillon, td.cellule-brouillon-conflit {
  box-shadow: inset 3px 0 0 var(--brouillon, #b8863a);
  background: var(--brouillon-fond, rgba(184, 134, 58, .07));
}
td.cellule-brouillon-conflit {
  box-shadow: inset 3px 0 0 var(--danger); background: var(--danger-pale);
}
.brouillon-pastille {
  display: inline-block; margin-left: 5px; padding: 0 3px; border-radius: 3px;
  font-size: 11px; line-height: 1.5; cursor: pointer; vertical-align: baseline;
  color: var(--brouillon, #b8863a); background: rgba(184, 134, 58, .16);
  /* La pastille ne doit jamais être coupée par le troncage de la cellule :
     c'est elle qui porte l'information « ce n'est pas enregistré ». */
  white-space: nowrap;
}
.brouillon-pastille:hover { background: rgba(184, 134, 58, .3); }
.brouillon-pastille.conflit { color: var(--danger); background: var(--danger-pale); }
.brouillon-pastille:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Les deux textes du conflit, côte à côte : on ne tranche pas sans les voir. */
.brouillon-diff { border-left: 3px solid var(--line); padding: 4px 0 4px 8px; margin: 8px 0; }
.brouillon-diff.base { border-left-color: var(--ink-3); }
.brouillon-diff.mien { border-left-color: var(--brouillon, #b8863a); }
.brouillon-diff-txt { font-size: 13px; white-space: pre-wrap; word-break: break-word; max-height: 120px; overflow: auto; }

/* ============================================================
   V8.26 — POINT 10 : LA LIGNE « LECTURE » DES MÉTADONNÉES
   ------------------------------------------------------------
   Un PRÉSENT et un PASSANT ne sont pas la même information : le premier peut
   répondre maintenant, le second est un souvenir. L'anneau vert (posé par
   js/presence.js) dit « ici » ; on désature et on adoucit tout le reste, pour
   que la différence se lise d'un coup d'œil et non en survolant chaque rond.
   ============================================================ */
.carte-meta .meta-ligne.meta-lecture { align-items: flex-start; }
.meta-lecture-corps { display: flex; flex-direction: column; gap: 4px; min-height: 24px; }
.meta-lecture-note {
  margin: 0; font-size: 11.5px; line-height: 1.35; color: var(--ink-3); max-width: 34ch;
}
/* Passant : gris, sans halo. La spécificité (deux classes) passe devant la
   règle de base injectée par js/presence.js, qui n'en a qu'une. */
.meta-lecture .presence-rond:not(.presence-rond-ici) { filter: grayscale(1); opacity: .72; }
.meta-lecture .presence-rond:not(.presence-rond-ici):hover { opacity: 1; }
/* Présent : l'anneau vert respire un peu plus que dans les pastilles
   flottantes — ici la ligne est lue posément, pas du coin de l'œil. */
.meta-lecture .presence-rond.presence-rond-ici { box-shadow: 0 0 0 2px var(--card), 0 0 0 3.5px var(--ok); }
.meta-lecture .presence-ronds-vide .presence-ronds-txt { font-style: italic; }

/* V8.57 — même correction que pour le privé (voir plus haut) : ce bloc
   écoutait le SYSTÈME et non le réglage du produit, donc il repeignait le
   brouillon même quand on avait demandé le clair, et se taisait quand on avait
   demandé le sombre sur une machine claire.
   Sur fond sombre l'ocre s'éteint : on l'éclaircit, et le voile de fond passe
   en clair sur sombre plutôt que l'inverse. */
html[data-ui="v2"][data-theme="sombre"] {
  --brouillon: #d9ad63; --brouillon-fond: rgba(217, 173, 99, .12);
}
html[data-ui="v2"][data-theme="sombre"] .brouillon-pastille { background: rgba(217, 173, 99, .18); }
html[data-ui="v2"][data-theme="sombre"] .brouillon-pastille:hover { background: rgba(217, 173, 99, .32); }

/* ============================================================
   V8.26 — POINT 9 : ANNULER / RÉTABLIR (pile locale à l'onglet)
   ------------------------------------------------------------
   Deux boutons dans la barre de la vue, qui PORTENT L'INTITULÉ de ce qu'ils
   vont défaire (« Annuler : Prix de « Chaise » »). D'où deux contraintes de
   dessin qui n'existent pas pour un bouton ordinaire :

   · l'intitulé est long et variable — le bouton ne doit ni faire sauter la
     barre à chaque saisie, ni déborder : largeur plafonnée, texte tronqué en
     « … », phrase complète dans l'infobulle ;
   · désactivé, il doit rester LISIBLE (« Annuler », grisé) plutôt que de
     disparaître : un bouton qui s'efface quand la pile se vide et réapparaît
     à la première saisie fait bouger toute la barre sous la souris.
   ============================================================ */
.annul-groupe { display: inline-flex; gap: 4px; align-self: center; }
.btn.btn-annul {
  max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.btn.btn-annul:disabled { opacity: .45; cursor: not-allowed; }
/* Une BARRIÈRE (geste non annulable en tête de pile) : le bouton reste actif —
   il ouvre l'explication et propose d'aller chercher derrière — mais il ne se
   présente pas comme une annulation ordinaire. Ocre, comme le brouillon : la
   même famille de « ce n'est pas ce que vous croyez ». */
.btn.btn-annul.annul-barriere {
  border-color: var(--brouillon, #b8863a); color: var(--brouillon, #b8863a);
}

/* Les trois valeurs d'un conflit d'annulation, l'une sous l'autre. Même
   grammaire que .brouillon-diff (point 5) : on ne tranche pas sans voir. */
.annul-diff { border-left: 3px solid var(--line); padding: 4px 0 4px 8px; margin: 8px 0; }
.annul-diff.autre { border-left-color: var(--danger); }
.annul-diff.mien { border-left-color: var(--ink-3); }
.annul-diff.cible { border-left-color: var(--accent); }
.annul-diff-txt { font-size: 13px; white-space: pre-wrap; word-break: break-word; max-height: 110px; overflow: auto; }

/* RETOUR VISUEL SUR CE QUI A ÉTÉ RESTAURÉ.
   Une annulation au clavier sur un tableau de cinquante lignes est, sans ça,
   un changement strictement invisible : on ne sait pas ce qui a bougé, donc on
   ne sait pas si ça a marché. Le surlignage est bref (1,6 s) et s'éteint tout
   seul — il signale, il ne décore pas.
   `box-shadow` plutôt que `background` : le fond des cellules porte déjà le
   brouillon, le commentaire et la sélection ; on ne veut pas les écraser. */
@keyframes cc-annul-flash {
  0%   { box-shadow: inset 0 0 0 2px var(--accent); background: var(--accent-pale); }
  70%  { box-shadow: inset 0 0 0 2px var(--accent); background: var(--accent-pale); }
  100% { box-shadow: inset 0 0 0 2px transparent; background: transparent; }
}
.cc-annul-flash { animation: cc-annul-flash 1.6s ease-out 1; }
/* Une carte de kanban n'est pas une cellule : le liseré fait le tour. */
.kanban-carte.cc-annul-flash { border-radius: var(--r); }
/* ⚠ `prefers-reduced-motion` coupe déjà toutes les animations (règle globale du
   haut de fichier) : sans repli, la personne qui l'a activé n'aurait AUCUN
   retour visuel. On lui laisse donc un surlignage fixe, retiré par le même
   minuteur JS. */
@media (prefers-reduced-motion: reduce) {
  .cc-annul-flash { box-shadow: inset 0 0 0 2px var(--accent) !important; background: var(--accent-pale) !important; }
}

/* -- V8.52 : les réglages du compte, dans « Mon profil » -- */
.cc-compte-email {
  font-family: var(--mono); font-size: 12px; color: var(--ink-2);
  margin: 0 0 10px; display: flex; align-items: center; gap: 5px;
}
.cc-compte-reglages > label {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin: 12px 0 4px;
}
.cc-compte-reglages > label:first-child { margin-top: 0; }
.cc-compte-reglages .champ-mdp { max-width: 320px; }
.cc-compte-langue {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft);
}
/* ⚠ `.cc-compte-reglages > label` NE L'ATTRAPE PAS : ce libellé-ci descend de
   `.cc-compte-langue`, il n'est pas enfant direct du bloc. Sans cette ligne,
   « 🌐 Langue » restait `display:inline`, collé à son menu déroulant — le
   défaut exact que la V8.51 vient de corriger dans les modales, reproduit une
   heure plus tard par un sélecteur en enfant direct posé trop vite. */
.cc-compte-langue > label {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin: 0 0 4px;
}
.cc-compte-reglages select { max-width: 320px; }
/* Le trait du menu du compte : deux gestes irréversibles en dessous. */
.cc-menu-trait { border: 0; border-top: 1px solid var(--line-soft); margin: 10px 0 2px; }

/* ============================================================
   V8.56 — LA PASTILLE D'ÉTAT, EN CSS ET NON EN ÉMOJI.
   ------------------------------------------------------------
   « 🟢 en ligne », « ⚪ dépubliée », « 🔴 critique » : trois ronds de couleur
   posés dans une chaîne de caractères. Ils avaient trois défauts, et le
   troisième est celui qui a décidé :

     1. Ils ne sont pas dessinés par nous. 🟢 est un glyphe de la police
        système : vert pomme sur un Mac, vert sapin sur Android, cerclé de
        noir sur certains Windows. Aucun rapport avec `--ok` ni avec le reste
        de l'écran.
     2. Ils ne suivent pas la taille du texte, ni son alignement : un émoji
        rond posé sur une ligne de 12 px déborde vers le bas.
     3. ILS NE CONNAISSENT PAS LE THÈME SOMBRE. Un ⚪ « éteint » disparaît sur
        fond marine ; un 🟢 y devient fluorescent. Une valeur d'état doit
        pâlir et s'assombrir avec le reste, et seule la CSS sait le faire.

   Ce n'est pas une icône non plus — un rond n'est pas un pictogramme, c'est
   une VALEUR. D'où une classe, et non un dessin de plus dans icones.js :

       el('span', { class: 'cc-pastille ok' }, 'en ligne')

   Variantes : `ok` (actif, en ligne), `eteint` (dépublié, épuisé), `alerte`
   (attention), `danger` (critique), `neutre` (par défaut si rien n'est posé).
   ============================================================ */
.cc-pastille { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.cc-pastille::before {
  content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-3);
  /* Un anneau très pâle décolle la pastille du fond : sans lui, le point
     « éteint » (gris clair sur blanc) devient invisible — exactement le
     défaut qu'on reproche au ⚪. */
  box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 12%, transparent);
}
.cc-pastille.ok::before { background: var(--ok); }
.cc-pastille.eteint::before { background: var(--ink-3); opacity: .55; }
.cc-pastille.alerte::before { background: var(--warn, #b8860b); }
.cc-pastille.danger::before { background: var(--danger); }

/* ============================================================
   V8.57 — LE BOUTON DE THÈME DU BANDEAU
   ------------------------------------------------------------
   Il vit sur le bandeau, pas sur le papier : ses couleurs sont donc celles du
   bandeau (`--topbar-*`), qui restent foncées dans les deux thèmes. C'est
   d'ailleurs la seule raison pour laquelle il n'a pas eu besoin d'être repensé
   pour le sombre — un bouton posé sur une surface qui ne s'inverse pas ne
   s'inverse pas non plus.
   ============================================================ */
.btn-theme {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex: none;
  background: none; border: 1px solid transparent; border-radius: var(--r);
  color: var(--topbar-attenue); padding: 0;
}
.btn-theme:hover:not(:disabled) { color: var(--topbar-txt); border-color: var(--topbar-ligne); }
/* ⚠ DÉSACTIVÉ = GRISÉ, PAS EFFACÉ. En interface v1 le thème sombre n'existe
   pas et le bouton est inerte ; le faire DISPARAÎTRE laisserait croire que le
   réglage n'existe pas du tout, alors qu'il est à un Ctrl+Alt+D. Il reste
   visible, éteint, et son `title` dit quoi faire. */
.btn-theme:disabled { opacity: .4; cursor: not-allowed; }

/* Quand le thème SUIT LE SYSTÈME, un point discret sous l'icône. Sans lui,
   « clair parce que je l'ai demandé » et « clair parce que ma machine l'est »
   sont indiscernables — et ce sont deux réglages différents, dont un seul
   basculera tout seul ce soir. */
.btn-theme.suit-systeme { position: relative; }
.btn-theme.suit-systeme::after {
  content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: currentColor; opacity: .7;
}

.cc-theme-pop .cc-menu-item.actif { color: var(--accent-fonce); font-weight: 700; }
.cc-theme-pop .cc-menu-item small { display: block; font-weight: 400; color: var(--ink-3); font-size: 11.5px; }
.cc-theme-pop .cc-menu-item strong { font-weight: inherit; }


/* ============================================================
   V8.57 — LES TROIS THÈMES EN UNE RANGÉE (menu du bandeau étroit)
   Trois boutons plutôt qu'un sous-menu : au doigt, un menu qui ouvre un menu
   est un menu qu'on referme. Ils se serrent sur trois colonnes égales, ce qui
   les rend cliquables sans viser.
   ============================================================ */
.cc-theme-rang { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.cc-theme-rang .btn { justify-content: center; padding: 6px 4px; font-size: 12px; gap: 4px; }
