/* ============================================================
   Somapp v2 — Design system (juillet 2026)
   Thème clair/sombre, accessible (WCAG AA), responsive.
   ============================================================ */

:root {
  /* Couleurs — thème clair */
  --bg: #f4f5f9;
  --surface: #ffffff;
  --surface-2: #f0f1f6;
  --surface-3: #e7e9f1;
  --border: #dcdfe8;
  --border-fort: #c3c7d4;
  --texte: #171923;
  --texte-2: #4b5163;
  --texte-3: #6d7488;
  --accent: #4056d6;
  --accent-hover: #3346bb;
  --accent-doux: #e8ebfc;
  --accent-texte: #ffffff;
  --ok: #1a7f4e;
  --ok-doux: #e0f3e9;
  --attention: #9a6700;
  --attention-doux: #fcf0d7;
  --danger: #c93838;
  --danger-doux: #fce8e8;
  --info: #21618d;
  --info-doux: #e3f0fa;

  /* Teintes catégorielles des cartes d'analyse — validées le 2026-08-27 avec
     `dataviz/scripts/validate_palette.js` : bande de luminosité, plancher de chroma,
     séparation daltonienne et contraste sur la surface, toutes paires confondues.
     TROIS suffisent, et c'est mesuré : une quatrième teinte fait tomber la séparation
     sous le seuil, quel que soit le ton choisi. Le reste des cartes garde un liseré
     gris — c'est justement ce qui permet aux teintes de vouloir dire quelque chose. */
  --carte-dates: #0a7d9c;
  --carte-montants: #7c4dbd;
  --carte-conditions: #b5407a;

  /* Géométrie */
  --radius-s: 8px;
  --radius: 12px;
  --radius-l: 18px;
  --ombre-1: 0 1px 3px rgba(20, 24, 40, .07), 0 1px 2px rgba(20, 24, 40, .05);
  --ombre-2: 0 6px 24px rgba(20, 24, 40, .10), 0 2px 6px rgba(20, 24, 40, .06);
  --ombre-3: 0 16px 48px rgba(20, 24, 40, .18);

  /* Typo */
  --police: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --police-mono: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  /* Polices par rôle : par défaut, chaque rôle hérite de la police générale.
     La personnalisation (admin) peut les surcharger indépendamment. */
  --police-titre: var(--police);
  --police-h1: var(--police-titre);
  --police-h2: var(--police-titre);
  --police-h3: var(--police-titre);
  --police-bouton: var(--police);
  --taille-base: 15px;

  /* Layout */
  --sidebar-l: 300px;
  --topbar-h: 58px;

  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #12141c;
  --surface: #1b1e2a;
  --surface-2: #232736;
  --surface-3: #2b3042;
  --border: #333849;
  --border-fort: #454b61;
  --texte: #eceef4;
  --texte-2: #b3b9c9;
  --texte-3: #8a91a5;
  --accent: #8395f5;
  --accent-hover: #9dabf7;
  --accent-doux: #262c48;
  --accent-texte: #10122b;
  --ok: #4cc98a;
  --ok-doux: #17301f;
  --attention: #e3b341;
  --attention-doux: #33290f;
  --danger: #f07373;
  --danger-doux: #3a1d1d;
  --info: #6cb2e8;

  /* Pas d'éclaircissement automatique des teintes claires : elles sortiraient de la
     bande de luminosité et perdraient leur séparation sur ce fond. Ces trois pas-ci ont
     été choisis puis validés contre la surface sombre (#1b1e2a). */
  --carte-dates: #22a0c0;
  --carte-montants: #8f63d8;
  --carte-conditions: #dd5590;
  --info-doux: #16283a;
  --ombre-1: 0 1px 3px rgba(0, 0, 0, .4);
  --ombre-2: 0 6px 24px rgba(0, 0, 0, .5);
  --ombre-3: 0 16px 48px rgba(0, 0, 0, .6);
  color-scheme: dark;
}

/* Taille de police réglable (accessibilité) */
:root[data-taille="s"] { --taille-base: 13.5px; }
:root[data-taille="l"] { --taille-base: 17px; }
:root[data-taille="xl"] { --taille-base: 19px; }

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { font-size: var(--taille-base); }
body {
  margin: 0;
  font-family: var(--police);
  background: var(--bg);
  color: var(--texte);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

html[data-demo="true"] body { padding-top: 30px; }
.banniere-demo {
  position: fixed; top: 0; left: 0; right: 0; z-index: 500;
  width: 100%;
  height: 30px; display: flex; align-items: center; justify-content: center;
  background: #20242d; color: #ffd166;
  border-bottom: 1px solid #4b5363;
  font-size: .74rem; font-weight: 750; letter-spacing: .06em;
}
html[data-demo="true"] .app { min-height: calc(100vh - 30px); }
html[data-demo="true"] .sidebar { top: 30px; height: calc(100vh - 30px); }
html[data-demo="true"] .topbar { top: 30px; }
html[data-demo="true"] .page-login { min-height: calc(100vh - 30px); }
img, svg, video { max-width: 100%; }
/* Icônes déclaratives : centrées, sans décalage de baseline du SVG inline */
[data-icone] { display: inline-flex; align-items: center; justify-content: center; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.25; font-weight: 650; }
h1 { font-size: 1.45rem; font-family: var(--police-h1); }
h2 { font-size: 1.2rem; font-family: var(--police-h2); }
h3, h4 { font-size: 1.05rem; font-family: var(--police-h3); }
h3 { font-size: 1.05rem; }
p { margin: 0 0 .8em; }
code { font-family: var(--police-mono); font-size: .88em; background: var(--surface-2); padding: .1em .35em; border-radius: 5px; }
::selection { background: var(--accent); color: var(--accent-texte); }

/* Focus visible : indispensable au clavier */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Mouvement réduit */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Lien d'évitement */
.skip-link {
  position: absolute; left: -9999px; top: 8px; z-index: 300;
  background: var(--accent); color: var(--accent-texte);
  padding: 10px 18px; border-radius: var(--radius-s); font-weight: 600;
}
.skip-link:focus { left: 8px; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Layout général ---------- */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-l) 1fr;
  grid-template-rows: var(--topbar-h) 1fr;
  grid-template-areas: "sidebar topbar" "sidebar main";
  min-height: 100vh;
}
.topbar { grid-area: topbar; }
.sidebar { grid-area: sidebar; }
.main {
  grid-area: main;
  /* Le bas est généreux : la barre de sélection est fixe et viendrait sinon recouvrir
     les derniers éléments de la liste. */
  padding: 22px 26px 96px;
  max-width: 100%;
  width: 100%;
}

/* ---------- Mémo partagé (panneau de droite) ---------- */
/* La zone de contenu se partage entre la page (85 %) et le chat (15 %), ce dernier ne
   descendant jamais sous 400 px — en deçà, les bulles deviennent trop étroites pour un
   vrai fil de discussion. Le `min-width:0` de la première colonne est indispensable :
   sans lui, un tableau large refuserait de rétrécir et pousserait le panneau hors de
   l'écran. */
.main { display: grid; grid-template-columns: minmax(0, 85fr) minmax(400px, 15fr); gap: 18px; align-items: start; }
.zone-principale { min-width: 0; }
.panneau-memo {
  display: flex; flex-direction: column; min-width: 0;
  position: sticky; top: calc(var(--topbar-h) + 22px);
  /* Hauteur visible moins 150 px. Un `100%` ne conviendrait pas : le parent n'a pas de
     hauteur propre, la valeur se résoudrait à `auto` et la limite serait sans effet. */
  max-height: calc(100vh - 150px);
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
}
/* Fermé : le panneau disparaît entièrement et la page reprend toute la largeur.
   Le seul point de bascule est le bouton « Chat support » de la barre du haut. */
html.memo-replie .main { grid-template-columns: minmax(0, 1fr); }
html.memo-replie .panneau-memo { display: none; }

.memo-tete {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border);
}
.memo-tete h2 { margin: 0; font-size: .95rem; flex: 1; }
/* Bascule d'ordre du fil : deux segments jointifs, un seul actif. Le format réduit la
   maintient dans l'en-tête sans concurrencer le titre. */
.memo-tri {
  display: inline-flex; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: 20px;
  background: var(--surface-2); padding: 2px;
}
.memo-tri button {
  border: none; background: none; cursor: pointer;
  font: inherit; font-size: .72rem; font-weight: 600; color: var(--texte-3);
  padding: 2px 9px; border-radius: 20px; line-height: 1.6;
  transition: background .12s, color .12s;
}
.memo-tri button:hover { color: var(--texte); }
.memo-tri button.actif { background: var(--surface); color: var(--accent); box-shadow: var(--ombre-1); }
/* Croix de fermeture : discrète dans l'en-tête, elle ne se colore qu'au survol pour ne
   pas concurrencer le titre. Format réduit, l'en-tête du panneau étant compact. */
#memo-fermer { width: 28px; height: 28px; border-radius: 7px; color: var(--texte-3); }
#memo-fermer:hover {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
}

/* Bouton d'ouverture du chat : la pastille dit d'un coup d'œil si le panneau est
   affiché (vert) ou masqué (gris), sans avoir à chercher la colonne des yeux. */
#btn-chat-support .pastille-etat {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--texte-3); flex: none;
  transition: background .15s ease, box-shadow .15s ease;
}
#btn-chat-support.actif .pastille-etat {
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent);
}

/* Voyant de synchronisation. Il n'est pas cliquable : le curseur doit le dire, sinon on
   passe son temps a essayer. Deux etats seulement, parce qu'un voyant a trois couleurs
   demande qu'on se souvienne de la troisieme. */
.indicateur-sync {
  cursor: default;
  gap: 6px;
}
.indicateur-sync .pastille-etat {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  /* Orange par defaut : le passage suivant est attendu. */
  background: var(--attention);
  transition: background .2s ease, box-shadow .2s ease;
}
/* Vert pendant trente secondes apres un passage. Le halo attire l'oeil sans clignoter —
   un voyant qui clignote dans un en-tete permanent devient vite insupportable. */
.indicateur-sync.fait .pastille-etat {
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent);
}
.memo-fil { flex: 1; min-height: 120px; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 14px; }
.memo-vide { margin: auto 0; color: var(--texte-3); font-size: .86rem; font-style: italic; text-align: center; }
/* Bulles de conversation : les messages reçus à gauche, les siens à droite. Le coin
   « mordu » du côté de l'émetteur donne le sens de lecture sans avoir à lire l'auteur. */
.memo-message {
  /* Un plancher de largeur évite les bulles minuscules sur les messages très courts,
     qui rompaient l'alignement visuel du fil. */
  align-self: flex-start; min-width: 60%; max-width: 100%;
  border: 1px solid var(--border); border-radius: 12px 12px 12px 4px;
  padding: 12px 9px 11px; background: var(--surface-2);
  box-shadow: 0 1px 2px rgb(20 24 40 / .05);
}
.memo-message.memo-mien {
  /* Ses propres messages restent calés à droite, avec un plancher à la moitié du fil :
     assez large pour se lire, assez retiré pour rester distinct des messages reçus. */
  align-self: flex-end; min-width: 50%;
  border-radius: 12px 12px 4px 12px;
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
  background: linear-gradient(180deg,
    rgb(230 233 250 / 24%),
    color-mix(in srgb, var(--accent) 7%, var(--surface)));
}
.memo-entete { display: flex; align-items: center; gap: 6px; margin-bottom: 9px; }
/* Initiale de l'auteur : la teinte vient de son nom, elle reste donc la même partout. */
.memo-pastille {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: .68rem; font-weight: 700; letter-spacing: 0;
  background: hsl(var(--teinte-auteur) 62% 88%);
  color: hsl(var(--teinte-auteur) 55% 32%);
}
:root[data-theme="dark"] .memo-pastille {
  background: hsl(var(--teinte-auteur) 35% 26%);
  color: hsl(var(--teinte-auteur) 70% 78%);
}
.memo-auteur { font-weight: 650; font-size: .78rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.memo-mien .memo-auteur { color: var(--accent); }
.memo-heure { font-size: .7rem; color: var(--texte-3); margin-left: auto; flex: 0 0 auto; }
/* La croix vient après l'heure : elle ne doit pas repousser l'horodatage. */
.memo-entete .memo-suppr { margin: 0; }
/* La croix porte sa teinte d'alerte dès le repos — l'action est destructive, autant
   l'annoncer — et se remplit d'un rouge franc au survol, croix en blanc. */
.memo-suppr {
  margin: 0; border: none; background: var(--danger-doux); padding: 4px; cursor: pointer;
  color: var(--danger); display: inline-flex; border-radius: 5px;
  /* Remontée de 2 px : alignée sur l'auteur et l'heure, la croix paraissait basse. */
  position: relative; top: -2px;
  transition: background .13s, color .13s;
}
.memo-suppr:hover { background: var(--danger); color: #ffffff; }
/* Le texte est posé sur un fond propre, détaché de la couleur de la bulle : il gagne
   en lisibilité, et l'en-tête comme les réactions restent dans la teinte de l'auteur. */
.memo-texte {
  margin: 0; font-size: .94rem; line-height: 1.6;
  overflow-wrap: anywhere; white-space: pre-wrap;
  background: var(--surface); border-radius: 8px; padding: 9px 11px;
  /* Un long message ne doit pas chasser tout le fil hors de l'écran : au-delà de ~9
     lignes la bulle est coupée et « Tout lire » ouvre le texte entier en modale. */
  max-height: 15em; overflow: hidden;
}
/* Blanc franc dans ses propres bulles, dont le fond est déjà teinté. */
.memo-mien .memo-texte {
  background-color: #ffffff;
}
/* Fondu de bas de bulle : la coupure se voit sans trait net, et le bouton qui suit
   s'annonce de lui-même. Le dégradé est un masque, il s'adapte donc au fond du thème. */
.memo-message.tronque .memo-texte {
  border-radius: 8px 8px 0 0;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent);
}
.memo-lire {
  display: block; width: 100%; margin: 0; border: none; cursor: pointer;
  background: var(--surface); border-radius: 0 0 8px 8px;
  padding: 4px 11px 8px; text-align: left;
  font: inherit; font-size: .82rem; font-weight: 600; color: var(--accent);
}
.memo-mien .memo-lire { background-color: #ffffff; }
.memo-lire:hover { text-decoration: underline; }
/* Texte intégral en modale : mêmes règles de césure que la bulle, en plus lisible. */
.memo-texte-complet {
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: .96rem; line-height: 1.65;
}
.memo-reactions { display: flex; align-items: center; gap: 4px; margin-top: 11px; }
/* Vote de priorité : deux flèches encadrant le score. Le groupe est compact et posé
   avant les réactions — c'est l'information qui sert à trier le support. */
.memo-vote {
  display: inline-flex; align-items: center; gap: 1px;
  border: 1px solid var(--border); border-radius: 20px;
  padding: 0 2px; margin-right: 4px; background: var(--surface);
}
.memo-fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: none; border-radius: 50%;
  background: none; color: var(--texte-3); cursor: pointer;
  transition: background .12s, color .12s;
}
/* Une seule icône de chevron pour les deux sens : la flèche du haut est le même dessin
   retourné, ce qui garantit deux glyphes rigoureusement symétriques. */
.memo-fleche.haut { rotate: 180deg; }
.memo-fleche:hover { background: var(--surface-2); color: var(--texte); }
.memo-fleche.haut.actif { color: var(--ok); background: var(--ok-doux); }
.memo-fleche.bas.actif { color: var(--danger); background: var(--danger-doux); }
.memo-score {
  min-width: 18px; text-align: center;
  font-size: .76rem; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--texte-3);
}
.memo-vote[data-signe="pos"] .memo-score { color: var(--ok); }
.memo-vote[data-signe="neg"] .memo-score { color: var(--danger); }
.memo-reaction {
  display: inline-flex; align-items: center; gap: 3px;
  border: 1px solid transparent; border-radius: 20px;
  background: color-mix(in srgb, var(--texte) 6%, transparent);
  padding: 1px 6px; font-size: .78rem; cursor: pointer; line-height: 1.7;
  transition: background .12s, border-color .12s;
}
.memo-reaction span { font-size: .72rem; font-weight: 650; color: var(--texte-2); }
.memo-reaction:hover { border-color: var(--accent); background: var(--surface); }
.memo-reaction.actif { border-color: var(--accent); background: var(--accent-doux); }
/* Le pouce n'est en couleur que si l'on a soi-même réagi : le total des autres se lit
   au compteur, la couleur répond seulement à « est-ce que j'ai cliqué ? ». Au survol,
   il se colore en aperçu de ce que le clic produira. */
/* Sélecteur composé volontaire : sans lui, la règle `.memo-reaction span` ci-dessus
   l'emporterait et rapetisserait l'emoji à la taille du compteur. */
.memo-reaction .memo-pouce {
  font-size: .78rem; font-weight: inherit; color: inherit;
  filter: grayscale(1); opacity: .55;
  transition: filter .12s, opacity .12s;
}
.memo-reaction:hover .memo-pouce,
.memo-reaction.actif .memo-pouce { filter: none; opacity: 1; }
/* Page d'origine : poussée à droite de la ligne par `margin-left:auto`, elle ferme la
   bulle sans se mêler aux votes. Le libellé s'efface avant l'icône si la place manque. */
.memo-lien {
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: auto; width: 24px; height: 24px;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--texte-3);
  text-decoration: none; transition: border-color .12s, color .12s;
}
.memo-lien svg { flex: 0 0 auto; }
a.memo-lien { cursor: pointer; }
a.memo-lien:hover { border-color: var(--accent); color: var(--accent); }
/* Message écrit depuis la page où l'on se trouve déjà : l'information reste affichée,
   mais rien à cliquer — le curseur ne doit donc pas promettre une action. */
.memo-lien.inerte { opacity: .6; cursor: default; }

.memo-saisie { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--border); }
.memo-saisie textarea { width: 100%; resize: vertical; font: inherit; font-size: .86rem; }

/* Sous 1200 px, le mémo passe sous la page : à 30 % il deviendrait illisible. */
@media (max-width: 1200px) {
  .main { grid-template-columns: minmax(0, 1fr); }
  .panneau-memo { position: static; max-height: 60vh; }
}

/* ---------- Topbar ---------- */
.topbar {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 0 18px;
  position: sticky; top: 0; z-index: 60;
}
/* Omnibox de recherche */
.omnibox { position: relative; flex: 1; min-width: 0; max-width: 720px; margin: 0 auto 0 20px; }
.topbar-explorateur { gap: 0; }
.topbar-explorateur .omnibox { margin-right: 0; }
.topbar-explorateur #btn-toggle-recherche {
  flex: 0 0 auto; height: 38px; margin-left: 10px; margin-right: auto;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px;
  font-family: var(--police); font-size: .95rem; line-height: 1;
}
.topbar-explorateur #btn-toggle-recherche ~ * { margin-left: 12px; }
.omnibox input {
  width: 100%; height: 38px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--texte);
  padding: 0 84px 0 38px;
  font-size: .95rem;
  transition: border-color .15s, background .15s;
}
#recherche-globale { padding: 8px 12px 8px 40px; }
.omnibox input:focus { border-color: var(--accent); background: var(--surface); }
.omnibox .ico-loupe { position: absolute; left: 12px; top: 56%; translate: 0 -50%; color: var(--texte-3); pointer-events: none; }
.omnibox .raccourci {
  position: absolute; right: 46px; top: 50%; translate: 0 -50%;
  font-size: .72rem; color: var(--texte-3);
  border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px;
  background: var(--surface);
}
.omnibox .btn-voix { position: absolute; right: 8px; top: 50%; translate: 0 -50%; }
.btn-voix.ecoute { color: var(--danger); animation: pulse-voix 1.2s infinite; }
@keyframes pulse-voix { 50% { opacity: .45; } }

.suggestions {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--ombre-2);
  padding: 6px; z-index: 100; max-height: 420px; overflow: auto;
}
.suggestions [role="option"] {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer;
  color: var(--texte);
}
.suggestions [role="option"]:hover, .suggestions [role="option"][aria-selected="true"] { background: var(--accent-doux); }
.suggestions .genre { margin-left: auto; font-size: .72rem; color: var(--texte-3); text-transform: uppercase; letter-spacing: .04em; }
.suggestions .raison-recherche { margin-top: 3px; white-space: normal; }

/* ---------- Sidebar ---------- */
.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  z-index: 70;
}
.sidebar .logo {
  display: flex; align-items: center; gap: 8px;
  padding: 13px 18px 11px;
  color: var(--texte); text-decoration: none;
}
/* Marque : le SVG porte ses propres couleurs, il ne suit donc pas le thème — d'où
   l'absence de teinte imposée ici. Le tracé n'est pas carré (viewBox 891 × 784) :
   `object-fit: contain` le laisse respirer sans le déformer. */
.logo-marque { width: 60px; height: 60px; flex-shrink: 0; object-fit: contain; }
/* Poppins n'est chargée que pour le nom de la marque : le reste de l'interface garde
   la police système, réglable par l'administration. Les deux moitiés du nom reprennent
   les teintes du logo — le bleu de la vague, l'orange de la voile. */
.logo-nom {
  font-family: 'Poppins', var(--police);
  font-size: 22px; font-weight: 600; letter-spacing: -.015em; line-height: 1;
  color: #324281;
}
.logo-nom b { font-weight: inherit; color: inherit; }
/* Les deux moitiés du nom sont droites : même teinte, même graisse, aucun contraste
   typographique — la coupure Som/app ne se lit plus que dans le logo lui-même. */
.logo-app { font-style: normal; }
.nav-groupe { padding: 6px 10px; }
.nav-groupe + .nav-groupe { border-top: 1px solid var(--border); margin-top: 6px; padding-top: 12px; }
.nav-groupe .nav-titre {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--texte-3); padding: 4px 10px 6px; font-weight: 650;
}
.nav-lien {
  display: flex; align-items: center; gap: 11px;
  padding: 8px 12px; margin: 1px 0;
  border-radius: 9px; color: var(--texte-2);
  font-weight: 500; text-decoration: none;
  transition: background .12s, color .12s;
}
.nav-lien:hover { background: var(--surface-2); color: var(--texte); text-decoration: none; }
.nav-lien[aria-current="page"] { background: var(--accent-doux); color: var(--accent); font-weight: 650; }
.nav-lien .badge-nb { margin-left: auto; }
.sidebar .pied {
  margin-top: auto; padding: 12px 16px; border-top: 1px solid var(--border);
  font-size: .78rem; color: var(--texte-3);
}

/* Arbre de dossiers */
.arbre-filtre { padding: 0 6px 6px; }
.arbre-filtre input {
  width: 100%; height: 30px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-2); color: var(--texte); font-size: .84rem;
}
.arbre-filtre input:focus { border-color: var(--accent); outline: none; }
/* Dossier qui correspond au filtre : les branches conservées uniquement pour mener à
   lui restent neutres, seul le résultat est mis en avant. */
.noeud-trouve { color: var(--accent); font-weight: 600; }
/* Un dossier ouvert : les dossiers voisins s'effacent pour mettre en avant l'endroit
   où l'on se trouve. Le chemin qui y mène reste net, sinon on perdrait le repère. */
.arbre-a-actif .noeud:not(.actif):not(.noeud-chemin) { opacity: .6; transition: opacity .15s; }
.arbre-a-actif .noeud:not(.actif):not(.noeud-chemin):hover { opacity: 1; }
/* Le contenu du dossier ouvert reste net : ce sont ses sous-dossiers, donc ce qu'on
   est venu consulter — seules les branches voisines s'effacent. */
.arbre-a-actif li:has(> .noeud.actif) .noeud { opacity: 1; }
/* Recherche en cours : les résultats restent pleinement lisibles. L'estompage sert à
   mettre en avant le dossier ouvert, il n'a plus lieu d'être quand on filtre. */
.arbre-filtre-actif .noeud:not(.actif):not(.noeud-chemin) { opacity: 1; }
/* Bouton de remontée, sous le champ de filtre : pleine largeur, il remplace les
   branches masquées comme moyen de revenir en arrière. */
/* Mêmes teintes que le fil d'Ariane de l'explorateur : bleu ciel et texte bleu — les
   deux jouent le même rôle de navigation dans la hiérarchie. */
.arbre-retour {
  display: flex; align-items: center; gap: 7px; width: 100%; margin-top: 6px;
  padding: 6px 10px; border: none; border-radius: 6px;
  background-color: #d7edfe; color: #3e76d0;
  font-size: .82rem; font-weight: 600; text-decoration: none;
}
/* La flèche est un tracé en `currentColor` : elle suit la couleur du texte. */
.arbre-retour:hover { background-color: #bfe0fd; color: #2f6fd0; text-decoration: none; }
:root[data-theme="dark"] .arbre-retour { background-color: #262e49; color: #b4bee3; }
:root[data-theme="dark"] .arbre-retour:hover { background-color: var(--surface-3); color: #8ab8f5; }
.arbre-retour svg { flex: 0 0 auto; }
.arbre-retour span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arbre-aucun { margin: 4px 8px; font-size: .82rem; color: var(--texte-3); font-style: italic; }
/* Le filtre ne trouve rien : plutôt que de laisser la personne dans une impasse, on lui
   propose de créer le dossier qu'elle cherchait. */
.arbre-creer {
  display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px;
  padding: 5px 8px; border: 1px dashed var(--border-fort); border-radius: var(--radius-s);
  background: none; color: var(--accent); cursor: pointer;
  font: inherit; font-size: .8rem; font-style: normal; text-align: left;
  transition: background .13s ease, border-color .13s ease;
}
.arbre-creer:hover,
.arbre-creer:focus-visible { background: var(--accent-doux); border-color: var(--accent); outline: none; }
.arbre-creer svg { flex: 0 0 auto; }
.arbre-creer span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arbre { padding: 2px 0 10px; }
.arbre ul { list-style: none; margin: 0; padding-left: 16px; }
.arbre > ul { padding-left: 4px; }
.arbre li { margin: 0; padding: 2px 0; }
/* Le fond reprend la couleur de la catégorie du dossier (`--c-dossier`, posé en style
   inline), très dilué. Sans catégorie la variable est absente et le fond reste
   transparent. Les règles de survol et d'état actif suivent et l'emportent. */
.noeud {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 8px 8px 0; border-radius: 7px;
  color: var(--texte-2); cursor: pointer; text-decoration: none;
  font-size: .92rem;
  background: color-mix(in srgb, var(--c-dossier, transparent) 9%, transparent);
}
.noeud:hover { background: var(--surface-2); text-decoration: none; }
.noeud.actif { background: var(--accent-doux); color: var(--accent); font-weight: 600; }
.noeud .chevron {
  width: 18px; height: 18px; display: grid; place-items: center;
  border: none; background: none; color: var(--texte-3); cursor: pointer;
  border-radius: 4px; padding: 0; flex-shrink: 0;
  transition: transform .15s;
}
/* Seul le chevron cliquable est pastillé : les feuilles de l'arbre portent la même
   classe sur un <span> vide, qui doit rester invisible. Le trait est épaissi via
   `stroke-width` — le SVG ne réagit pas à `font-weight`. Déplié = bleu, replié = vert :
   l'état du dossier se lit à la couleur avant même l'orientation du chevron. */
.noeud button.chevron {
  width: 20px; height: 20px; border-radius: 50px;
  color: #0b5c2a; background: #b7f0c9;
  opacity: .9; /* la pastille s'adoucit sans que ses deux teintes soient à refaire */
}
.noeud button.chevron.ouvert { color: #0e1d7b; background: #b4defe; }
/* Le SVG est rendu à 13 px par `icone()` : on l'agrandit ici plutôt qu'à l'appel, la
   taille n'ayant de sens que dans cette pastille. Le trait suit l'échelle du viewBox. */
.noeud button.chevron svg { width: 11px; height: 11px; }
/* Sur le <path>, pas sur le <svg> : le tracé porte un attribut `stroke-width="2"` en
   dur, et un attribut de présentation l'emporte toujours sur une valeur héritée. */
.noeud button.chevron svg path { stroke-width: 4.5; }
.noeud .chevron.ouvert { transform: rotate(90deg); }
/* L'icône du dossier est un flex item comme un autre : sans cela, un nom long la
   comprimait au lieu de laisser le texte se tronquer. Le chevron, lui, est déjà figé.
   `--c-dossier` vient de la catégorie du dossier, posée en style inline ; sans
   catégorie la variable est absente et l'icône suit la couleur du texte. */
.noeud > svg { flex: 0 0 auto; color: var(--c-dossier, inherit); }
/* Le nom se coupe sur une seule ligne : c'est ce débordement en largeur qui déclenche
   la bulle de rappel au survol (cf. `tronqueEnLargeur` dans core.js). */
.noeud .nom-noeud { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noeud .nb { margin-left: auto; font-size: .74rem; color: var(--texte-3); }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 36px; padding: 0 14px;
  border-radius: 9px; border: 1px solid transparent;
  font: inherit; font-family: var(--police-bouton); font-size: .92rem; font-weight: 600;
  cursor: pointer; text-decoration: none;
  transition: background .13s, border-color .13s, color .13s, box-shadow .13s;
  white-space: nowrap;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primaire { background: var(--accent); color: var(--accent-texte); }
.btn-primaire:hover:not(:disabled) { background: var(--accent-hover); }
.btn-secondaire { background: var(--surface); color: var(--texte); border-color: var(--border-fort); }
.btn-secondaire:hover:not(:disabled) { background: var(--surface-2); }
.btn-discret { background: transparent; color: var(--texte-2); }
.btn-discret:hover:not(:disabled) { background: var(--surface-2); color: var(--texte); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover:not(:disabled) { filter: brightness(.92); }
.btn-danger-doux { background: var(--danger-doux); color: var(--danger); }
.btn-attention-doux { background: var(--attention-doux); color: var(--attention); }
.btn-attention-doux:hover:not(:disabled) { filter: brightness(.95); }
.btn-s { height: 30px; padding: 0 10px; font-size: .84rem; border-radius: 7px; }
.btn-icone {
  width: 36px; height: 36px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px; border: none; background: transparent;
  color: var(--texte-2); cursor: pointer;
  transition: background .13s, color .13s;
}
/* Barre du haut : le fond gris ne surgit plus au survol, il est là en permanence — les
   boutons se lisent comme des pastilles, et seul le bleu marque le survol. Le `:where()`
   ramène la spécificité au niveau de la règle de survol, qui suit et doit l'emporter :
   sans lui, les boutons imbriqués (cloche, compte) gardaient leur gris au survol.
   Le micro est exclu : il vit dans le champ de recherche, pas à côté. */
.topbar .btn-icone:not(:where(.btn-voix)) { background: var(--surface-2); }
/* Survol : bleu léger, franc. `--surface-2` (le gris d'avant) tirait déjà sur le bleu,
   donc un mélange trop dilué ne se distinguait pas ; l'icône vire à l'accent avec lui. */
.btn-icone:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); }
.btn-icone.actif { background: var(--accent-doux); color: var(--accent); }

/* ---------- Style & paramètres : table élément par élément (admin) ---------- */
.style-table-enveloppe { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-s); }
.style-table { min-width: 1160px; margin: 0; }
.style-table th, .style-table td { padding: 6px 8px; text-align: center; vertical-align: middle; }
.style-table thead th {
  position: sticky; top: 0; z-index: 1;
  font-size: .72rem; text-transform: uppercase; letter-spacing: .03em;
  color: var(--texte-3); background: var(--surface-2); white-space: nowrap;
}
.style-th-groupe { border-left: 1px solid var(--border); }
.style-table tbody td { border-bottom: 1px solid var(--border); }
.style-table tbody tr:last-child td { border-bottom: 0; }
.style-el-nom { text-align: left !important; min-width: 210px; }
.style-el-nom span { display: inline-flex; flex-direction: column; gap: 1px; vertical-align: middle; }
.style-el-nom strong { font-size: .86rem; font-weight: 600; }
.style-el-nom code {
  font-size: .72rem; color: var(--texte-3); background: none; padding: 0;
}
.style-reset-ligne { width: 26px; height: 26px; margin-right: 8px; vertical-align: middle; }
.style-apropos { text-align: left !important; max-width: 240px; }
.style-apropos-txt {
  display: block; max-width: 240px; width: 100%;
  font: inherit; font-size: .8rem; color: var(--texte-2); text-align: left;
  background: none; border: none; padding: 0; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.style-apropos-txt:hover { color: var(--accent); text-decoration: underline; }
.style-td-na { color: var(--texte-3); opacity: .5; }
.style-cell-couleur {
  width: 40px; height: 28px; padding: 2px; border: 1px solid var(--border-fort);
  border-radius: 6px; background: var(--surface); cursor: pointer;
}
.style-cell-couleur::-webkit-color-swatch { border: none; border-radius: 3px; }
.style-cell-couleur::-webkit-color-swatch-wrapper { padding: 0; }
.style-cell-taille { width: 66px; text-align: center; }
.style-cell-police { min-width: 130px; height: 30px; padding: 2px 6px; font-size: .82rem; }

/* ---------- Sélecteur personnalisé (remplace les <select> natifs) ---------- */
.select-natif-cache { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; margin: -1px; }
.select-custom { position: relative; vertical-align: middle; max-width: 100%; }
.select-custom-bouton {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; min-height: 38px; padding: 8px 12px;
  font: inherit; color: var(--texte); text-align: left; cursor: pointer;
  /* Le <select> natif étant toujours masqué au profit de ce bouton, c'est ici qu'il
     faut reprendre les teintes des champs de saisie. */
  background: #f5faff; border: 1px solid #cad3ef; border-radius: 9px;
  box-shadow: 0 0 0 3px var(--halo-champ, transparent);
  transition: border-color .13s, box-shadow .13s;
}
.select-custom-bouton:hover { border-color: var(--accent); }
/* Sélecteur verrouillé : la valeur reste lisible — c'est bien l'information qui compte —
   mais rien n'invite à cliquer. Même traitement qu'un champ texte désactivé. */
.select-custom.desactive .select-custom-bouton {
  background: var(--surface-2); color: var(--texte-3); cursor: not-allowed;
}
.select-custom.desactive .select-custom-bouton:hover { border-color: var(--border); }
.select-custom.desactive .select-custom-bouton > svg { opacity: .4; }
:root[data-theme="dark"] .select-custom-bouton { background: var(--surface); border-color: var(--border-fort); }
.select-custom.ouvert .select-custom-bouton { border-color: var(--accent); }
.select-custom-bouton:focus-visible { outline: none; border-color: var(--accent); }
.select-custom-txt { display: inline-flex; align-items: center; gap: 8px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select-custom-txt > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select-custom-bouton > svg { flex: 0 0 auto; color: var(--texte-3); transition: transform .18s ease; }
.select-custom.ouvert .select-custom-bouton > svg { transform: rotate(180deg); }
/* position:fixed + coordonnées calculées en JS : le panneau échappe aux conteneurs
   qui le rognaient (.modale-corps en overflow:auto, tableaux, panneaux à défilement). */
.select-custom-panneau {
  position: fixed; z-index: 300; top: 0; left: 0;
  max-width: min(320px, 90vw); max-height: 300px;
  /* Le panneau ne défile plus lui-même : c'est la liste interne qui le fait, pour que la
     barre de boutons reste visible au lieu de disparaître vers le haut. */
  overflow: hidden; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border-fort); border-radius: 11px;
  box-shadow: var(--ombre-2); padding: 5px;
  opacity: 0; transform: translateY(-6px) scale(.99); pointer-events: none;
  transition: opacity .13s ease, transform .13s ease;
}
.select-custom.ouvert .select-custom-panneau { opacity: 1; transform: none; pointer-events: auto; }
/* Hauteur de ligne fixe plutôt que dictée par le contenu : c'est elle qui sert à plafonner
   une colonne à un nombre de lignes exact. Déduite de la hauteur du contenu (texte ~17px,
   pastille 17px) plus l'ancien remplissage — l'aspect ne change pas, il devient prévisible.
   Le remplissage vertical reste pour les rares contenus plus hauts, que `min-height`
   laisse alors grandir. */
.select-custom-panneau { --select-ligne-h: 34px; }
.select-custom-item {
  display: flex; align-items: center; gap: 9px;
  min-height: var(--select-ligne-h);
  padding: 4px 10px; border-radius: 7px; cursor: pointer;
  font-size: .9rem; color: var(--texte); white-space: nowrap;
}
.select-custom-item > span { overflow: hidden; text-overflow: ellipsis; }
/* Nombre d'éléments derrière l'entrée. `flex: 0 0 auto` : c'est le libellé qui se tronque,
   jamais le compte — un « Factur… (5) » reste utile, un « Factures (… » ne dit plus rien. */
.select-custom-nb {
  flex: 0 0 auto; margin-left: -3px;
  font-size: .82rem; color: var(--texte-3); font-variant-numeric: tabular-nums;
}
.select-custom-item.actif .select-custom-nb { color: inherit; opacity: .7; }
.select-custom-item:hover { background: var(--surface-2); }
.select-custom-item.actif { background: var(--accent-doux); color: var(--accent); font-weight: 650; }
/* Option présente dans la liste mais indisponible ici. Elle reste lisible — c'est son but,
   dire qu'une valeur existe ailleurs — sans jamais réagir au survol ni au clic. */
.select-custom-item.desactive { opacity: .45; cursor: default; }
.select-custom-item.desactive:hover { background: transparent; }
.select-custom-vide { padding: 10px 12px; font-size: .84rem; color: var(--texte-3); font-style: italic; }
/* Créer l'entrée manquante (`data-action-vide`). Hors de la liste qui défile, en pied de
   panneau : c'est une commande, pas une valeur — et elle doit rester visible quand la
   liste est longue, puisqu'elle sert justement quand aucune ligne ne convient. */
.select-custom-creer {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px; width: 100%;
  margin-top: 4px; padding: 8px 10px; border: 0; border-top: 1px solid var(--border);
  border-radius: 0 0 7px 7px; background: none; cursor: pointer;
  font: inherit; font-size: .86rem; text-align: left; color: var(--accent);
  transition: background .13s ease;
}
.select-custom-creer:hover,
.select-custom-creer:focus-visible { background: var(--accent-doux); outline: none; }
.select-custom-creer svg { flex: 0 0 auto; }
.select-custom-creer span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Raccourci de la colonne « ailleurs » : un vrai bouton, donc atteignable au clavier.
   Assombri au repos — il ne décrit rien du dossier ouvert — mais il réagit au survol,
   sans quoi rien ne dirait qu'il est cliquable là où ses voisins ne le sont pas. */
.select-custom-ailleurs {
  width: 100%; text-align: left; font-family: inherit;
  border: 0; background: none; opacity: .62; cursor: pointer;
  transition: opacity .13s ease, background .13s ease;
}
.select-custom-ailleurs:hover,
.select-custom-ailleurs:focus-visible {
  opacity: 1; background: var(--surface-2); color: var(--accent); outline: none;
}
/* Deux colonnes (`data-colonnes`) : disponibles à gauche, indisponibles à droite, chacune
   sous son titre. La grille existe même à une seule colonne — le titre reste utile seul,
   c'est lui qui dit pourquoi les lignes sont là. La classe `colonnes` n'apparaît que quand
   les deux groupes sont peuplés ; elle seule élargit le panneau et dédouble la grille. */
.select-custom-grille { display: grid; grid-template-columns: 1fr; gap: 2px; }
/* Plus haut qu'une liste simple : il doit loger 6 lignes, le titre et la barre de boutons.
   Le JS pose la valeur définitive selon la place disponible ; ceci n'est que le repli. */
.select-custom-panneau.colonnes { max-width: min(560px, 92vw); max-height: 420px; }
.select-custom-panneau.colonnes .select-custom-grille { grid-template-columns: 1fr 1fr; gap: 10px; }
.select-custom-panneau.colonnes .select-custom-colonne + .select-custom-colonne {
  border-left: 1px solid var(--border); padding-left: 10px;
}
.select-custom-colonne { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
/* Chaque colonne défile pour son propre compte, plafonnée à 6 lignes. Avant, une colonne
   longue étirait le panneau et faisait défiler les deux ensemble : on perdait de vue la
   colonne courte pour aller au bout de l'autre. Le plafond s'exprime en hauteurs de ligne,
   donc il reste juste si la ligne change de taille. */
.select-custom-lignes {
  overflow-y: auto; min-height: 0;
  max-height: calc(var(--select-ligne-h) * 6);
  overscroll-behavior: contain;
}
/* Barre de commandes du filtre (`data-bouton`) : hors de la zone qui défile, donc toujours
   sous les yeux. Ce sont de vrais <button>, hors du listbox — ils commandent le filtre,
   ils ne nomment pas une valeur. */
.select-custom-actions {
  display: flex; gap: 6px; flex: 0 0 auto;
  padding: 2px 2px 7px; margin-bottom: 5px; border-bottom: 1px solid var(--border);
}
.select-custom-action {
  flex: 1; min-width: 0; padding: 6px 10px; border-radius: 7px;
  border: 1px solid var(--border-fort); background: var(--surface-2);
  font-size: .82rem; font-weight: 600; color: var(--texte); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.select-custom-action:hover:not(:disabled),
.select-custom-action:focus-visible { border-color: var(--accent); color: var(--accent); outline: none; }
.select-custom-action.actif { background: var(--accent-doux); border-color: var(--accent); color: var(--accent); }
.select-custom-action:disabled { opacity: .45; cursor: default; }
/* Seule cette zone défile ; `min-height: 0` sans quoi un enfant flex refuse de rétrécir
   sous la hauteur de son contenu et la barre serait poussée hors du panneau. */
.select-custom-liste { overflow-y: auto; min-height: 0; }
/* Hors de la zone qui défile : le titre reste donc visible sans avoir à être collant. */
.select-custom-titre {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  padding: 5px 10px 6px; margin-bottom: 2px;
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--texte-3); white-space: nowrap;
}
.select-custom-compte {
  padding: 0 5px; border-radius: 5px; background: var(--surface-2);
  font-size: .68rem; font-weight: 650; color: var(--texte-3);
}
/* Étroit : les colonnes s'empilent. Côte à côte, chacune tomberait sous la largeur d'un
   libellé et le texte serait tronqué des deux côtés à la fois. */
@media (max-width: 560px) {
  .select-custom-panneau.colonnes .select-custom-grille { grid-template-columns: 1fr; gap: 2px; }
  .select-custom-panneau.colonnes .select-custom-colonne + .select-custom-colonne {
    border-left: 0; padding-left: 0;
  }
}
/* Variante « recherche » : le champ est à la fois la barre de saisie et l'affichage de
   la sélection. L'<input> occupe toute la largeur disponible, le chevron reste à droite. */
.select-custom-combo { cursor: text; }
/* Sélecteurs volontairement lourds : la règle globale `input[type="text"]` (0,1,1) et sa
   variante sombre (0,2,1) donneraient sinon au champ interne sa propre bordure et son
   propre fond — d'où un cadre dans le cadre. Seule l'enveloppe porte la bordure. */
.select-custom .select-custom-champ,
:root[data-theme="dark"] .select-custom .select-custom-champ {
  flex: 1; min-width: 0; width: auto;
  border: 0; background: none; box-shadow: none;
  padding: 0; min-height: 0;
  font: inherit; color: inherit; outline: none;
}
.select-custom .select-custom-champ::placeholder { color: var(--texte-3); }
/* Requête en cours : le chevron tourne doucement, sans bloquer la liste déjà affichée. */
@keyframes select-attente { to { rotate: 360deg; } }
.select-custom.select-chargement .select-custom-bouton > svg { animation: select-attente 1s linear infinite; }
.select-swatch { width: 15px; height: 15px; flex: 0 0 auto; border-radius: 4px; border: 1px solid rgba(0,0,0,.15); }

/* ---------- Champs ---------- */
.champ { display: flex; flex-direction: column; gap: 5px; }
.champ[hidden] { display: none; }
.champ > label { font-size: .86rem; font-weight: 600; color: var(--texte-2); }
input[type="text"], input[type="password"], input[type="number"], input[type="date"],
input[type="search"], input[type="email"], select, textarea {
  font: inherit; color: var(--texte);
  background: #f5faff;
  border: 1px solid #cad3ef;
  border-radius: 9px;
  padding: 8px 12px;
  min-height: 38px;
  /* Halo pilotable : transparent au repos et au focus (seule la bordure change),
     il reste disponible pour signaler une validation ou une erreur. */
  box-shadow: 0 0 0 3px var(--halo-champ, transparent);
  transition: border-color .13s, box-shadow .13s;
  width: 100%;
}
/* Les deux teintes ci-dessus sont claires : en thème sombre on repasse aux jetons. */
:root[data-theme="dark"] input[type="text"], :root[data-theme="dark"] input[type="password"],
:root[data-theme="dark"] input[type="number"], :root[data-theme="dark"] input[type="date"],
:root[data-theme="dark"] input[type="search"], :root[data-theme="dark"] input[type="email"],
:root[data-theme="dark"] select, :root[data-theme="dark"] textarea {
  background: var(--surface);
  border-color: var(--border-fort);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; border-color: var(--accent);
}
textarea { resize: vertical; min-height: 84px; }
select { cursor: pointer; }
/* Champ verrouillé : la valeur reste parfaitement lisible — c'est elle qu'on vient
   consulter — mais le fond neutre et le curseur disent qu'elle ne se change pas. */
input:disabled, textarea:disabled, select:disabled {
  background: var(--surface-2); color: var(--texte-2);
  border-color: var(--border); cursor: not-allowed;
}
input[type="checkbox"]:disabled { cursor: not-allowed; opacity: .55; }
input[type="checkbox"]:disabled + *, label:has(input:disabled) { color: var(--texte-3); cursor: not-allowed; }
.aide-champ { font-size: .8rem; color: var(--texte-3); }

/* Encadré explicatif : un liseré de couleur à gauche plutôt qu'un cadre complet, pour
   qu'il se lise comme une note en marge et non comme une alerte. */
.encadre-info {
  display: flex; gap: 11px; align-items: flex-start;
  margin: 0 0 20px; padding: 13px 16px;
  border: 1px solid var(--border); border-left: 3px solid var(--info);
  border-radius: var(--radius-s); background: var(--info-doux);
}
.encadre-info .encadre-icone { color: var(--info); flex: 0 0 auto; margin-top: 1px; }
.encadre-info b { display: block; margin-bottom: 5px; font-size: .9rem; }
.encadre-info ul { margin: 0; padding-left: 18px; }
.encadre-info li { font-size: .88rem; line-height: 1.55; color: var(--texte-2); }
.encadre-info li + li { margin-top: 3px; }

.interrupteur { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
.interrupteur input { position: absolute; opacity: 0; width: 42px; height: 24px; margin: 0; cursor: pointer; }
.interrupteur .piste {
  width: 42px; height: 24px; border-radius: 12px;
  background: var(--border-fort); position: relative; transition: background .15s; flex-shrink: 0;
}
.interrupteur .piste::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: var(--ombre-1); transition: translate .15s;
}
.interrupteur input:checked + .piste { background: var(--accent); }
.interrupteur input:checked + .piste::after { translate: 18px 0; }
.interrupteur input:focus-visible + .piste { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Cartes & panneaux ---------- */
.carte {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--ombre-1);
  padding: 18px 20px;
  margin-top: 10px;
}
.carte + .carte { margin-top: 16px; }
.carte-titre { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.carte-titre h2, .carte-titre h3 { margin: 0; }
.carte-titre .a-droite { margin-left: auto; display: flex; gap: 8px; align-items: center; }

/* ---------- Choix du jeu de démonstration (administration) ---------- */
/* Deux cartes cliquables plutôt qu'une liste déroulante : le choix engage une
   reconstruction complète de l'environnement, ses conséquences doivent être lisibles
   sans avoir à ouvrir quoi que ce soit. */
.demo-variantes {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px; border: none; padding: 0; margin: 0 0 14px;
}
.demo-variantes legend {
  padding: 0; margin-bottom: 8px;
  font-size: .78rem; font-weight: 650; color: var(--texte-3);
  text-transform: uppercase; letter-spacing: .04em;
}
.demo-variante {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface);
  transition: border-color .12s, background .12s;
}
.demo-variante:hover { border-color: var(--border-fort); }
.demo-variante.actif { border-color: var(--accent); background: var(--accent-doux); }
.demo-variante input { margin-top: 3px; flex: 0 0 auto; accent-color: var(--accent); }
.demo-variante b { display: block; font-size: .92rem; font-weight: 650; }
.demo-variante small { display: block; margin-top: 2px; color: var(--texte-2); font-size: .8rem; line-height: 1.45; }
/* Fiche document : actions sur deux colonnes dans la carte de droite.
   Alignées à gauche pour que les icônes forment deux colonnes lisibles. */
.doc-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.doc-actions .btn {
  width: 100%; min-width: 0;
  /* hauteur libre : sur une colonne étroite, un libellé long passe sur deux lignes
     au lieu de déborder — la grille égalise la hauteur de la rangée. */
  height: auto; min-height: 36px; padding: 7px 11px;
  justify-content: flex-start; text-align: left; line-height: 1.25;
}
.doc-actions .btn > svg { flex: 0 0 auto; }
.doc-actions .btn.actif { border-color: var(--accent); color: var(--accent); background: var(--accent-doux); }
/* Favori actif : ambre plutôt qu'accent, pour coller à l'étoile. Même rendu sur la fiche
   document et dans la barre d'outils de l'explorateur. */
.doc-actions .btn-favori.actif,
.barre-outils .btn-favori.actif { color: #d8792c; background: #fef0d7; border-color: #d7a042; }
:root[data-theme="dark"] .doc-actions .btn-favori.actif,
:root[data-theme="dark"] .barre-outils .btn-favori.actif { color: #f0b45e; background: #3a2b14; border-color: #7a5a22; }
/* Champ non pertinent pour ce type de fichier, révélable à la demande */
.champ-masque { display: none; }

/* ---------- Champ « liste de mots » : chaque entrée validée devient une pastille ---------- */
.champ-mots {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
  min-height: 44px; padding: 6px 9px; cursor: text;
  /* Faux champ de saisie : mêmes teintes que les vrais inputs, sinon il détonne
     au milieu des autres champs du formulaire. */
  background: #f5faff; border: 1px solid #cad3ef; border-radius: 9px;
  box-shadow: 0 0 0 3px var(--halo-champ, transparent);
  transition: border-color .13s, box-shadow .13s;
}
:root[data-theme="dark"] .champ-mots { background: var(--surface); border-color: var(--border-fort); }
.champ-mots:focus-within { border-color: var(--accent); }
/* --teinte est posée en ligne à partir du mot : une couleur stable et propre à chacun. */
.mot-pastille {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  padding: 5px 6px 5px 14px; border-radius: 999px;
  background: hsl(var(--teinte, 250) 85% 92%);
  color: hsl(var(--teinte, 250) 65% 30%);
  font-size: .92rem; font-weight: 650; line-height: 1;
}
/* Hauteur de ligne calée sur celle de la croix : les deux boîtes font 22px et le centrage
   flex les superpose exactement. Mais centrer les boîtes ne centre pas l'encre : le texte
   occupe le haut de sa boîte (hampes hautes, jambages sous la ligne de base restés vides
   sur un mot en minuscules), et paraît donc bas. D'où cette correction optique, exprimée
   en em pour rester juste si la taille de police change. */
.mot-pastille > span {
  line-height: 22px; position: relative; top: -0.07em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mot-x {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; margin-left: 4px; border: 0; border-radius: 50%;
  background: none; color: inherit; cursor: pointer; opacity: .6;
  transition: background .13s, color .13s, opacity .13s;
}
.mot-x:hover, .mot-x:focus-visible { background: hsl(var(--teinte, 250) 60% 42%); color: #fff; opacity: 1; }
/* Variante lien (fiche document) : même pastille, sans croix, donc padding symétrique. */
.mots-liste { display: flex; flex-wrap: wrap; gap: 8px; }
.mot-lien { padding-right: 14px; text-decoration: none; transition: background .13s, color .13s; }
.mot-lien:hover, .mot-lien:focus-visible {
  background: hsl(var(--teinte, 250) 70% 84%); color: hsl(var(--teinte, 250) 70% 24%); text-decoration: none;
}
:root[data-theme="dark"] .mot-lien:hover, :root[data-theme="dark"] .mot-lien:focus-visible {
  background: hsl(var(--teinte, 250) 40% 32%); color: hsl(var(--teinte, 250) 80% 85%);
}
:root[data-theme="dark"] .mot-pastille {
  background: hsl(var(--teinte, 250) 38% 24%);
  color: hsl(var(--teinte, 250) 75% 78%);
}
:root[data-theme="dark"] .mot-x:hover, :root[data-theme="dark"] .mot-x:focus-visible {
  background: hsl(var(--teinte, 250) 60% 58%); color: #10131c;
}
/* La règle globale input[type="text"] (0,1,1) doit être battue, sinon le champ de
   saisie garde sa propre bordure et son padding : d'où le double liseré. */
.champ-mots .champ-mots-saisie {
  flex: 1 1 110px; min-width: 90px; width: auto;
  padding: 4px 2px; min-height: 0;
  border: 0; border-radius: 0; outline: none; background: none; box-shadow: none;
  font: inherit; font-size: .92rem; color: var(--texte);
}
.meta-liste {
  display: grid; grid-template-columns: minmax(120px, 170px) minmax(0, 1fr);
  gap: 9px 16px; margin: 0;
}
.meta-liste dt { color: var(--texte-3); font-size: .82rem; font-weight: 650; }
.meta-liste dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.grille { display: grid; gap: 16px; }
.grille-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grille-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grille-4 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* Tuiles de stats */
.tuile-stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px 18px;
  display: flex; flex-direction: column; gap: 2px;
}
.tuile-stat .valeur { font-size: 1.7rem; font-weight: 750; letter-spacing: -.02em; }
.tuile-stat .libelle { font-size: .84rem; color: var(--texte-2); }
.tuile-stat .detail { font-size: .78rem; color: var(--texte-3); }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .76rem; font-weight: 650;
  padding: 2px 9px; border-radius: 20px;
  background: var(--surface-3); color: var(--texte-2);
  white-space: nowrap;
}
.badge-ok { background: var(--ok-doux); color: var(--ok); }
.badge-attention { background: var(--attention-doux); color: var(--attention); }
.badge-danger { background: var(--danger-doux); color: var(--danger); }
.badge-info { background: var(--info-doux); color: var(--info); }
.badge-accent { background: var(--accent-doux); color: var(--accent); }
.badge-nb {
  background: #ffffff; color: #4f43f1;
  font-size: .72rem; font-weight: 650; border-radius: 12px; padding: 1px 8px;
}
.pastille-notif {
  position: absolute; top: 4px; right: 4px;
  min-width: 16px; height: 16px; border-radius: 8px;
  background: var(--danger); color: #fff;
  font-size: .64rem; font-weight: 700;
  display: grid; place-items: center; padding: 0 4px;
}

/* ---------- Tableaux ---------- */
.tableau-enveloppe { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
table.tableau { width: 100%; border-collapse: collapse; font-size: .92rem; }
.tableau th {
  text-align: left; font-size: .78rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texte-3); font-weight: 650;
  padding: 10px 14px; border-bottom: 1px solid var(--border);
  background: var(--surface-2); white-space: nowrap;
  position: sticky; top: 0;
}
.tableau td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tableau tbody tr:last-child td { border-bottom: none; }
.tableau tbody tr { transition: background .1s; }
.tableau tbody tr:hover { background: var(--surface-2); }
.tableau tbody tr.selectionne { background: var(--accent-doux); }
.tableau .tri-btn { background: none; border: none; font: inherit; color: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; padding: 0; text-transform: inherit; letter-spacing: inherit; font-weight: inherit; }

/* ---------- Explorateur : liste & grille ---------- */
.fil-ariane {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-bottom: 14px; padding: 5px; border-radius: 5px;
  background-color: #d7edfe; font-size: 1.05rem; line-height: 1.2;
}
.fil-ariane > a, .fil-ariane > .courant, .fil-ariane > .separateur {
  display: inline-flex; align-items: center; min-height: 32px;
}
.fil-ariane a { color: var(--texte-2); padding: 5px 8px; border-radius: 6px; }
/* Fond blanc en thème clair (var(--surface) = #ffffff), assombri en thème sombre. */
.fil-ariane > a { background-color: var(--surface); }
.fil-ariane > a:first-child {
  gap: 10px;
  text-decoration: none;
  color: #6296ea;
  font-style: italic;
}
.fil-ariane > a > svg { color: #539bf9; }
.fil-ariane .racine-libelle { position: relative; top: 1px; color: #3e76d0; font-size: 15px; font-weight: 600; }
.fil-ariane a > span { display: inline-flex; align-items: center; }
.fil-ariane a:hover { background: #bfe0fd; text-decoration: none; color: #2f6fd0; }
.fil-ariane > a:first-child:hover { color: #2f6fd0; }
.fil-ariane > a:hover > svg,
.fil-ariane > a:hover > .racine-libelle { color: #2f6fd0; }
.fil-ariane .separateur { color: var(--texte-3); }
.fil-ariane .courant { gap: 7px; font-weight: 500; padding: 5px 8px; }
.fil-ariane svg { display: block; flex: 0 0 auto; width: 20px; height: 20px; }
.fil-ariane .badge-nb { display: inline-flex; align-items: center; min-height: 22px; font-size: .82rem; line-height: 1; }
.fil-ariane .courant .badge-nb { margin-left: 10px; }
:root[data-theme="dark"] .fil-ariane { background-color: #262e49; }
:root[data-theme="dark"] .fil-ariane .racine-libelle { color: #b4bee3; }
:root[data-theme="dark"] .fil-ariane a:hover { background: var(--surface-3); color: var(--texte); }
:root[data-theme="dark"] .fil-ariane > a:hover > svg,
:root[data-theme="dark"] .fil-ariane > a:hover > .racine-libelle { color: #8ab8f5; }

.barre-outils {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.barre-outils .a-droite { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* Vignettes des filtres appliqués, entre la barre d'outils et le contenu. Vides, elles
   n'occupent aucune place : le conteneur est masqué plutôt que laissé à zéro, pour ne pas
   ajouter d'espace au-dessus du contenu quand aucun filtre n'est posé. */
.filtres-actifs { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0 30px; }
.filtres-actifs[hidden] { display: none; }
.puce-filtre {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 4px 4px 11px; border-radius: 999px;
  background: var(--accent-doux); border: 1px solid var(--accent);
  font-size: .84rem; font-weight: 600; color: var(--accent); max-width: 100%;
}
.puce-pastille { width: 12px; height: 12px; flex: 0 0 auto; border-radius: 4px; border: 1px solid rgba(0,0,0,.15); }
.puce-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* La croix reste ronde et de taille constante quel que soit le libellé : c'est la cible du
   clic, elle ne doit pas rétrécir avec un texte long. */
.puce-x {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: inherit; cursor: pointer;
  transition: background .13s ease;
}
.puce-x:hover, .puce-x:focus-visible { background: var(--accent); color: var(--surface); outline: none; }
/* « Tout effacer » : une vignette sobre, pour ne pas peser autant qu'un filtre réel. */
.puce-tout {
  padding: 4px 12px; cursor: pointer; font-family: inherit;
  background: var(--surface-2); border-color: var(--border-fort); color: var(--texte-2);
}
.puce-tout:hover, .puce-tout:focus-visible { border-color: var(--accent); color: var(--accent); outline: none; }

.vue-grille {
  display: grid; gap: 12px;
  /* 200 px au minimum par tuile : en deçà, le nom et les étiquettes se serrent trop.
     `auto-fill` ajuste le nombre de colonnes à la largeur disponible. */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.tuile-item {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px;
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  cursor: pointer; text-align: center; position: relative;
  transition: border-color .13s, box-shadow .13s, translate .13s;
  color: var(--texte); text-decoration: none;
}
.tuile-item:hover { border-color: var(--accent); box-shadow: var(--ombre-2); translate: 0 -2px; text-decoration: none; }
/* Un clic sélectionne, un double-clic ouvre : pas de sélection de texte parasite */
.tuile-item, .ligne-item, .tableau tbody tr { user-select: none; }
/* Marqueurs : favori en haut à droite (la case de sélection occupe le coin gauche),
   pastilles de catégorie sous le nom. */
.marque-favori {
  display: inline-flex; align-items: center; justify-content: center;
  color: #d8792c; flex: 0 0 auto;
}
/* Groupe ancré en haut à droite : le doublon se pose à gauche du favori, et se
   recale seul contre le bord quand l'élément n'est pas en favori. */
.marques-tuile {
  position: absolute; top: 8px; right: 8px; z-index: 1;
  display: flex; align-items: center; gap: 6px;
}
.marques-tuile .marque-favori {
  width: 24px; height: 24px; border-radius: 50%;
  background: #fef0d7; box-shadow: 0 1px 3px rgb(10 12 24 / .18);
}
/* min-height plutôt que height : suit le réglage de taille d'interface sans être écrasé. */
.badge-doublon {
  min-height: 24px; padding: 0 10px;
  font-size: .66rem; box-shadow: 0 1px 3px rgb(10 12 24 / .18);
}
.ligne-item .marque-favori { margin-right: 5px; vertical-align: -2px; }
/* Pastille de couleur d'une catégorie — utilisée dans la popup « Catégories ». */
.pastille-cat {
  flex: 0 0 auto; display: inline-block;
  width: 13px; height: 13px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .14);
}

/* Catégorie sans étiquette rattachée : un simple contour. Un aplat gris se lisait comme
   une couleur choisie, alors qu'il signalait justement son absence. */
.pastille-cat-vide {
  background: transparent; box-shadow: none;
  border: 1px dashed var(--border-fort);
}

/* Étiquettes de catégorie sous le nom de la tuile, centrées */
/* align-self: stretch — la tuile est en align-items:center, sans ça le bloc
   resterait à la largeur de son texte au lieu de prendre toute la carte. */
/* margin-top:auto — plaquée en bas de la tuile, comme le bouton « Liaisons » : elle ne
   flotte donc plus selon la longueur du nom, et les étiquettes s'alignent d'une carte
   à l'autre. La marge automatique passe ici : deux `auto` se partageraient l'espace. */
/* C'est un <button> (il ouvre la modale de catégories) : on lui retire tout l'habillage
   natif pour qu'il reste la simple ligne d'étiquettes qu'il était. */
.cats-etiquettes {
  display: flex; flex-direction: column; gap: 4px;
  align-self: stretch; min-width: 0; margin-top: auto;
  padding: 0; border: 0; background: none; color: inherit; font: inherit;
  cursor: pointer; text-align: inherit;
}
.cats-etiquettes:hover .cat-etiquette { filter: brightness(.96); }
.cats-etiquettes:hover .cat-etiquette-defaut { opacity: 1; }
.cats-etiquettes:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.tuile-item .liaison-voir { margin-top: 0; }
.cat-etiquette {
  justify-content: center; text-align: center; padding: 3px 9px;
  font-size: .73rem; font-weight: 500; letter-spacing: normal;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  /* Fond transparent. Liseré et texte neutres par défaut ; ils prennent la couleur de la
     carte dès que celle-ci en a une (règle ci-dessous). */
  background: transparent; border: 1px solid var(--border-fort); color: var(--texte-2);
}
/* Le badge prend la couleur de la carte qui le contient, avec un plancher de contraste.
   Le mélange se fait vers `--texte` — presque noir en thème clair, presque blanc en
   sombre — donc la correction s'inverse d'elle-même selon le thème, sans règle dédiée.
   Mélanger vers `--border` comme le fait la carte donnait un texte illisible sur les
   nuances pâles : un liseré peut être ténu, un libellé doit se lire.

   Les proportions sont mesurées sur les 71 teintes de la palette, dans les deux thèmes :
   40 % pour le texte garantit au minimum 4,59 (seuil AA : 4,5), 50 % pour le liseré au
   minimum 3,36 (seuil composants : 3,0). La condition porte sur la présence de
   `--c-carte`, comme pour la carte — une variable non définie ne peut pas servir de test
   dans `color-mix`. */
.tuile-item[style*="--c-carte"] .cat-etiquette {
  border-color: color-mix(in srgb, var(--c-carte) 50%, var(--texte));
  color: color-mix(in srgb, var(--c-carte) 40%, var(--texte));
}

/* « Sans catégorie » : blanc sur fond clair, noir sur fond sombre. Le liseré est
   indispensable — sans lui, le blanc disparaîtrait sur la tuile, elle aussi blanche. */
.cat-etiquette-defaut {
  background: #ffffff; color: #111827; box-shadow: inset 0 0 0 1px var(--border-fort);
  opacity: .5; /* un élément non classé s'efface derrière ceux qui le sont */
}
:root[data-theme="dark"] .cat-etiquette-defaut {
  background: #111827; color: #ffffff; box-shadow: inset 0 0 0 1px var(--border-fort);
}
:root[data-theme="dark"] .marques-tuile .marque-favori { background: #3a2b14; color: #f0b45e; }
:root[data-theme="dark"] .ligne-item .marque-favori { color: #f0b45e; }

.tuile-item.selectionne {
  border-color: var(--accent);
  background: var(--accent-doux);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
/* Carte colorée (fichier ou dossier) : bandeau haut + bordure teintée, visible même sur une miniature */
.tuile-item[style*="--c-carte"] {
  border-color: color-mix(in srgb, var(--c-carte) 55%, var(--border));
  background: color-mix(in srgb, var(--c-carte) 6%, var(--surface));
  overflow: hidden;
}
.tuile-item[style*="--c-carte"]::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 5px;
  background: var(--c-carte); pointer-events: none;
}
.tuile-item .apercu {
  width: 100%; aspect-ratio: 4/3; border-radius: var(--radius-s);
  background: var(--surface-2);
  display: grid; place-items: center; overflow: hidden;
}
.tuile-item .apercu img { width: 100%; height: 100%; object-fit: cover; }
.tuile-item .nom {
  font-size: .86rem; font-weight: 550; line-height: 1.3;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical;
  word-break: break-word;
}
/* Infobulle applicative : remplace celle du navigateur pour tout `title`. Position
   calculée en JS, d'où le `position: fixed` sans ancrage propre. Non cliquable, pour
   ne jamais s'interposer entre le curseur et l'élément décrit. Les couleurs sont
   surchargeables par l'admin (élément « Infobulle » de Style et paramètres). */
.infobulle {
  position: fixed; z-index: 500; pointer-events: none;
  /* `max-content` garde le texte sur une seule ligne tant qu'il tient ; au-delà, la
     largeur est bornée et le texte passe à la ligne de lui-même. */
  width: max-content; max-width: min(460px, 84vw); padding: 8px 12px;
  background: var(--accent); color: var(--accent-texte);
  border-radius: 8px; box-shadow: var(--ombre-2);
  /* Interligne serré : au-delà, la boîte de ligne dépasse les glyphes et le texte
     paraît collé vers le bas de la bulle au lieu d'être centré entre ses paddings. */
  font-size: .88rem; line-height: 1.25; text-align: left;
  overflow-wrap: anywhere;
  opacity: 0; translate: 0 4px;
  /* Sortie : nette et plus rapide que l'entrée. La transition est portée par l'état de
     repos, celle d'entrée par `.visible` — c'est ce qui permet deux durées distinctes. */
  transition: opacity .09s ease-in, translate .09s ease-in;
}
/* Séparateur de fil d'Ariane à l'intérieur d'une infobulle : pastille ronde à chevron.
   Bleu électrique volontairement plus vif et plus clair que le fond de la bulle (qui est
   déjà l'accent) — un bleu proche s'y fondrait au lieu de s'en détacher. La valeur est
   écrite en dur, ce n'est pas une couleur de thème mais un repère de lecture, identique
   en clair comme en sombre. */
.infobulle .chemin-fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; margin: 0 7px;
  border-radius: 50%; background: #00a3ff; color: #ffffff;
  /* `middle` cale le centre de la pastille sur le centre optique du texte (ligne de base
     + demi-hauteur d'x). Une valeur en pixels y parviendrait pour une taille de police
     donnée et se décalerait dès que l'admin change celle des infobulles. */
  vertical-align: middle;
  /* Remontée d'1 px : `middle` est juste géométriquement, mais un disque plein paraît
     bas à côté de minuscules dont la masse est plus haute. Correction optique, en
     `translate` pour qu'elle ne décale pas la ligne. */
  translate: 0 -1px;
}
.infobulle .chemin-fleche svg { display: block; }
/* Le chevron du jeu d'icônes est tracé pour un canevas de 24 px avec un trait de 2. Rendu
   à 12 px, ce trait ne fait plus que 1 px — d'où un chevron fantomatique, qu'on prend pour
   une opacité. On l'épaissit dans le repère du canevas : 3,6 donne 1,8 px à l'écran. */
.infobulle .chemin-fleche svg path { stroke-width: 3.6; stroke: #ffffff; }

.infobulle.dessous { translate: 0 -4px; }
.infobulle.visible {
  opacity: 1; translate: none;
  transition: opacity .13s ease-out, translate .13s ease-out;
}
/* Option réglable par l'admin, par élément : l'apparition rebondit deux fois. Le
   `translate` reste piloté par le positionnement, seul l'échelle bouge. */
.infobulle.rebond.visible { animation: infobulle-rebond .44s cubic-bezier(.3, .7, .4, 1); }
@keyframes infobulle-rebond {
  0%   { scale: .82; }
  35%  { scale: 1.06; }
  55%  { scale: 1; }
  75%  { scale: 1.025; }
  100% { scale: 1; }
}
/* Cases à cocher en ligne des formulaires de réglage. */
.case-ligne { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: .9rem; cursor: pointer; }

/* Fil d'Ariane du DOM (« Modifier l'infobulle ») : du parent le plus large à l'élément
   cliqué. Il défile horizontalement plutôt que de casser la lecture du chemin. */
.ib-fil {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  padding: 8px; border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface-2);
}
.ib-fil-item {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid transparent; border-radius: 7px; background: none;
  padding: 4px 8px; font: inherit; cursor: pointer; color: var(--texte-2);
}
.ib-fil-item code { font-size: .78rem; }
.ib-fil-item .badge { color: #3346bb; background: #ccd3ff; }
.ib-fil-item:hover { background: var(--surface); border-color: var(--border); }
.ib-fil-item.actif { background: var(--accent-doux); border-color: var(--accent); color: var(--accent); }
.ib-fil-sep { color: var(--texte-3); font-size: .8rem; }
/* Repère des niveaux qui portent réellement une infobulle : c'est le seul qui compte. */
.ib-pastille {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: 0 0 auto;
}

.tuile-item .infos { font-size: .74rem; color: var(--texte-3); }
.tuile-item input[type="checkbox"] { position: absolute; top: 8px; left: 8px; width: 26px; height: 26px; accent-color: var(--accent); }

.icone-fichier {
  width: 40px; height: 40px; border-radius: 10px;
  display: grid; place-items: center; flex-shrink: 0;
  font-size: .68rem; font-weight: 750; letter-spacing: .02em;
}
.icone-fichier svg { width: 22px; height: 22px; }
.if-pdf { background: #fde5e5; color: #c0392b; }
.if-image { background: #e5f2fd; color: #2471a3; }
.if-document { background: #e3ecfb; color: #2456a6; }
.if-tableur { background: #e2f4e8; color: #1e8449; }
.if-presentation { background: #fdeee0; color: #ca6f1e; }
.if-video { background: #f2e5fd; color: #7d3c98; }
.if-audio { background: #fdf2e0; color: #b7950b; }
.if-archive { background: #efe9e2; color: #7d6608; }
.if-texte, .if-code { background: var(--surface-3); color: var(--texte-2); }
.if-autre, .if-email { background: var(--surface-3); color: var(--texte-2); }
:root[data-theme="dark"] .if-pdf { background: #3a2020; color: #f1948a; }
:root[data-theme="dark"] .if-image { background: #1c2f40; color: #85c1e9; }
:root[data-theme="dark"] .if-document { background: #1d2a44; color: #7fa8e8; }
:root[data-theme="dark"] .if-tableur { background: #1a3324; color: #7dcea0; }
:root[data-theme="dark"] .if-presentation { background: #3b2a1a; color: #eb984e; }
:root[data-theme="dark"] .if-video { background: #2e1d3a; color: #c39bd3; }
:root[data-theme="dark"] .if-audio { background: #38301a; color: #f4d03f; }
:root[data-theme="dark"] .if-archive { background: #32302a; color: #d4c37a; }

.ligne-item { display: flex; align-items: center; gap: 12px; min-width: 0; }
.ligne-item .textes { min-width: 0; flex: 1; }
.ligne-item .nom { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; color: var(--texte); }
.ligne-item .sous { font-size: .78rem; color: var(--texte-3); }

/* Barre d'actions groupées */
/* Ancrée au bas de la fenêtre, pas au bas du contenu : en `sticky` elle restait dans le
   flux et se retrouvait collée sous une liste courte, au milieu de l'écran. Les bords
   suivent la colonne principale (largeur de la barre latérale + son padding). */
.barre-selection {
  position: fixed; z-index: 50;
  left: calc(var(--sidebar-l) + 26px); right: 26px; bottom: 18px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border-fort);
  border-radius: var(--radius-l); box-shadow: var(--ombre-3);
  padding: 10px 16px;
}

/* ---------- Modales & tiroirs ---------- */
.voile {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(10, 12, 24, .55);
  display: grid; place-items: center; padding: 20px;
  backdrop-filter: blur(2px);
}
.modale {
  background: var(--surface); border-radius: var(--radius-l);
  box-shadow: var(--ombre-3);
  width: 100%; max-width: 520px; max-height: 90vh;
  display: flex; flex-direction: column;
  animation: modale-in .18s ease-out;
}
.modale.large { max-width: 980px; }
@keyframes modale-in { from { opacity: 0; translate: 0 10px; } }
.modale-tete { display: flex; align-items: center; gap: 10px; padding: 16px 20px 0; }
.modale-tete h2 { margin: 0; font-size: 1.1rem; flex: 1; }
.modale-corps { padding: 14px 20px; overflow-y: auto; }
.modale-pied { display: flex; justify-content: flex-end; gap: 10px; padding: 0 20px 18px; }

/* Visionneuse de fichier */
.visionneuse { width: 100%; height: min(72vh, 760px); border: none; border-radius: var(--radius-s); background: var(--surface-2); }
.visionneuse-img { max-width: 100%; max-height: 72vh; object-fit: contain; border-radius: var(--radius-s); display: block; margin: 0 auto; }

/* ---------- Toasts ---------- */
.zone-toasts {
  position: fixed; bottom: 20px; right: 20px; z-index: 400;
  display: flex; flex-direction: column; gap: 10px; max-width: 380px;
}
.toast {
  background: var(--surface); border: 1px solid var(--border-fort);
  border-radius: var(--radius); box-shadow: var(--ombre-2);
  padding: 12px 16px; display: flex; gap: 10px; align-items: flex-start;
  animation: toast-in .2s ease-out;
}
@keyframes toast-in { from { opacity: 0; translate: 20px 0; } }
.toast.ok { border-left: 4px solid var(--ok); }
.toast.erreur { border-left: 4px solid var(--danger); }
.toast.info { border-left: 4px solid var(--info); }

/* ---------- Menu contextuel (clic droit) ---------- */
.menu-contextuel {
  position: fixed; z-index: 450; min-width: 214px;
  background: var(--surface); border: 1px solid var(--border-fort);
  border-radius: var(--radius); box-shadow: var(--ombre-3);
  padding: 6px; user-select: none;
  opacity: 0; transform: scale(.97); transform-origin: top left;
  transition: opacity .1s ease-out, transform .1s ease-out;
}
.menu-contextuel.ouvert { opacity: 1; transform: scale(1); }
.menu-ctx-item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 8px 10px; border: none; border-radius: 8px; background: none;
  font: inherit; font-size: .88rem; color: var(--texte); text-align: left; cursor: pointer;
}
.menu-ctx-item:hover { background: var(--accent-doux); color: var(--accent); }
.menu-ctx-item.danger:hover { background: var(--danger-doux); color: var(--danger); }
.menu-ctx-ico { display: inline-flex; flex: 0 0 auto; width: 16px; color: var(--texte-3); }
.menu-ctx-item:hover .menu-ctx-ico { color: inherit; }
.menu-ctx-label { flex: 1; white-space: nowrap; }
.menu-ctx-kbd { flex: 0 0 auto; font-size: .74rem; color: var(--texte-3); letter-spacing: .02em; }
.menu-ctx-item.desactive {
  color: var(--texte-3); font-style: italic; cursor: default; opacity: .65;
}
.menu-ctx-item.desactive:hover { background: none; color: var(--texte-3); }
.menu-ctx-item.desactive .menu-ctx-ico,
.menu-ctx-item.desactive .menu-ctx-kbd { color: var(--texte-3); }
.menu-ctx-sep { height: 1px; margin: 5px 8px; background: var(--border); }

/* Popup Catégories */
.liste-categories { display: flex; flex-wrap: wrap; gap: 8px 14px; }
/* --c-cat : couleur de la catégorie, posée en style inline par la modale. Diluée dans
   la transparence, elle teinte la pastille sans nuire à la lisibilité du texte, et
   fonctionne telle quelle sur fond clair comme sombre. */
.case-categorie {
  display: inline-flex; align-items: center; gap: 7px; font-size: .9rem;
  padding: 5px 10px; border: 1px solid var(--border); border-radius: 16px; cursor: pointer;
  background: color-mix(in srgb, var(--c-cat, transparent) 10%, transparent);
  border-color: color-mix(in srgb, var(--c-cat, var(--border)) 50%, var(--border));
}
.case-categorie:hover { border-color: var(--accent); }
/* Limite de catégories atteinte : la case reste lisible mais visiblement hors d'atteinte. */
.case-bloquee { opacity: .45; cursor: not-allowed; }
.case-bloquee:hover { border-color: var(--border); }
/* Cochée : le fond se densifie, la sélection se voit sans dépendre de la seule case. */
.case-categorie:has(input:checked) {
  background: color-mix(in srgb, var(--c-cat, transparent) 30%, transparent);
}
.case-categorie input { accent-color: var(--accent); }
/* Ligne : la case cliquable, puis les commandes réservées à l'admin. */
.ligne-categorie { display: inline-flex; align-items: center; gap: 4px; }
.ligne-categorie .cat-suppr { width: 26px; height: 26px; border-radius: 7px; color: var(--texte-3); }
.ligne-categorie .cat-suppr:hover { color: var(--danger); background: var(--danger-doux); }

/* Popup Couleur — palette prédéfinie */
/* Deux colonnes : la palette à gauche, tout ce qui se règle à droite. Le choix d'une
   couleur et la lecture de son effet se font alors d'un seul regard, sans faire défiler. */
/* Trois colonnes dans un rapport 50 / 20 / 30. En `fr` et non en pourcentages : les
   `fr` se partagent l'espace restant APRÈS les gouttières, là où trois pourcentages
   totalisant 100 % déborderaient de la largeur exactement de ces gouttières. */
.couleur-agencement {
  display: grid;
  grid-template-columns: minmax(0, 50fr) minmax(0, 20fr) minmax(0, 30fr);
  gap: 20px; align-items: stretch;
}
/* Fenêtre élargie pour ce seul dialogue : à 980 px, 30 % ne suffisait pas à la palette
   (douze colonnes de pastilles) et elle se serait écrasée. */
.modale:has(.couleur-agencement) { max-width: 1220px; }
@media (max-width: 980px) {
  /* Palette au-dessus, les deux colonnes de réglage côte à côte en dessous. */
  .couleur-agencement { grid-template-columns: minmax(170px, 1fr) minmax(250px, 1.15fr); }
  .couleur-colonne-palette { grid-column: 1 / -1; }
}
@media (max-width: 720px) { .couleur-agencement { grid-template-columns: 1fr; } }
.couleur-colonne-reglages > *:first-child { margin-top: 0; }
/* L'aperçu occupe toute la hauteur laissée par la colonne : c'est lui qu'on regarde en
   choisissant une couleur, une vignette de 76 px n'en montrait presque rien. */
.couleur-colonne-apercu { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* L'aperçu occupe seul sa colonne, sur toute la hauteur. */
.couleur-colonne-apercu .apercu-couleur { flex: 1; min-height: 190px; align-items: stretch; }
.couleur-colonne-reglages .champ-etiquette { margin-top: 0; }
/* Aperçu : une tuile réelle, dans une grille d'une seule colonne. Rien n'y est
   cliquable — c'est une démonstration, pas un raccourci vers un dossier. */
/* La colonne fait 171 px : la grille de l'explorateur impose 200 px minimum par tuile,
   ce qui la ferait déborder. On force donc une colonne à la largeur disponible. */
.apercu-grille { grid-template-columns: minmax(0, 1fr); align-content: start; width: 100%; }
.apercu-grille .tuile-item { pointer-events: none; cursor: default; }
.couleur-colonne-reglages { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* Sous la palette : le bouton s'aligne sur sa largeur, il n'a plus besoin de se
   contracter comme dans la colonne étroite d'où il vient. Deux lignes empilées — l'action
   d'abord, sa portée en dessous : un bouton doit dire ce qu'il fait avant d'expliquer sur
   quoi, et la portée est ici la seule chose qui prête à confusion. */
.couleur-colonne-palette #coul-def-global {
  flex-direction: column; gap: 2px;
  height: auto; white-space: normal; text-align: center; line-height: 1.3; padding: 9px 12px;
}
.couleur-colonne-palette #coul-def-global small {
  font-size: .76rem; font-weight: 400; opacity: .75;
}
/* La carte de rattachement prend le reste de la colonne, son filet supérieur n'a plus
   lieu d'être : elle n'est plus dans le flux du bloc précédent. */
.couleur-colonne-reglages .lien-categorie { margin-top: 0; padding-top: 0; border-top: none; }

/* Une famille de couleurs par colonne, ses nuances empilées : `column` remplit la
   première colonne avant de passer à la suivante, ce que fait justement le tableau
   aplati (rouge complet, puis orange, etc.). */
.palette-couleurs {
  display: grid; grid-auto-flow: column;
  /* Le nombre de lignes suit celui des nuances : il est posé en style inline par le
     script, car `repeat()` n'accepte pas une variable CSS comme compteur. */
  /* Colonnes en `1fr` plutôt qu'en pixels : les pastilles occupent toute la largeur
     accordée à la colonne, quelle qu'elle soit, et restent carrées par `aspect-ratio`. */
  grid-auto-columns: 1fr; gap: 8px;
}
/* Douze colonnes : onze familles, puis les neutres. Cinq neutres et le carré barré font
   six cases, autant que les nuances d'une famille — la grille est donc rectangulaire.
   Un léger retrait à droite évite que les pastilles ne touchent la colonne suivante. */
.couleur-colonne-palette { display: flex; flex-direction: column; gap: 14px; padding-right: 8px; }
/* Carré barré : une diagonale rouge sur damier clair, la convention pour « rien ». */
.pastille-defaut {
  background:
    linear-gradient(to top right, transparent calc(50% - 1px), var(--danger) calc(50% - 1px),
      var(--danger) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--surface);
}
.pastille-choix {
  position: relative;
  width: 100%; aspect-ratio: 1; border: 1px solid rgba(0, 0, 0, .12);
  border-radius: 5px; cursor: pointer; padding: 0;
  transition: transform .1s, box-shadow .1s;
}
.pastille-choix:hover { transform: scale(1.12); }
.pastille-choix.actif {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);
}
/* Coche sur la pastille retenue. Le liseré seul suffisait mal : sur une palette dense,
   il se confond avec l'écart entre deux pastilles. La coche est posée dans une pastille
   pleine — un trait blanc à même la couleur disparaîtrait sur les teintes claires. */
.pastille-choix.actif::after {
  content: ''; position: absolute; top: 3px; right: 3px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 13l4 4 10-10' fill='none' stroke='white' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 9px 9px no-repeat;
  box-shadow: 0 0 0 1.5px var(--surface);
}

/* Libellé au-dessus du champ, comme partout ailleurs dans l'application : le seul
   texte d'invite disparaissait dès la première frappe, or c'est justement à ce
   moment-là qu'on peut douter de ce qu'on est en train de nommer. */
.champ-etiquette { margin-top: 14px; margin-bottom: 22px; }
.champ-etiquette .btn { height: auto; align-self: stretch; }
/* Le nom affiché n'est pas encore celui de la couleur sélectionnée : annoncer ce que
   « Appliquer » va en faire. En accent plutôt qu'en gris d'aide — c'est une conséquence
   du prochain clic, pas une explication de plus. */
.etiquette-attente { margin: 0; color: var(--accent); }
.apercu-couleur { display: flex; }
.apercu-couleur > * { flex: 1; }
/* Confirmation « couleur par défaut » : aperçu à gauche, explication à droite, mêmes
   proportions que la ligne d'aperçu de la modale couleur. Une colonne si l'écran est étroit. */
.confirme-defaut {
  display: grid; grid-template-columns: 2fr 3fr; gap: 14px; align-items: center;
}
.confirme-defaut-texte { margin: 0; }
/* Seule modale dont les boutons sont centrés : ils prolongent l'aperçu plutôt que de
   clore un formulaire, d'où le repérage par le contenu du corps. */
.modale:has(.confirme-defaut) .modale-pied { justify-content: center; }
@media (max-width: 480px) { .confirme-defaut { grid-template-columns: 1fr; } }
.tuile-apercu-couleur {
  width: 100%; height: 100%; min-height: 76px; border-radius: var(--radius-s);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  border: 1px solid var(--border);
}
.apercu-etiquette {
  max-width: 100%; padding: 0 8px; font-size: .76rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pied-couleur {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
}
/* Une seule action désormais : « Remettre par défaut » faisait doublon avec le carré
   barré de la palette, qui exprime le même choix là où on le prend. */
.pied-couleur-actions { display: flex; gap: 10px; justify-content: flex-end; }
.pied-couleur-actions .btn { min-width: 160px; }

/* Choix « Éditer le style » (menu contextuel admin) */
.choix-style { display: flex; flex-direction: column; gap: 8px; }
.choix-style-item {
  display: flex; flex-direction: column; gap: 3px; align-items: flex-start;
  width: 100%; padding: 10px 12px; text-align: left; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-s);
  font: inherit; color: var(--texte);
  transition: border-color .12s, background .12s;
}
.choix-style-item:hover { border-color: var(--accent); background: var(--accent-doux); }
.choix-style-label { font-weight: 600; display: flex; align-items: center; gap: 8px; }
.choix-style-item code { font-size: .78rem; color: var(--texte-3); background: none; padding: 0; }

/* Inspecteur intégré (menu contextuel admin) */
.inspecteur-selecteur {
  display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
  padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius-s);
}
.inspecteur-selecteur code {
  flex: 1; min-width: 0; background: none; padding: 0; font-size: .82rem;
  overflow-wrap: anywhere; color: var(--accent);
}
.inspecteur-selecteur .btn { flex: 0 0 auto; }
/* Fil d'Ariane cliquable de l'inspecteur (navigation vers les ancêtres) */
.insp-ariane {
  flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  font-family: var(--police-mono); font-size: .82rem;
}
.insp-ariane .insp-sep { color: var(--texte-3); }
.insp-ariane .courant { padding: 2px 6px; color: var(--texte); font-weight: 650; overflow-wrap: anywhere; }
.insp-noeud {
  padding: 2px 6px; border: 0; border-radius: 5px; background: none;
  font: inherit; color: var(--accent); cursor: pointer; overflow-wrap: anywhere;
}
.insp-noeud:hover, .insp-noeud:focus-visible { background: var(--accent-doux); }
/* Segments cliquables dans le sélecteur d'une règle */
.insp-seg {
  padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer;
  text-decoration: underline dotted; text-underline-offset: 2px; overflow-wrap: anywhere;
}
.insp-seg:hover, .insp-seg:focus-visible { background: var(--accent-doux); border-radius: 4px; text-decoration: none; }
.insp-seg-courant { font-weight: 700; }
/* Élément de la page survolé depuis l'inspecteur */
.insp-survol { outline: 2px dashed var(--accent) !important; outline-offset: 2px; }

/* ---------- Inspecteur ancré à droite (façon DevTools) ---------- */
:root { --insp-dock-l: max(340px, 25vw); }
.insp-dock {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 460;
  width: var(--insp-dock-l);
  display: flex; flex-direction: column;
  background: var(--surface); border-left: 1px solid var(--border-fort);
  box-shadow: -8px 0 24px rgba(10, 12, 24, .12);
  animation: insp-dock-in .18s ease-out;
}
@keyframes insp-dock-in { from { opacity: 0; translate: 16px 0; } }
.insp-dock-tete {
  display: flex; align-items: center; gap: 6px;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
}
.insp-dock-tete h2 { margin: 0; flex: 1; font-size: 1rem; }
.insp-dock-corps { flex: 1; min-height: 0; overflow-y: auto; padding: 14px; }
.insp-poignee { position: absolute; left: -3px; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 1; }
.insp-poignee:hover, .insp-poignee.actif { background: var(--accent-doux); }
/* Pipette : sélection d'un élément par survol de la page */
html.insp-pipette *:not(.insp-dock, .insp-dock *) { cursor: crosshair !important; }
html.insp-pipette .insp-dock { user-select: none; }
.insp-pipette-cible {
  outline: 2px solid var(--accent) !important; outline-offset: 1px;
  box-shadow: inset 0 0 0 9999px color-mix(in srgb, var(--accent) 10%, transparent) !important;
}
.insp-astuce {
  position: fixed; top: 14px; left: 50%; translate: -50% 0; z-index: 470;
  pointer-events: none; padding: 8px 16px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border-fort); box-shadow: var(--ombre-2);
  font-size: .82rem; font-weight: 600; color: var(--texte);
}
html.insp-dock-actif .insp-astuce { left: calc((100% - var(--insp-dock-l)) / 2); }
/* La page se replie sur la place restante */
html.insp-dock-actif body { padding-right: var(--insp-dock-l); }
html.insp-dock-actif .voile { right: var(--insp-dock-l); }
html.insp-dock-actif .zone-toasts { right: calc(var(--insp-dock-l) + 20px); }
/* Le panneau monte jusqu'en haut, y compris en mode démo : la bannière est déjà
   raccourcie par la règle ci-dessus, elle reste donc entièrement visible à sa gauche. */
html.insp-dock-actif .banniere-demo { right: var(--insp-dock-l); width: auto; }
/* Compacte l'inspecteur dans le panneau étroit */
.insp-dock .insp-prop { grid-template-columns: minmax(90px, 125px) minmax(0, 1fr); gap: 0 12px; }
.insp-dock .inspecteur-selecteur { flex-wrap: wrap; }
/* Sous 980 px, le panneau se pose par-dessus plutôt que de replier la page */
@media (max-width: 980px) {
  html.insp-dock-actif body { padding-right: 0; }
  html.insp-dock-actif .voile, html.insp-dock-actif .banniere-demo { right: 0; }
  html.insp-dock-actif .zone-toasts { right: 20px; }
  .insp-dock { width: min(92vw, var(--insp-dock-l)); }
}
textarea.inspecteur-html {
  display: block; width: 100%; min-height: 150px; max-height: 320px; resize: vertical;
  margin: 8px 0 0; padding: 10px 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-s);
  font-family: var(--police-mono); font-size: .78rem; line-height: 1.5; color: var(--texte);
  /* Retour à la ligne automatique : `anywhere` casse aussi un attribut style très long,
     qu'un simple pre-wrap laisserait déborder faute d'espace où couper. */
  white-space: pre-wrap; overflow-wrap: anywhere; overflow: auto;
}
.insp-html-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.insp-html-actions .insp-editeur-note { margin: 0; flex: 1 1 160px; }
.inspecteur-html {
  margin: 8px 0 0; max-height: 260px; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-s);
  padding: 10px 12px; font-family: var(--police-mono); font-size: .78rem; white-space: pre-wrap; overflow-wrap: anywhere;
}
.inspecteur-regles { max-width: 100%; }
.insp-regle { min-width: 0; margin-bottom: 8px; border: 1px solid var(--border); border-radius: var(--radius-s); overflow: hidden; }
.insp-regle:last-child { margin-bottom: 0; }
.insp-regle-tete {
  display: flex; align-items: baseline; gap: 8px 10px; justify-content: space-between; flex-wrap: wrap;
  padding: 6px 10px; background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.insp-regle-tete code { flex: 1 1 auto; min-width: 0; background: none; padding: 0; font-size: .8rem; color: var(--accent); overflow-wrap: anywhere; }
.insp-regle-src { flex: 0 0 auto; font-size: .72rem; color: var(--texte-3); overflow-wrap: anywhere; }
.insp-regle-decl {
  margin: 0; padding: 8px 10px; font-family: var(--police-mono);
  font-size: .78rem; line-height: 1.5;
  overflow-wrap: anywhere; word-break: break-word; color: var(--texte-2);
  max-width: 100%;
  display: flex; flex-direction: column; align-items: stretch;
}
/* Une déclaration = une ligne copiable au clic */
.insp-decl {
  margin: 0 -5px; padding: 1px 5px; border: 0; border-radius: 4px;
  background: none; font: inherit; color: inherit; text-align: left;
  cursor: copy; overflow-wrap: anywhere; word-break: break-word;
}
.insp-decl:hover, .insp-decl:focus-visible { background: var(--accent-doux); color: var(--texte); }
/* Propriétés de l'élément : la ligne entière (libellé + valeur) est une seule zone copiable */
.inspecteur-meta { margin: 0; display: flex; flex-direction: column; gap: 2px; }
.insp-prop {
  display: grid; grid-template-columns: minmax(110px, 160px) minmax(0, 1fr);
  gap: 0 16px; align-items: baseline;
  padding: 3px 6px; margin: 0 -6px; border-radius: 5px; cursor: copy;
}
.insp-prop:hover, .insp-prop:focus-visible { background: var(--accent-doux); }
.insp-prop-cle { color: var(--texte-3); font-family: var(--police-mono); font-size: .76rem; font-weight: 650; }
.insp-prop-val { min-width: 0; overflow-wrap: anywhere; }

/* ---------- Édition live : crayon + éditeur inline ---------- */
.insp-ligne { display: flex; align-items: flex-start; gap: 6px; }
.insp-ligne > .insp-decl, .insp-ligne > .insp-prop { flex: 1 1 auto; min-width: 0; margin: 0; }
.insp-crayon {
  flex: 0 0 auto; width: 20px; height: 20px; margin-top: 2px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 5px; background: var(--surface);
  color: var(--texte-3); cursor: pointer; transition: background .13s, color .13s, border-color .13s;
}
.insp-crayon:hover, .insp-crayon.modifie { border-color: var(--accent); color: var(--accent); background: var(--accent-doux); }
.insp-crayon-cale { flex: 0 0 auto; width: 20px; }
.insp-editeur {
  flex: 1 1 auto; min-width: 0; padding: 6px 8px;
  border: 1px solid var(--accent); border-radius: 6px; background: var(--surface-2);
}
.insp-editeur-tete { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.insp-editeur-prop { font-family: var(--police-mono); font-size: .78rem; color: var(--texte-3); }
.insp-editeur-val, .insp-code {
  flex: 1 1 130px; min-width: 0; padding: 3px 6px;
  border: 1px solid var(--border-fort); border-radius: 5px;
  background: var(--surface); color: var(--texte);
  font-family: var(--police-mono); font-size: .78rem;
}
.insp-editeur-val.invalide, .insp-code.invalide { border-color: var(--danger); }
.insp-mini { width: 24px; height: 24px; border-radius: 6px; }
.insp-pastille {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0; cursor: pointer;
  border: 1px solid var(--border-fort); border-radius: 5px;
  background-color: var(--pastille, transparent);
}
.insp-editeur-note { margin: 6px 0 0; font-size: .7rem; line-height: 1.35; color: var(--texte-3); }
.insp-palette { display: none; margin-top: 8px; }
.insp-palette.ouvert { display: block; }
.insp-palette-spectre { display: flex; align-items: center; gap: 8px; }
.insp-spectre {
  flex: 0 0 auto; width: 42px; height: 28px; padding: 2px; cursor: pointer;
  border: 1px solid var(--border-fort); border-radius: 5px; background: var(--surface);
}
/* Curseur d'opacité : dégradé de la teinte courante sur un damier de transparence */
.insp-alpha { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.insp-alpha-libelle { flex: 0 0 auto; font-size: .68rem; font-weight: 700; color: var(--texte-3); text-transform: uppercase; letter-spacing: .05em; }
.insp-alpha-val { flex: 0 0 auto; min-width: 46px; text-align: right; font-family: var(--police-mono); font-size: .72rem; color: var(--texte-2); }
.insp-alpha-curseur {
  flex: 1 1 auto; min-width: 0; height: 16px; margin: 0; padding: 0;
  appearance: none; -webkit-appearance: none; background: none; cursor: pointer;
}
.insp-alpha-curseur::-webkit-slider-runnable-track {
  height: 16px; border: 1px solid var(--border-fort); border-radius: 8px;
  background:
    linear-gradient(90deg, transparent, var(--alpha-teinte, var(--accent))),
    repeating-conic-gradient(rgb(0 0 0 / 0) 0% 25%, rgb(128 128 128 / .28) 0% 50%) 0 0 / 10px 10px;
}
.insp-alpha-curseur::-moz-range-track {
  height: 16px; border: 1px solid var(--border-fort); border-radius: 8px;
  background:
    linear-gradient(90deg, transparent, var(--alpha-teinte, var(--accent))),
    repeating-conic-gradient(rgb(0 0 0 / 0) 0% 25%, rgb(128 128 128 / .28) 0% 50%) 0 0 / 10px 10px;
}
.insp-alpha-curseur::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; width: 14px; height: 14px; margin-top: 0;
  border-radius: 50%; background: var(--surface); border: 2px solid var(--accent);
  box-shadow: 0 1px 3px rgb(10 12 24 / .3); cursor: pointer;
}
.insp-alpha-curseur::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--accent);
  box-shadow: 0 1px 3px rgb(10 12 24 / .3); cursor: pointer;
}
.insp-palette-titre {
  margin: 8px 0 4px; font-size: .68rem; font-weight: 700; color: var(--texte-3);
  text-transform: uppercase; letter-spacing: .05em;
}
.insp-refs { display: flex; flex-wrap: wrap; gap: 4px; }
.insp-ref {
  width: 20px; height: 20px; padding: 0; cursor: pointer;
  border: 1px solid var(--border-fort); border-radius: 4px;
}
.insp-ref:hover, .insp-ref:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.insp-copie-regle { flex: 0 0 auto; align-self: center; width: 26px; height: 26px; border-radius: 6px; }
.insp-regles-tete { display: flex; align-items: center; gap: 10px; margin: 18px 0 8px; }
.insp-regles-tete h3 { margin: 0; flex: 1; font-size: .95rem; }

/* Mise en évidence de la ligne ciblée dans la table de style */
.style-row-cible > td { background: var(--accent-doux) !important; animation: cible-pulse 1.3s ease-out; }
@keyframes cible-pulse { 0%, 40% { background: var(--accent-doux); } 20% { background: color-mix(in srgb, var(--accent) 30%, transparent); } }

/* ---------- Notifications (menu) ---------- */
.menu-deroulant {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 150;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--ombre-2);
  min-width: 320px; max-width: 400px; max-height: 480px; overflow-y: auto;
  padding: 6px;
}
.menu-deroulant .entete-menu {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; font-weight: 650; border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}
.item-notif { padding: 9px 12px; border-radius: 8px; display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.item-notif:hover { background: var(--surface-2); }
.item-notif.non-lu { background: var(--accent-doux); }
.item-notif .quand { font-size: .74rem; color: var(--texte-3); }
.menu-simple { min-width: 210px; }
.menu-simple .item-menu {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; border-radius: 8px; border: none; background: none;
  font: inherit; color: var(--texte); cursor: pointer; text-align: left; text-decoration: none;
}
.menu-simple .item-menu:hover { background: var(--surface-2); text-decoration: none; }

/* ---------- Filtres (recherche avancée) ---------- */
/* Six colonnes fixes, et non un `auto-fit` qui répartit selon le nombre de champs : les
   deux bandes n'en ont pas le même compte (6 et 5), leurs colonnes ne tombaient donc pas
   en face. Les paliers étroits sont des diviseurs de 6, pour que l'alignement tienne à
   toutes les largeurs. `minmax(0, …)` empêche un libellé long d'élargir sa colonne. */
.panneau-filtres {
  display: grid; gap: 12px;
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
@media (max-width: 1250px) { .panneau-filtres { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) { .panneau-filtres { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .panneau-filtres { grid-template-columns: minmax(0, 1fr); } }
/* Le panneau se lit en trois bandes : ce qui identifie le document, puis ce qui le qualifie
   et le chiffre, puis la période. Chaque bande reste une grille responsive à part entière. */
.panneau-classement { margin-top: 12px; }
/* Les dates sur leur propre ligne, juste avant les boutons : encadrer une période est une
   opération à part, et les avoir côte à côte plutôt que dispersées évite d'en inverser les
   bornes. La ligne emprunte la grille commune (`panneau-filtres` dans la vue) : ses quatre
   champs tombent donc sous les quatre premières colonnes des bandes du dessus. */
.panneau-dates { margin-top: 12px; }
.explorateur-recherche[hidden] { display: none !important; }
.btn.recherche-active { border-color: var(--accent); background: var(--accent-doux); color: var(--accent); }
.recherche-principale-ligne input { min-width: 0; flex: 1; }
/* Le champ « Source » posé contre la barre de recherche : largeur fixe, c'est la saisie qui
   prend la place restante. Son <label> est masqué mais présent — l'intitulé de la vignette
   qui annule le filtre en dépend. */
.champ-source { flex: 0 0 auto; width: 170px; }
.champ-source > select { width: 100%; }
.resultats-groupe-titre { margin: 0 0 10px; font-size: 1rem; }

/* ---------- Corbeille : segments de période, groupes, tuiles ---------- */
/* Le filtre de période se cale à droite, juste avant les boutons de vue. Il prend la
   marge automatique, et celle de `.a-droite` qui suit est neutralisée : deux marges
   `auto` se partageraient l'espace et le laisseraient flotter au milieu. */
.barre-outils #filtre-periode,
.barre-outils .select-custom:has(#filtre-periode) { margin-left: auto; }
.barre-outils #filtre-periode ~ .a-droite,
.barre-outils .select-custom:has(#filtre-periode) ~ .a-droite { margin-left: 0; }

/* Titre de page avec un contrôle aligné à droite sur la même ligne. Le titre garde sa
   marge basse, le contrôle s'aligne sur sa ligne de base optique. */
.titre-ligne { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: .5em; }
/* La marge basse passe au conteneur, sinon elle décalerait le titre par rapport au
   contrôle avec lequel il doit s'aligner. */
.titre-ligne > h1 { margin-bottom: 0; }
.titre-ligne > .interrupteur { margin-left: auto; font-size: .88rem; color: var(--texte-2); }

/* Rappel du délai de rétention : posé sur la surface, il se lit comme une note et non
   comme un paragraphe perdu au-dessus de la liste. */
.info-retention {
  background: var(--surface); color: var(--texte-2);
  border-radius: 15px; padding: 12px 18px; margin: 0 0 14px;
  font-size: .88rem; line-height: 1.4; font-style: italic;
  /* Le cadre épouse le texte : un bloc pleine largeur donnerait une grande plage vide
     à droite d'une phrase courte. */
  width: fit-content; max-width: 100%;
}

/* Corbeille scindée : les deux paliers côte à côte, à largeur égale. Le panneau
   d'archive est teinté pour qu'on ne confonde pas les deux à la lecture. Sur écran
   étroit ils s'empilent, chacun reprenant toute la largeur. */
.corbeille-scindee {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start;
}
@media (max-width: 1100px) { .corbeille-scindee { grid-template-columns: 1fr; } }
.colonne-corbeille {
  min-width: 0; padding: 12px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
}
.colonne-corbeille.col-archive { border-color: #e8be82; background: #fffdf8; }
:root[data-theme="dark"] .colonne-corbeille.col-archive { background: var(--surface-2); }
.colonne-corbeille-titre {
  margin: 0 0 10px; font-size: .95rem; font-weight: 650;
  display: flex; align-items: center; gap: 8px;
}
.col-archive .colonne-corbeille-titre { color: #9e6733; }
.colonne-corbeille-vide { margin: 0; padding: 18px 4px; color: var(--texte-3); font-size: .88rem; font-style: italic; }
/* Hauteur d'environ deux périodes : au-delà le corps défile, ce qui garde les deux
   panneaux visibles ensemble quelle que soit la quantité d'éléments. */
/* `padding-right` dégage le contenu de la barre de défilement, `scrollbar-gutter`
   réserve sa place en permanence : la largeur ne saute plus quand elle apparaît. */
.colonne-corbeille-corps {
  /* Plancher de trois lignes : sur un écran peu haut, la valeur relative ne suffirait
     pas et le panneau défilerait dès la première ligne. `max()` garde la hauteur
     souple quand le contenu est court — c'est un plafond, pas une hauteur imposée. */
  max-height: max(280px, 72vh); overflow-y: auto; overscroll-behavior: contain;
  padding-right: 10px; scrollbar-gutter: stable;
}
/* Le titre de période reste visible pendant le défilement de son propre groupe. Le
   fond doit être opaque et reprendre celui du panneau, sinon le contenu défile
   derrière lui. */
.colonne-corbeille-corps .groupe-titre {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface); padding-block: 6px; margin-top: 10px;
}
.col-archive .colonne-corbeille-corps .groupe-titre { background: #fffdf8; }
:root[data-theme="dark"] .col-archive .colonne-corbeille-corps .groupe-titre { background: var(--surface-2); }
.colonne-corbeille .tableau-enveloppe { overflow-x: auto; }

/* Bouton de sélection d'une période entière, dans l'en-tête de groupe. */
.btn-groupe-sel {
  border: 1px solid var(--border); border-radius: 20px; background: var(--surface);
  color: var(--texte-2); font: inherit; font-size: .72rem; padding: 2px 9px;
  cursor: pointer; font-weight: 500; white-space: nowrap;
}
.btn-groupe-sel:hover { border-color: var(--accent); color: var(--accent); }
.btn-groupe-sel[aria-pressed="true"] { background: var(--accent-doux); border-color: var(--accent); color: var(--accent); }

/* Bandeau de la corbeille étendue : orange, comme le badge des éléments archivés —
   c'est un avertissement de portée, pas une erreur, d'où le contraste avec le rouge
   du bandeau « élément supprimé » de la fiche document. */
.bandeau-archive {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px; padding: 11px 15px;
  border: 1px solid #e8be82; border-radius: var(--radius);
  background: #fef5e1; color: #9e6733;
  font-size: .9rem; line-height: 1.35;
  width: fit-content; max-width: 100%;
}
/* `display: flex` ci-dessus l'emporte sur la règle `[hidden]` du navigateur, dont la
   spécificité est nulle : sans cette ligne, l'attribut `hidden` reste sans effet. */
.bandeau-archive[hidden] { display: none; }
.bandeau-archive svg { flex: 0 0 auto; }

/* Archive administrateur : éléments passés le premier délai de rétention, en sursis
   avant destruction. Le liseré orange les sépare des suppressions récentes sans les
   rendre illisibles — ils restent restaurables. */
.tableau tbody tr.est-archive > td:first-child { box-shadow: inset 3px 0 0 var(--attention); }
.tuile-item.est-archive { border-color: var(--attention); }
/* Tuiles du panneau d'archive : liseré ambré discret, assorti au cadre du panneau. */
/* Tuiles de la corbeille : liseré neutre un peu plus chaud que celui de l'explorateur. */
.tuile-item.tuile-corbeille { border: 1px solid #d0c3b3; }
/* Panneau d'archive : le même liseré, teinté d'ambre comme le cadre du panneau. */
.col-archive .tuile-item.tuile-corbeille { border: 1px solid rgb(154 103 0 / 40%); }
/* Échéance : discrète tant qu'elle est lointaine, rouge quand l'élément est sur le
   point de basculer — c'est le moment où il faut décider de le restaurer. */
.infos-echeance { font-style: italic; }
.infos-echeance.urgent { color: var(--danger); font-style: normal; font-weight: 600; }
.badge-archive {
  text-transform: uppercase; letter-spacing: .04em; font-size: .68rem;
  color: #ffffff; background: #ff6d2e;
  margin: 0; padding: 3px 7px; border-radius: 20px;
}

/* Bandeau d'un élément consulté depuis la corbeille : rouge franc, en tête de fiche,
   pour qu'on ne le confonde pas avec un document encore rangé dans l'arborescence. */
.bandeau-corbeille {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 16px; padding: 12px 16px;
  border: 1px solid var(--danger); border-radius: var(--radius);
  background: var(--danger-doux); color: var(--danger);
  font-size: .9rem; line-height: 1.35;
}
.bandeau-corbeille-txt { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1; }
.bandeau-corbeille-txt svg { flex: 0 0 auto; }
.bandeau-corbeille-actions { display: flex; gap: 8px; margin-left: auto; }
.bandeau-corbeille .btn { background: var(--danger); color: #fff; border-color: var(--danger); }
.bandeau-corbeille .btn-secondaire { background: var(--surface); color: var(--danger); }

/* Boutons collés en un seul bloc : le choix est exclusif, la forme le dit. */
.segments { display: inline-flex; border: 1px solid var(--border); border-radius: 9px; overflow: hidden; }
.segments .segment {
  border: none; background: var(--surface); color: var(--texte-2);
  font: inherit; font-size: .84rem; padding: 6px 12px; cursor: pointer;
  border-left: 1px solid var(--border);
}
.segments .segment:first-child { border-left: none; }
.segments .segment:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
/* Actif : italique et couleur d'accent, sans fond plein — le bloc reste discret dans
   la barre d'outils, comme le filtre de période de l'explorateur. */
.segments .segment.actif { color: var(--accent); font-style: italic; font-weight: 600; }
/* Titre de période, en grille comme en liste : même hiérarchie visuelle. */
.groupe-titre {
  margin: 18px 0 10px; font-size: .95rem; font-weight: 650;
  display: flex; align-items: center; gap: 8px;
}
.groupe-titre:first-child { margin-top: 0; }
.tableau .ligne-groupe > th {
  position: sticky; left: 0; background: var(--surface-2);
  font-size: .85rem; font-weight: 650; text-align: left; padding: 8px 10px;
}
/* Une tuile de corbeille ne s'ouvre pas : elle porte ses propres boutons, d'où le
   retrait des affordances de clic héritées de `.tuile-item`. */
/* La vignette reprend telle quelle celle de l'explorateur (`.tuile-item .apercu`) :
   format 4/3 et miniature en `cover`. Seules les actions s'ajoutent, plaquées en bas
   pour que les boutons s'alignent d'une tuile à l'autre. Ils occupent toute la largeur,
   empilés : côte à côte, leurs libellés se tronquaient dans une tuile étroite. */
/* Pastille d'extension dans la vignette d'une tuile : elle y remplace l'aperçu, elle
   doit donc occuper la place plutôt que rester à sa taille de liste. Vaut pour
   l'explorateur comme pour la corbeille. */
.tuile-item .apercu .icone-fichier { width: 50px; height: 50px; border-radius: 12px; font-size: 13px; }
.tuile-item .apercu .icone-fichier svg { width: 28px; height: 28px; }
/* Icône de dossier : elle occupe seule la vignette, d'où une taille supérieure à celle
   d'un symbole enfermé dans une pastille. Réglée ici plutôt qu'à l'appel de `icone()`,
   qui sert aussi la vue liste. */
.tuile-item .apercu > svg { width: 48px; height: 48px; }
.tuile-corbeille .tuile-actions {
  display: flex; flex-direction: column; gap: 6px;
  align-self: stretch; margin-top: auto;
}
.tuile-corbeille .tuile-actions .btn { width: 100%; justify-content: center; }
.puces-filtres { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.puce {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-doux); color: var(--accent);
  border-radius: 16px; padding: 3px 6px 3px 11px;
  font-size: .82rem; font-weight: 600;
}
.puce button {
  border: none; background: none; color: inherit; cursor: pointer;
  width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
  padding: 0; font-size: .9rem;
}
/* Recherches sauvegardées : elles partagent leur ligne avec Rechercher, Réinitialiser et
   Sauvegarder. À 24 px au milieu de boutons de 36 px, elles passaient pour une légende
   plutôt que pour des raccourcis cliquables. La règle est limitée à cette zone : `.puce`
   sert aussi aux mots-clés d'un document et aux listes de l'administration, où la taille
   d'un bouton n'aurait pas de sens. */
#zone-recherches-sauvees .puce {
  height: 36px; padding: 0 5px 0 14px;
  border: 1px solid var(--accent); border-radius: 999px;
  font-size: .92rem; font-family: var(--police-bouton);
}
#zone-recherches-sauvees .puce button { width: 26px; height: 26px; font-size: 1.1rem; }
#zone-recherches-sauvees .puce button:hover { background: var(--accent); color: var(--surface); }
.puce button:hover { background: rgba(0,0,0,.1); }
.puce-couleur {
  position: relative; width: 16px; height: 16px; flex: none;
  display: inline-grid; place-items: center; cursor: pointer;
}
.puce-couleur input[type="color"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; padding: 0; border: 0;
}
.puce-couleur-pastille {
  width: 14px; height: 14px; border-radius: 50%;
  box-sizing: border-box; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.12);
}
.puce-couleur-pastille.vide { border: 1.5px dashed currentColor; opacity: .55; box-shadow: none; }

/* Onglet « Catégories & couleurs » : les trois notions côte à côte plutôt qu'en
   paragraphes empilés — c'est leur indépendance qu'il s'agit de montrer, et trois
   colonnes la disent mieux qu'un texte suivi. */
.classement-explication {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.classement-explication h3 {
  margin: 0 0 6px; font-size: .95rem; color: var(--texte-1);
}
.classement-explication h3 em { font-style: normal; color: var(--accent); }
.classement-explication p { margin: 0; font-size: .86rem; color: var(--texte-2); line-height: 1.5; }
/* Champ de nom dans la palette : à la taille de sa colonne, sans le gabarit d'un
   formulaire — c'est une cellule de tableau qu'on corrige au vol. */
input.cl-nom {
  min-height: 30px; padding: 3px 8px; width: 100%; max-width: 220px;
}
.pastille-statut {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 4px; vertical-align: middle; flex: none;
}

/* ---------- Upload ---------- */
.zone-depot {
  border: 2px dashed var(--border-fort);
  border-radius: var(--radius-l);
  padding: 44px 24px; text-align: center;
  background: var(--surface);
  transition: border-color .15s, background .15s;
  cursor: pointer;
}
.zone-depot.survol, .zone-depot:hover { border-color: var(--accent); background: var(--accent-doux); }
.zone-depot .grande-icone { color: var(--accent); margin-bottom: 8px; }
.barre-progression { height: 8px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.barre-progression > div { height: 100%; background: var(--accent); border-radius: 4px; transition: width .2s; }

/* Tableau benchmark V2 — réservé à l'administrateur principal. */
.bench-entete { display: flex; justify-content: space-between; align-items: center; gap: 20px; border-left: 5px solid var(--accent); }
.bench-entete h2 { margin: 8px 0 4px; }
.bench-entete p { margin: 0; color: var(--texte-2); }
.bench-mode { flex: 0 0 auto; text-align: right; }
.bench-mode > span { display: block; color: var(--texte-3); font-size: .75rem; }
.bench-mode > strong { display: block; color: var(--accent); text-transform: uppercase; font-size: 1.05rem; margin: 3px 0 10px; }
.bench-tuiles { margin-top: 16px; }
.bench-tuiles .valeur { font-size: 1.45rem; }
.bench-avancement { margin-top: 16px; }
.bench-avancement > .barre-progression { height: 11px; margin-bottom: 16px; }
.bench-mini-stats { margin-top: 12px; }
.bench-mini-stats > div { padding: 11px 12px; border-radius: var(--radius-s); background: var(--surface-2); }
.bench-mini-stats span { display: block; color: var(--texte-3); font-size: .76rem; }
.bench-mini-stats strong { display: block; margin-top: 3px; }
.bench-colonnes { margin-top: 16px; align-items: start; }
.bench-colonnes .carte { margin-top: 0; }
.bench-route + .bench-route { margin-top: 15px; }
.bench-route > div:first-child { display: flex; justify-content: space-between; gap: 12px; }
.bench-route > div:first-child span, .bench-route small { color: var(--texte-3); font-size: .75rem; }
.bench-route .barre-progression { margin: 6px 0; }
.bench-raisons { display: flex; flex-wrap: wrap; gap: 8px; }
.bench-raison { display: inline-flex; align-items: center; gap: 8px; padding: 7px 10px; background: var(--surface-2); border-radius: 999px; }
.bench-raison b { color: var(--accent); }
.bench-negatif { color: var(--danger); }
.bench-limites { margin-top: 16px; padding: 14px 18px; border: 1px solid var(--attention); border-radius: var(--radius); background: var(--attention-doux); font-size: .84rem; }
.bench-limites ul { margin: 8px 0 0 18px; color: var(--texte-2); }
.bench-date { margin: 10px 0 0; color: var(--texte-3); font-size: .75rem; text-align: right; }

@media (max-width: 700px) {
  .bench-entete { align-items: stretch; flex-direction: column; }
  .bench-mode { text-align: left; }
}

/* ---------- Fiche document ---------- */
.doc-layout { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 18px; align-items: start; }
.doc-meta dl { display: grid; grid-template-columns: 130px 1fr; gap: 7px 12px; margin: 0; font-size: .92rem; }
.doc-meta dt { color: var(--texte-3); }
.doc-meta dd { margin: 0; word-break: break-word; }
.bloc-ocr {
  background: var(--surface-2); border-radius: var(--radius-s);
  padding: 12px 14px; max-height: 300px; overflow: auto;
  font-size: .86rem; white-space: pre-wrap; font-family: var(--police-mono);
}

/* ---------- Login ---------- */
.page-login {
  min-height: 100vh; display: grid; place-items: center;
  background: linear-gradient(160deg, var(--bg) 0%, var(--accent-doux) 100%);
  padding: 20px;
}
.carte-login {
  width: 100%; max-width: 400px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-l); box-shadow: var(--ombre-2);
  padding: 34px 32px;
}
.carte-login .logo-login { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }

/* ---------- Onglets admin ---------- */
.onglets {
  display: flex; gap: 4px; flex-wrap: wrap;
  border-bottom: 1px solid var(--border); margin-bottom: 20px;
}
.onglet {
  border: none; background: none; font: inherit; font-weight: 600;
  color: var(--texte-2); padding: 10px 14px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.onglet:hover { color: var(--texte); }
.onglet[aria-selected="true"] { color: var(--accent); border-bottom-color: var(--accent); }


/* ---------- Admin : recherche live dans un tableau ---------- */
/* La loupe est posée dans le champ plutôt qu'à côté : la barre se lit alors comme un
   seul objet, et le compteur de résultats tient dans la même boîte. */
.recherche-tableau {
  display: flex; align-items: center; gap: 9px;
  margin: 0 0 12px; padding: 4px 12px 4px 11px;
  border: 1px solid var(--border); border-radius: 22px; background: var(--surface-2);
}
.recherche-tableau:focus-within { border-color: var(--accent); background: var(--surface); }
.recherche-tableau-icone { display: inline-flex; color: var(--texte-3); flex: 0 0 auto; }
.recherche-tableau:focus-within .recherche-tableau-icone { color: var(--accent); }
/* Le champ perd son cadre : c'est l'enveloppe qui le porte. */
.recherche-tableau input[type="search"] {
  flex: 1; min-width: 0; border: none; background: none; padding: 5px 0;
  font: inherit; font-size: .9rem; color: var(--texte); min-height: 0;
}
.recherche-tableau input[type="search"]:focus { outline: none; box-shadow: none; }
.recherche-tableau input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }
.recherche-tableau-compte {
  flex: 0 0 auto; font-size: .78rem; color: var(--texte-3); font-variant-numeric: tabular-nums;
}
.tableau-vide { color: var(--texte-3); font-style: italic; padding: 18px 10px; }

/* ---------- Accès : dossiers, fichiers et catégories ---------- */
.panneau-acces { display: block; }

/* Résumé du groupe choisi : ce que la personne a DÉJÀ. Il justifie que le reste de
   l'écran soit facultatif — on ne règle ici que les exceptions. */
.resume-groupe {
  margin: 0 0 12px; padding: 11px 14px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
  font-size: .85rem; line-height: 1.45;
}
.resume-groupe > div { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 5px; }
.resume-groupe p { margin: 0 0 3px; color: var(--texte-2); }
.resume-groupe p:last-child { margin-bottom: 0; }
.resume-groupe .puce-cap { margin-right: 2px; }

.acces-intro {
  margin: 0 0 12px; padding: 10px 14px;
  border-left: 3px solid var(--accent); border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--accent-doux); font-size: .83rem; line-height: 1.5; color: var(--texte-2);
}
.acces-intro p { margin: 0 0 5px; }
.acces-intro p:last-child { margin-bottom: 0; }
.acces-section-titre {
  margin: 14px 0 6px; font-size: .72rem; font-weight: 650;
  text-transform: uppercase; letter-spacing: .04em; color: var(--texte-3);
}

.acces-resultats {
  list-style: none; margin: 0; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius);
}
/* Coins arrondis portés par les extrémités plutôt que par `overflow: hidden` : celui-ci
   rognait tout ce qui dépasse, infobulle comprise. */
.acces-resultat:first-child .acces-resultat-tete { border-radius: var(--radius) var(--radius) 0 0; }
.acces-resultat:last-child .acces-resultat-tete { border-radius: 0 0 var(--radius) var(--radius); }
.acces-resultats > li:only-child .acces-resultat-tete { border-radius: var(--radius); }
.acces-resultat { border-bottom: 1px solid var(--border); position: relative; }
/* Liste récapitulative : mêmes lignes que les résultats, avec un retrait direct à droite.
   La croix est posée par-dessus la ligne plutôt que dans le bouton qui la déplie — un
   bouton dans un bouton n'est pas du HTML valide, et le clic serait ambigu. */
.acces-etablies .acces-resultat-tete { padding-right: 44px; }
.acces-retrait {
  position: absolute; top: 50%; right: 10px; translate: 0 -50%;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 7px;
  border: 1px solid transparent; background: none; color: var(--texte-3); cursor: pointer;
}
.acces-retrait:hover { border-color: var(--danger); background: var(--danger-doux); color: var(--danger); }
/* Le récapitulatif est détaché du reste : c'est le bilan de ce qui a été décidé, il ne
   doit pas se lire dans la continuité du champ de recherche qui le suit. */
#acces-etablies { margin: 50px 0; }
.acces-aucune-regle {
  margin: 0 0 12px; padding: 10px 14px; border: 1px dashed var(--border);
  border-radius: var(--radius); color: var(--texte-3); font-size: .84rem; font-style: italic;
}
.acces-section-titre .badge-nb { margin-left: 6px; border: 1px solid var(--border); }
.acces-resultat:last-child { border-bottom: none; }
/* Une ligne réglée se repère d'un coup d'œil dans une liste de résultats. */
.acces-resultat.a-regle { background: var(--accent-doux); }
.acces-resultat-tete {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; border: none; background: none; font: inherit;
  text-align: left; cursor: pointer; color: inherit;
}
.acces-resultat-tete:hover { background: var(--surface-2); }
.acces-resultat.a-regle .acces-resultat-tete:hover { background: var(--accent-doux); }
.acces-resultat-icone { flex: 0 0 auto; display: inline-flex; color: var(--texte-3); }
.acces-resultat-txt { flex: 1; min-width: 0; display: grid; }
.acces-resultat-nom { font-size: .89rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acces-resultat-txt small { font-size: .74rem; color: var(--texte-3); }
.acces-resultat-etat { flex: 0 0 auto; font-size: .78rem; }
/* Le chevron pivote quand le réglage est déplié : la ligne dit son propre état. */
.acces-resultat-tete > svg:last-child { flex: 0 0 auto; color: var(--texte-3); transition: transform .18s ease; }
.acces-resultat.ouvert .acces-resultat-tete > svg:last-child { transform: rotate(180deg); }

/* Pastille « Voir le lien » : le chemin complet apparaît au survol. Il s'agit du fil
   d'Ariane dans l'arborescence, pas d'une adresse web — d'où le libellé et l'infobulle
   maison plutôt qu'un `title`, qui tarde et tronque. */
.pastille-chemin {
  position: relative; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border: 1px solid var(--border-fort); border-radius: 20px;
  background: var(--surface); color: var(--texte-3);
  font-size: .72rem; cursor: help; white-space: nowrap;
}
.pastille-chemin:hover, .pastille-chemin:focus-visible { border-color: var(--accent); color: var(--accent); }

/* Réglage déplié sous la ligne. Il tient lieu de fenêtre : on est déjà dans une modale,
   en ouvrir une seconde fermerait la première. */
.acces-regle {
  padding: 12px 14px 14px 42px; background: var(--surface);
  border-top: 1px dashed var(--border);
}
.acces-regle-actuel { margin: 0 0 10px; font-size: .84rem; }
.acces-regle-choix { display: grid; gap: 7px; }
.acces-regle-option {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
}
.acces-regle-option:hover { border-color: var(--accent); }
.acces-regle-option.actif { border-color: var(--accent); background: var(--accent-doux); }
.acces-regle-option input { margin-top: 3px; flex: 0 0 auto; }
.acces-regle-option span { display: grid; gap: 2px; min-width: 0; }
.acces-regle-option b { font-size: .88rem; }
.acces-regle-option small { font-size: .78rem; color: var(--texte-2); line-height: 1.4; }
.acces-regle [data-retirer] { margin-top: 10px; }
.acces-globale {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 11px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
}
.acces-globale > div { flex: 1; min-width: 200px; display: grid; }
.acces-globale b { font-size: .9rem; }
.acces-arbre {
  list-style: none; margin: 0; padding: 0;
  max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.acces-ligne {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 12px 6px calc(12px + var(--profondeur, 0) * 20px);
  border-bottom: 1px solid var(--border);
}
.acces-ligne:last-child { border-bottom: none; }
.acces-ligne[hidden] { display: none; }
.acces-ligne:hover { background: var(--surface-2); }
/* Un dossier explicitement réglé se repère dans une longue liste : c'est la seule chose
   qu'on cherche en rouvrant le panneau. */
.acces-ligne.a-regle { background: var(--accent-doux); }
.acces-ligne.a-regle:hover { background: var(--accent-doux); }
.acces-nom { display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0; font-size: .88rem; }
.acces-nom > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acces-nom svg { flex: 0 0 auto; color: var(--texte-3); }
.acces-effet { flex: 0 0 auto; font-size: .78rem; }
.acces-herite { color: var(--texte-3); font-style: italic; }
.acces-vide { padding: 18px 12px; color: var(--texte-3); font-style: italic; }

/* Rattachement d'une couleur à une catégorie, dans la fenêtre « Couleur / étiquette ».
   Détaché du reste par un filet : ce bloc ne concerne pas l'élément qu'on a sous la main
   mais tous ceux qui portent la catégorie — la portée n'est pas la même. */
.lien-categorie { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.lien-categorie-tete { display: flex; align-items: center; gap: 8px; font-size: .9rem; }
.lien-categorie-tete svg { color: var(--texte-3); }
.lien-categorie .aide-champ { display: block; margin: 4px 0 9px; }
/* Le bouton s'aligne sur le sélecteur par étirement plutôt qu'avec une hauteur écrite
   en dur : `border-box` étant actif, les deux occupent exactement la même hauteur totale,
   bordure et remplissage compris — et le bouton suivra si le sélecteur change un jour. */
.lien-categorie-ligne { display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap; }
.lien-categorie-ligne .btn {
  height: auto; min-height: 38px; border-radius: 9px; padding: 0 16px;
}
/* Le sélecteur occupe 60 % de la ligne, quelle que soit la longueur du nom de catégorie.
   Sa largeur ne saute donc plus d'un choix à l'autre, et le bouton reste à sa place.
   `flex-basis` plutôt que `width` : le composant de remplacement pose lui-même une
   largeur de 100 % sur son enveloppe, que `flex-basis` prime en disposition flex. */
.lien-categorie-ligne .select-custom { flex: 0 0 60%; min-width: 0; }
/* Avertissement de remplacement : ton « attention », pas « erreur » — rien n'est cassé,
   c'est une conséquence qu'on annonce avant qu'elle survienne. */
.avert-lien {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 10px 0 0; padding: 9px 12px; border-radius: var(--radius);
  background: var(--attention-doux); color: var(--attention);
  font-size: .81rem; line-height: 1.45;
}
.avert-lien-marque {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-top: 1px; border-radius: 50%;
  background: var(--attention); color: var(--surface); font-size: .72rem; font-weight: 700;
}
/* La couleur en place, montrée plutôt que décrite : un code hexadécimal ne se reconnaît
   pas d'un coup d'œil. */
.avert-lien-pastille {
  display: inline-block; width: 12px; height: 12px; vertical-align: -1px;
  border-radius: 3px; border: 1px solid rgb(0 0 0 / 15%);
}
.avert-lien code { background: rgb(255 255 255 / 45%); }

.lien-categorie-puces { display: flex; flex-wrap: wrap; gap: 6px; }
.puce-lien-cat {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 6px 2px 10px; border-radius: 20px;
  background: var(--accent-doux); color: var(--accent); font-size: .78rem; font-weight: 600;
}
.puce-lien-cat button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0; border: none; border-radius: 50%;
  background: none; color: inherit; cursor: pointer;
}
.puce-lien-cat button:hover { background: var(--accent); color: var(--accent-texte); }
/* Rappel des quatre niveaux sous le formulaire de droits : les libellés seuls ne disent
   pas ce qu'ils autorisent, et c'est exactement la question qu'on se pose en les posant. */
.aide-niveaux {
  margin: 0; padding: 10px 14px 10px 30px; list-style: disc;
  border-radius: var(--radius); background: var(--surface-2);
  font-size: .8rem; line-height: 1.5; color: var(--texte-2);
}
.aide-niveaux b { color: var(--texte); }
/* Avertissement de liste tronquée : sans lui, une recherche trop large paraîtrait avoir
   tout trouvé, et on conclurait à tort qu'un fichier n'existe pas. */
.acces-partiel {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 8px; padding: 8px 12px; border-radius: var(--radius);
  background: var(--attention-doux); color: var(--attention);
  font-size: .8rem; line-height: 1.4;
}
.acces-partiel svg { flex: 0 0 auto; }
/* Mode d'emploi du tableau. Trois phrases courtes plutôt qu'un paragraphe : on les lit
   une fois, on ne les relit jamais. */
.acces-legende {
  margin: 0 0 12px; padding: 11px 14px;
  border-left: 3px solid var(--accent); border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-2); font-size: .83rem; line-height: 1.5; color: var(--texte-2);
}
.acces-legende p { margin: 0 0 6px; }
.acces-legende p:last-child { margin-bottom: 0; }
/* En-tête de colonnes : la distinction entre « ce qui s'applique » et « votre règle » est
   tout l'enjeu de l'écran, elle doit être nommée. */
.acces-ligne.acces-entete {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2); font-size: .72rem; font-weight: 650;
  text-transform: uppercase; letter-spacing: .04em; color: var(--texte-3);
}
.acces-ligne.acces-entete:hover { background: var(--surface-2); }
.acces-colonne-regle { flex: 0 0 auto; }
/* Onglets internes à la fenêtre d'accès : plus discrets que ceux de la page, ils
   naviguent dans un contenu, ils ne changent pas d'écran. */
.onglets-acces { margin-bottom: 14px; }
.onglets-acces .onglet { padding: 7px 12px; font-size: .88rem; }
.acces-sous-section {
  display: flex; align-items: center; gap: 7px;
  margin: 0 0 8px; font-size: .88rem; font-weight: 650; color: var(--texte-2);
}
.acces-sous-section svg { color: var(--texte-3); }

/* Section « Accès » repliée dans la fenêtre de création : elle ne doit pas peser sur un
   formulaire dont c'est la partie facultative. */
.bloc-acces-creation { border-top: 1px solid var(--border); padding-top: 12px; }
.bloc-acces-creation > summary { cursor: pointer; font-weight: 600; font-size: .9rem; }
.bloc-acces-creation > summary .aide-champ { font-weight: 400; }
.bloc-acces-creation[open] > summary { margin-bottom: 10px; }

/* Saisie qui apparaît sous un sélecteur quand on y choisit « Autre… ». Décalée et reliée
   par un liseré : elle appartient au champ du dessus, ce n'est pas un champ de plus. */
.champ-autre {
  display: grid; gap: 4px; margin: 8px 0 0 12px;
  padding-left: 12px; border-left: 2px solid var(--accent-doux);
}
.champ-autre[hidden] { display: none; }

/* Note de portée : ce que cette section montre à l'administrateur et cache aux autres.
   Liseré à gauche plutôt que cadre complet — elle se lit comme une note en marge, pas
   comme un avertissement. Le cadenas la distingue au premier coup d'œil des aides
   ordinaires, qui sont nombreuses sur cet écran. */
.note-acces {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 0 14px; padding: 10px 14px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--accent-doux); color: var(--texte-2);
  font-size: .84rem; line-height: 1.5;
}
.note-acces svg { flex: 0 0 auto; margin-top: 2px; color: var(--accent); }
.note-acces b { color: var(--texte); }
.note-acces code { background: var(--surface); font-size: .8rem; }

/* Bandeau en tête d'une fenêtre en lecture seule : il dit d'emblée pourquoi les champs
   ne répondent pas, au lieu de laisser chercher. */
.bandeau-verrou {
  display: flex; align-items: flex-start; gap: 9px; margin: 0;
  padding: 10px 13px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface-2);
  color: var(--texte-2); font-size: .85rem; line-height: 1.4;
}
.bandeau-verrou svg { flex: 0 0 auto; margin-top: 1px; color: var(--texte-3); }

/* Boutons d'action d'une ligne de tableau. Le flex va sur ce conteneur, jamais sur le
   `<td>` : une cellule en `display: flex` cesse d'être une cellule de tableau, perd le
   `vertical-align: middle` de `.tableau td` et se décale du reste de la ligne. */
.cellule-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ---------- Admin : état d'un compte, actif ou bloqué ---------- */
/* Deux segments jointifs plutôt qu'un bouton d'action : l'état courant se lit sans
   avoir à traduire « Désactiver » en « il est donc actif ». Le segment choisi prend la
   couleur de ce qu'il signifie — vert pour ouvert, rouge pour fermé. */
.segments-etat { border-radius: 20px; }
.segments-etat .segment { padding: 3px 11px; font-size: .78rem; font-weight: 600; }
.segments-etat .segment.actif { font-style: normal; }
.segments-etat .segment[data-valeur="1"].actif { background: var(--ok-doux); color: var(--ok); }
.segments-etat .segment[data-valeur="0"].actif { background: var(--danger-doux); color: var(--danger); }
/* Le segment non retenu reste discret : il n'est qu'une possibilité, pas un état. */
.segments-etat .segment:not(.actif) { color: var(--texte-3); }
.segments-etat .segment[data-valeur="1"]:not(.actif):hover { background: var(--ok-doux); color: var(--ok); }
.segments-etat .segment[data-valeur="0"]:not(.actif):hover { background: var(--danger-doux); color: var(--danger); }

/* Rôle qui n'est pas rattaché au groupe du compte : signalement, pas erreur. */
.alerte-rattachement {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: 5px; vertical-align: middle;
  border-radius: 50%; background: var(--attention-doux); color: var(--attention);
  font-size: .72rem; font-weight: 700; cursor: help;
}

/* ---------- Admin : groupes et rôles ---------- */
/* Trois principes rappelés côte à côte avant les listes : sans eux, la différence
   entre un groupe et un rôle se devine mal, et c'est précisément ce qui se joue ici. */
.acces-principes {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px; margin: 0 0 20px;
}
.acces-principe {
  display: flex; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
}
.acces-principe-puce {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--accent-doux); color: var(--accent);
}
.acces-principe b { font-size: .9rem; }
.acces-principe p { margin: 4px 0 0; font-size: .82rem; line-height: 1.45; color: var(--texte-2); }

.acces-colonnes {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 22px; align-items: start;
}
@media (max-width: 1100px) { .acces-colonnes { grid-template-columns: 1fr; } }
.acces-titre {
  margin: 0 0 12px; font-size: .95rem;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.acces-sous-titre { font-size: .78rem; font-weight: 400; color: var(--texte-3); font-style: italic; }

/* L'échelle des groupes : une colonne de rangs numérotés reliés par un filet vertical.
   Le rang dit la hiérarchie, le filet dit qu'elle est continue — deux groupes voisins
   ne sont pas deux cases sans rapport. */
.echelle-groupes { list-style: none; margin: 0; padding: 0; position: relative; }
.echelle-groupe { position: relative; display: flex; gap: 12px; padding-bottom: 12px; }
.echelle-groupe:last-child { padding-bottom: 0; }
/* Le filet part du bas de la pastille et rejoint la suivante. Il s'arrête au dernier
   rang, sinon il pendrait dans le vide sous le groupe le plus restreint. */
.echelle-groupe::before {
  content: ""; position: absolute; left: 13px; top: 30px; bottom: 0;
  width: 2px; background: var(--border);
}
.echelle-groupe:last-child::before { display: none; }
.echelle-rang {
  flex: 0 0 auto; z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-doux); color: var(--accent);
  font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.echelle-corps {
  flex: 1; min-width: 0;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); padding: 10px 12px;
}
.echelle-tete { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.echelle-tete strong { font-size: .95rem; }
.echelle-tete code { font-size: .76rem; }
.echelle-caps { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.puce-cap {
  font-size: .72rem; padding: 2px 8px; border-radius: 6px;
  background: var(--surface-2); color: var(--texte-2); border: 1px solid var(--border);
}
.puce-cap-vide { font-style: italic; color: var(--texte-3); border-style: dashed; }
/* Les rôles rattachés sont séparés des capacités par un filet : ils ne relèvent pas du
   même axe, l'un dit les pouvoirs du groupe, l'autre qui y est attendu. */
.echelle-roles {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: 9px; padding-top: 8px; border-top: 1px dashed var(--border);
}
.echelle-roles-mot, .role-liens-mot {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--texte-3); margin-right: 2px;
}
.echelle-roles-vide, .role-liens-vide, .role-mesures-vide {
  font-size: .78rem; color: var(--texte-3); font-style: italic;
}
.puce-role, .role-nom {
  border: 1px solid color-mix(in srgb, var(--info) 35%, transparent);
  background: var(--info-doux); color: var(--info);
  font: inherit; font-size: .78rem; font-weight: 600;
  padding: 2px 10px; border-radius: 20px; cursor: pointer;
}
.puce-role:hover, .role-nom:hover { border-color: var(--info); }
/* Rôle mis en évidence : il ressort dans les deux colonnes à la fois, c'est ce qui
   montre d'un coup d'œil dans quels groupes il vit. */
.puce-role.en-avant, .role-nom.en-avant {
  background: var(--info); color: #ffffff; border-color: var(--info);
}
.echelle-groupe.groupe-eclaire .echelle-corps {
  border-color: var(--info); box-shadow: 0 0 0 3px var(--info-doux);
}
.echelle-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 9px; }
.btn-rang {
  width: 26px; height: 26px; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: 7px;
  background: var(--surface); color: var(--texte-2);
  font: inherit; font-size: .85rem; line-height: 1; cursor: pointer;
}
.btn-rang:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.btn-rang:disabled { opacity: .35; cursor: default; }

/* Niveau par défaut d'un groupe, coloré comme ce qu'il autorise : rouge quand il
   n'ouvre rien, vert quand il ouvre tout. */
.badge-niveau.niveau-aucun { background: var(--danger-doux); color: var(--danger); }
.badge-niveau.niveau-lecture { background: var(--attention-doux); color: var(--attention); }
.badge-niveau.niveau-ecriture { background: var(--info-doux); color: var(--info); }
.badge-niveau.niveau-total { background: var(--ok-doux); color: var(--ok); }

.liste-roles { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.role-carte {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); padding: 10px 12px;
}
.role-carte.en-avant { border-color: var(--info); box-shadow: 0 0 0 3px var(--info-doux); }
.role-tete { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.role-tete code { font-size: .76rem; }
.role-actions { display: flex; gap: 6px; margin-left: auto; }
.role-liens { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.puce-groupe {
  font-size: .76rem; font-weight: 600; padding: 2px 9px; border-radius: 20px;
  background: var(--accent-doux); color: var(--accent);
}
/* Groupe ou rôle suspendu : il reste lisible et modifiable — c'est de là qu'on le
   rétablit — mais il sort visiblement du jeu. D'où le liseré rouge et le contenu estompé,
   plutôt qu'un simple badge qui se noierait dans les autres. */
.echelle-groupe.est-bloque .echelle-corps,
.role-carte.est-bloque {
  border-color: var(--danger); background: var(--danger-doux);
}
.echelle-groupe.est-bloque .echelle-rang { background: var(--danger-doux); color: var(--danger); }
/* L'estompage épargne la barre d'actions : le bouton qui débloque doit rester net. */
.est-bloque .echelle-caps, .est-bloque .echelle-roles,
.est-bloque .role-liens, .est-bloque .role-mesures { opacity: .55; }

.role-mesures { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 8px; }
.role-mesures .badge-nb { border: 1px solid var(--border); }

/* Cases de rattachement dans la fenêtre d'un rôle : chaque groupe rappelle son niveau
   par défaut, sans quoi cocher « Lecteur » ne dit pas ce que ça implique. */
.choix-groupes { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 7px; }
.choix-groupe {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px;
  background: var(--surface);
}
.choix-groupe:hover { border-color: var(--accent); }
.choix-groupe:has(input:checked) { border-color: var(--accent); background: var(--accent-doux); }
.choix-groupe span { display: flex; flex-direction: column; min-width: 0; }
.choix-groupe b { font-size: .86rem; }
.choix-groupe small { font-size: .74rem; color: var(--texte-3); }

/* ---------- Historique lié ---------- */
.pastille-lien {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; min-height: 28px; padding: 3px 9px;
  border: 1px solid var(--border-fort); border-radius: 16px;
  background: var(--surface-2); color: var(--texte); font: inherit;
  font-size: .82rem; font-weight: 600; cursor: pointer;
  transition: background .13s, border-color .13s, color .13s;
}
.pastille-lien:hover { background: var(--accent-doux); border-color: var(--accent); color: var(--accent); }
.pastille-lien svg { flex: 0 0 auto; }
.pastille-lien span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pastille-lien .textes { display: block; min-width: 0; text-align: left; white-space: normal; }
.pastille-lien .textes .nom { display: block; }
.pastille-lien .textes .raison-recherche { overflow: visible; text-overflow: clip; white-space: normal; }
.pastille-utilisateur { color: var(--accent); background: var(--accent-doux); border-color: transparent; }

/* Pastilles décoratives (non cliquables) : chemin et catégories dans les liaisons */
/* Surlignage inline (chemin / catégories) : fond coloré, mais à hauteur de texte
   — plus de forme « pastille » (ni bordure, ni padding vertical, ni line-height). */
.pastille-statique {
  display: inline; padding: 0 6px; border-radius: 4px;
  background: #fffcf5; border: none;
  font-weight: 600; white-space: nowrap;
}
:root[data-theme="dark"] .pastille-statique { background: var(--surface-2); }
.ligne-pastilles { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; vertical-align: middle; }
.chemin-sep { color: var(--texte-3); margin: 0 1px; }
.liaison-cible .ligne-info { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.liaison-cible .chemin-sep { display: inline; }

.historique-identite {
  display: flex; align-items: center; gap: 11px;
  padding: 0 0 14px; border-bottom: 1px solid var(--border);
}
.historique-identite-icone {
  width: 40px; height: 40px; flex: 0 0 40px;
  display: grid; place-items: center; border-radius: 8px;
  background: var(--accent-doux); color: var(--accent);
}
.historique-identite strong { display: block; overflow-wrap: anywhere; }
.historique-meta {
  display: flex; align-items: center; gap: 6px 14px; flex-wrap: wrap;
  margin-top: 5px; color: var(--texte-3); font-size: .78rem;
}
.historique-meta span { display: inline-flex; align-items: center; gap: 4px; }
.historique-ip { font-family: var(--police-mono); }
.historique-avertissement {
  margin: 12px 0 0; padding: 8px 10px; border-left: 3px solid var(--attention);
  background: var(--attention-doux); color: var(--attention); font-size: .82rem;
}

.historique-filtres {
  display: grid; grid-template-columns: minmax(150px, 190px) minmax(150px, 190px) minmax(260px, 1fr);
  align-items: end; gap: 10px; padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.historique-raccourcis { display: flex; align-items: center; justify-content: flex-end; gap: 7px; flex-wrap: wrap; }

.historique-timeline { position: relative; padding: 8px 0 2px 30px; }
.historique-timeline::before {
  content: ""; position: absolute; left: 9px; top: 23px; bottom: 25px;
  width: 2px; background: var(--border-fort);
}
.historique-evenement { position: relative; padding: 12px 0 15px; }
.historique-evenement + .historique-evenement { border-top: 1px solid var(--border); }
.historique-point {
  position: absolute; left: -27px; top: 18px; z-index: 1;
  width: 14px; height: 14px; border: 3px solid var(--surface); border-radius: 50%;
  background: var(--texte-3); box-shadow: 0 0 0 1px var(--border-fort);
}
.historique-point.ok { background: var(--ok); }
.historique-point.attention { background: var(--attention); }
.historique-point.danger { background: var(--danger); }
.historique-point.neutre { background: var(--accent); }
.historique-contenu { min-width: 0; }
.historique-entete { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.historique-entete time { margin-left: auto; color: var(--texte-3); font-size: .78rem; white-space: nowrap; }
.historique-nom { display: flex; align-items: center; gap: 6px; font-size: .9rem; overflow-wrap: anywhere; }
.historique-contenu p { margin: 5px 0 0; color: var(--texte-2); font-size: .86rem; overflow-wrap: anywhere; }
.historique-contenu p.historique-sans-detail { color: var(--texte-3); font-style: italic; }
.historique-chemin {
  margin-top: 7px; padding: 5px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-radius: 6px; background: var(--surface-2); color: var(--texte-2);
  font-family: var(--police-mono); font-size: .74rem;
}
.historique-pagination { margin-top: 8px; }

/* ---------- Recherche explicable & liaisons ---------- */
.raison-recherche {
  display: block; color: var(--accent); font-size: .74rem; line-height: 1.35;
  overflow-wrap: anywhere;
}
.ligne-item .textes .raison-recherche { margin-top: 3px; white-space: normal; }
.extrait-donnee-cachee { color: var(--texte-2); font-size: .72rem; }
.ligne-item .textes .extrait-donnee-cachee { width: 100%; max-width: 620px; }
.resultat-surligne {
  padding: 0 2px; border-radius: 2px;
  background: #ffe066; color: #111; font-weight: 750;
}
.liaison-voir {
  align-self: stretch; width: 100%; margin-top: auto; justify-content: center;
  border: 1px solid var(--border-fort); background: var(--surface);
  color: var(--texte-2); cursor: pointer; font-size: .73rem;
}
.liaison-source {
  display: flex; align-items: center; gap: 10px; padding: 0 0 12px;
  border-bottom: 1px solid var(--border);
}
.liaison-source div { min-width: 0; }
.liaison-source > div strong, .liaison-source > div span { display: block; overflow-wrap: anywhere; }
.liaison-source > div span { margin-top: 2px; color: var(--texte-3); font-size: .78rem; }
.liaison-liste, .liaison-contenu-dossier, #liaison-resultats, #up-liaison-resultats {
  display: flex; flex-direction: column; gap: 2px; margin-top: 10px;
}
.liaison-element {
  display: flex; align-items: center; gap: 10px; min-height: 48px;
  padding: 7px 5px; border-bottom: 1px solid var(--border);
}
.liaison-element:last-child { border-bottom: 0; }
/* Champ combiné « lier à » : les propositions flottent sous le champ au lieu de pousser
   le reste de la carte vers le bas à chaque frappe. */
.combo-liaison { position: relative; }
.combo-liaison-panneau {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 460;
  max-height: 320px; overflow-y: auto;
  margin: 0; padding: 4px 10px;
  border: 1px solid var(--border-fort); border-radius: var(--radius-s);
  background: var(--surface); box-shadow: var(--ombre-2);
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity .12s ease, transform .12s ease;
}
.combo-liaison.ouvert .combo-liaison-panneau { opacity: 1; transform: none; pointer-events: auto; }
/* Ligne parcourue au clavier : même teinte que l'option active d'un sélecteur. */
.combo-liaison-panneau .liaison-element.survol { background: var(--accent-doux); border-radius: 6px; }
.combo-liaison-vide { padding: 8px 2px; font-style: italic; }
/* Liste par défaut : on dit d'où viennent ces propositions, sinon on croit à un résultat
   de recherche alors qu'on n'a rien tapé. */
.combo-liaison-entete {
  margin: 0; padding: 6px 2px 7px; border-bottom: 1px solid var(--border);
  font-size: .76rem;
}
/* Requête en cours : un liseré discret sur le champ, la liste précédente reste lisible. */
.combo-liaison.chargement input { border-color: var(--accent); }
.liaison-cible {
  min-width: 0; flex: 1; border: 0; padding: 0; background: none; color: inherit;
  text-align: left; cursor: pointer;
}
.liaison-cible strong, .liaison-cible span { display: block; overflow-wrap: anywhere; }
.liaison-cible span { margin-top: 2px; color: #4f493e; font-size: .76rem; }
:root[data-theme="dark"] .liaison-cible span { color: var(--texte-3); }
.liaison-cible .textes { margin-top: 0; color: inherit; font-size: inherit; }
.liaison-cible .raison-recherche { color: var(--accent); }
.liaison-cible .extrait-donnee-cachee { color: var(--texte-2); }
.liaison-cible:hover strong { color: var(--accent); }
.liaison-dossier { background: var(--accent-doux); color: var(--accent); }
.liaison-ajout { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }
.liaison-ajout label { display: block; margin-bottom: 6px; font-size: .82rem; font-weight: 650; }
.liaison-vide { padding: 22px 8px; }
.liaison-media { display: block; width: 100%; max-height: 62vh; object-fit: contain; background: var(--surface-2); }
.liaison-frame { height: min(62vh, 680px); border: 0; }
.liaison-sans-apercu { display: grid; place-items: center; gap: 10px; min-height: 180px; color: var(--texte-3); }
.liaison-meta { margin-top: 12px; }
.liaison-puce { gap: 5px; }
.liaison-puce .icone-fichier { width: 20px; height: 20px; font-size: .48rem; }
.liaison-import #up-liaison-resultats { max-height: 280px; overflow-y: auto; }

/* ---------- Pagination ---------- */
.pagination { display: flex; align-items: center; gap: 8px; justify-content: center; margin-top: 18px; flex-wrap: wrap; }
.pagination .info { font-size: .86rem; color: var(--texte-3); }

/* ---------- États vides ---------- */
.etat-vide {
  text-align: center; padding: 54px 20px; color: var(--texte-3);
}
.etat-vide .grande-icone { margin-bottom: 10px; opacity: .6; }
.etat-vide h3 { color: var(--texte-2); }

/* Squelettes de chargement */
.squelette {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: squelette 1.4s infinite;
  border-radius: var(--radius-s);
}
@keyframes squelette { to { background-position: -200% 0; } }

/* ---------- Mini graphiques SVG ---------- */
.graph-barres { display: flex; align-items: flex-end; gap: 6px; height: 120px; }
.graph-barres .barre { flex: 1; background: var(--accent); border-radius: 4px 4px 0 0; min-height: 3px; opacity: .85; }
.graph-barres .barre:hover { opacity: 1; }
.legende-graph { display: flex; gap: 6px; font-size: .7rem; color: var(--texte-3); margin-top: 4px; }
.legende-graph span { flex: 1; text-align: center; overflow: hidden; }

/* ---------- Responsive ---------- */
.btn-menu-mobile { display: none; }

@media (max-width: 980px) {
  .app { grid-template-columns: 1fr; grid-template-areas: "topbar" "main"; }
  .sidebar {
    position: fixed; left: 0; top: 0; bottom: 0;
    width: min(300px, 85vw); height: 100vh;
    translate: -100% 0; transition: translate .2s ease-out;
    box-shadow: var(--ombre-3);
  }
  html[data-demo="true"] .sidebar { top: 30px; bottom: 0; height: calc(100vh - 30px); }
  .sidebar.ouverte { translate: 0 0; }
  .voile-sidebar { position: fixed; inset: 0; background: rgba(10,12,24,.45); z-index: 65; }
  .btn-menu-mobile { display: inline-flex; }
  .main { padding: 16px 14px 108px; }
  /* La barre latérale est hors flux : la barre de sélection occupe toute la largeur. */
  .barre-selection { left: 14px; right: 14px; bottom: 12px; }
  .doc-layout { grid-template-columns: 1fr; }
  .omnibox .raccourci { display: none; }
}

@media (max-width: 560px) {
  .vue-grille { grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); }
  .modale-pied { flex-wrap: wrap; }
  .barre-outils .a-droite { margin-left: 0; width: 100%; }
  .voile { padding: 8px; }
  .modale { max-height: 96vh; }
  .modale-tete { padding: 13px 14px 0; }
  .modale-corps { padding: 12px 14px; }
  .historique-filtres { grid-template-columns: 1fr 1fr; }
  .historique-raccourcis { grid-column: 1 / -1; justify-content: flex-start; }
  .historique-raccourcis .btn { flex: 1 1 auto; }
  .historique-entete { align-items: flex-start; flex-wrap: wrap; }
  .historique-entete time { width: 100%; margin-left: 0; }
  .meta-liste { grid-template-columns: 1fr; gap: 3px; }
  .recherche-principale-ligne { flex-wrap: wrap; }
  .recherche-principale-ligne .btn { width: 100%; }
  .meta-liste dd { margin-bottom: 9px; }
}

/* Impression */
@media print {
  .sidebar, .topbar, .barre-outils, .barre-selection, .pagination { display: none !important; }
  .app { display: block; }
  .main { padding: 0; }
}

/* ============================================================
   Contrôle de complétude : page « À vérifier » et champs manquants
   ============================================================

   Le code couleur n'est pas décoratif, il porte une décision :
     rouge   — un champ OBLIGATOIRE manque, ou l'analyse a échoué. À traiter.
     orange  — le contrôle passe, mais quelque chose jette un doute dessus.
     jaune   — seuls des champs facultatifs manquent. Bon à savoir.
   Chaque niveau garde un libellé texte à côté de sa couleur : un tri par couleur
   seule est inutilisable pour qui distingue mal le rouge du vert. */

.segment-rouge[aria-pressed="true"] { background: var(--danger-doux); color: var(--danger); }
.segment-orange[aria-pressed="true"] { background: var(--attention-doux); color: var(--attention); }
.segment-jaune[aria-pressed="true"] { background: var(--attention-doux); color: var(--attention); }
#filtre-severite .badge-nb { margin-left: 6px; }

.badge-sev-rouge { background: var(--danger-doux); color: var(--danger); }
.badge-sev-orange { background: var(--attention-doux); color: var(--attention); }
.badge-sev-jaune { background: var(--attention-doux); color: var(--attention); opacity: .85; }
.badge-sev-vert { background: var(--ok-doux); color: var(--ok); }

.carte-verif {
  margin-bottom: 10px;
  border-left: 4px solid var(--border);
  transition: border-color .15s ease;
}
.carte-verif.sev-rouge { border-left-color: var(--danger); }
.carte-verif.sev-orange { border-left-color: var(--attention); }
.carte-verif.sev-jaune { border-left-color: var(--attention); opacity: .94; }
.carte-verif.sev-vert { border-left-color: var(--ok); }
.carte-verif.est-verifie { opacity: .6; }

.verif-entete { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.verif-icone { flex: 0 0 auto; display: flex; align-items: center; }
.verif-titres { flex: 1 1 260px; min-width: 0; }
.verif-nom {
  display: block; font-weight: 650; font-size: .98rem;
  color: var(--texte); text-decoration: none; word-break: break-word;
}
.verif-nom:hover { text-decoration: underline; }
.verif-sous { font-size: .82rem; color: var(--texte-2); margin-top: 3px; }
.verif-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

.verif-motifs {
  margin: 10px 0 0; padding: 0 0 0 18px;
  font-size: .85rem; color: var(--texte-2);
}
.verif-motifs li { margin: 2px 0; }

.verif-manquants { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.puce-manquant {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 999px;
  font-size: .78rem; line-height: 1.6;
  background: var(--attention-doux); color: var(--attention);
  border: 1px dashed transparent;
}
.puce-manquant.obligatoire {
  background: var(--danger-doux); color: var(--danger);
  border-color: currentColor; font-weight: 600;
}

/* Sur la fiche : ce qui manque s'affiche À LA PLACE de la valeur, jamais en la
   masquant. Une ligne absente laisse croire que le champ n'existe pas ; une ligne
   « non trouvée » dit qu'on a cherché. */
.doc-meta dd.valeur-manquante,
.valeur-manquante {
  color: var(--danger); font-style: italic; font-size: .85rem;
}
.valeur-manquante.facultative { color: var(--attention); }
.valeur-manquante::before { content: "— "; opacity: .6; }

.bandeau-controle {
  display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-radius: 10px; margin-bottom: 14px;
  font-size: .88rem;
}
.bandeau-controle.sev-rouge { background: var(--danger-doux); color: var(--danger); }
.bandeau-controle.sev-orange, .bandeau-controle.sev-jaune {
  background: var(--attention-doux); color: var(--attention);
}
.bandeau-controle .a-droite { margin-left: auto; display: flex; gap: 8px; align-items: center; }

/* ============================================================
   Bloc « Analyse du document »
   ============================================================

   Il portait le contenu réel du document dans une enfilade de listes de définition :
   références, dates, montants et conditions se suivaient sur une seule colonne, et il
   fallait parcourir trente lignes pour retrouver un total. La structure suit désormais
   la façon dont on lit un document :

     1. son identité et son taux de complétude — d'un coup d'œil, en haut ;
     2. ce qu'il dit, en une phrase ;
     3. ses CHIFFRES, en tuiles — c'est ce qu'on vient lire sur une facture ;
     4. le reste, en cartes courtes qui se balaient au lieu de se dérouler ;
     5. ce qui manque, à part et en dernier.

   Trois barres pour HT / TVA / TTC seraient un graphique qui n'apprend rien que les
   nombres ne disent mieux : une poignée de chiffres de tête se présente en tuiles. */

.bloc-analyse-large .doc-meta dl,
.bloc-analyse-large dl.doc-meta {
  display: grid; grid-template-columns: minmax(120px, 40%) 1fr;
  gap: 5px 12px; font-size: .9rem; margin: 0;
}
.bloc-analyse-large dl.doc-meta dt { color: var(--texte-2); }
.bloc-analyse-large dl.doc-meta dd { margin: 0; }

/* --- 1. Identité et complétude --- */
.analyse-identite {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 14px;
  background: var(--surface-2); border-radius: var(--radius-s);
}
.analyse-identite-gauche { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.badge-type { font-size: .88rem; padding: 4px 12px; }
.analyse-provenance {
  display: inline-flex; gap: 6px; flex-wrap: wrap;
  font-size: .78rem; color: var(--texte-3);
}

/* Jauge : le remplissage porte la sévérité, la piste est un pas plus clair de la même
   teinte — l'état se lit sur toute la barre, pas seulement à son extrémité. */
.jauge-bloc { margin-left: auto; min-width: 190px; }
.jauge-entete {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-bottom: 5px;
}
.jauge-libelle { font-size: .78rem; color: var(--texte-2); }
.jauge-chiffre { font-size: .95rem; font-weight: 650; color: var(--texte); }
.jauge-sur { font-weight: 400; font-size: .82rem; color: var(--texte-3); }
.jauge { height: 7px; border-radius: 999px; overflow: hidden; }
.jauge-remplissage { height: 100%; border-radius: 999px; transition: width .3s ease; }
.jauge.sev-vert   { background: var(--ok-doux); }
.jauge.sev-vert   .jauge-remplissage { background: var(--ok); }
.jauge.sev-jaune  { background: var(--attention-doux); }
.jauge.sev-jaune  .jauge-remplissage { background: var(--attention); }
.jauge.sev-orange { background: var(--attention-doux); }
.jauge.sev-orange .jauge-remplissage { background: var(--attention); }
.jauge.sev-rouge  { background: var(--danger-doux); }
.jauge.sev-rouge  .jauge-remplissage { background: var(--danger); }

/* --- 2. Le résumé, en phrase d'attaque --- */
.analyse-resume {
  font-size: 1rem; line-height: 1.6; color: var(--texte);
  margin: 0 0 16px; padding-left: 14px;
  border-left: 3px solid var(--accent);
}

/* --- 2 bis. Les parties, un cadre chacune --- */
/* Deux sociétés, deux cadres. Les fondre en une liste unique faisait perdre à qui
   appartenait quelle adresse — et un SIRET sans propriétaire n'identifie personne. */
/* Les cadres de parties vivent dans le MÊME flux en colonnes que les autres cartes
   (`.cartes-detail`). Ils avaient leur propre grille à colonnes explicites : la page
   changeait donc de règle en son milieu, et la jointure entre les deux mécaniques
   laissait un décrochage. Une seule règle pour tous les cadres, désormais.

   `inline-block` + largeur pleine : sans cela, Chrome coupe encore certaines cartes
   entre deux colonnes malgré `break-inside`. */


/* Les références ne sont PAS une partie au document : le liseré orange le dit, là où
   l'accent désigne qui écrit et le vert qui reçoit. */
.carte-references { border-top-color: var(--attention); }
.carte-references .partie-role { color: var(--attention); }
.carte-references .partie-champs { margin-top: 2px; }
.carte-partie {
  padding: 14px 16px; border-radius: var(--radius-s);
  border: 1px solid var(--border); background: var(--surface);
  border-top: 3px solid var(--texte-3);
}
.carte-partie .partie-champs { font-variant-numeric: tabular-nums; }
/* Qui écrit et qui reçoit ne se distinguent PAS par la seule couleur du liseré : le
   rôle est écrit en toutes lettres au-dessus du nom. La couleur ne fait que confirmer. */
.carte-partie.role-emetteur, .carte-partie.role-fournisseur { border-top-color: var(--accent); }
.carte-partie.role-destinataire, .carte-partie.role-client { border-top-color: var(--ok); }

.partie-entete { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.partie-role {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; color: var(--texte-3);
}
.carte-partie.role-emetteur .partie-role,
.carte-partie.role-fournisseur .partie-role { color: var(--accent); }
.carte-partie.role-destinataire .partie-role,
.carte-partie.role-client .partie-role { color: var(--ok); }
.partie-nom {
  font-size: 1.05rem; font-weight: 650; color: var(--texte);
  text-decoration: none; word-break: break-word;
}
.partie-nom:hover { text-decoration: underline; }
.partie-forme { font-size: .78rem; color: var(--texte-3); }

.partie-adresse {
  font-style: normal; font-size: .86rem; line-height: 1.45;
  color: var(--texte-2); margin: 0 0 10px;
  padding-left: 10px; border-left: 2px solid var(--border);
}

.partie-champs {
  display: grid; grid-template-columns: auto 1fr; gap: 3px 10px;
  font-size: .82rem; margin: 0;
}
.partie-champs dt { color: var(--texte-3); white-space: nowrap; }
/* Les identifiants légaux s'alignent en colonne et se comparent chiffre à chiffre : c'est
   le cas où les chiffres tabulaires servent vraiment. */
.partie-champs dd {
  margin: 0; color: var(--texte); word-break: break-word;
  font-variant-numeric: tabular-nums;
}
.partie-champs dd a { color: var(--accent); text-decoration: none; }
.partie-champs dd a:hover { text-decoration: underline; }

.partie-contact {
  margin-top: 10px; padding-top: 9px; border-top: 1px dashed var(--border);
  font-size: .84rem; color: var(--texte-2);
}
.partie-contact-titre {
  display: block; font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texte-3); margin-bottom: 3px;
}
.partie-contact a { color: var(--accent); text-decoration: none; }
.partie-contact a:hover { text-decoration: underline; }

/* --- 3. Les chiffres, en tuiles --- */
.tuiles-chiffres {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px; margin-bottom: 18px;
}
.tuile-chiffre {
  display: flex; flex-direction: column; gap: 3px;
  padding: 12px 14px; border-radius: var(--radius-s);
  border: 1px solid var(--border); background: var(--surface);
}
/* Le TTC est ce que le document coûte : les autres le composent. */
.tuile-chiffre.principale { border-color: var(--accent); background: var(--accent-doux); }
.tuile-libelle { font-size: .76rem; color: var(--texte-2); }
.tuile-chiffre.principale .tuile-libelle { color: var(--accent); }
/* Chiffres proportionnels, pas tabulaires : `tabular-nums` donne à chaque signe la
   largeur d'un zéro, ce qui délie visiblement un nombre affiché en grand. Le tabulaire
   est réservé aux colonnes qui doivent s'aligner verticalement. */
.tuile-valeur { font-size: 1.32rem; font-weight: 650; color: var(--texte); line-height: 1.15; }
.tuile-chiffre.principale .tuile-valeur { color: var(--accent); }
.tuile-note { font-size: .7rem; color: var(--texte-3); font-style: italic; }

/* --- 4. Le reste : des cartes qui se tassent --- */
/*
   Trois mises en page se succédaient dans le même bloc : des cadres pour les parties, un
   panneau sans cadres pour les données, un bloc à part pour les entités. Chacune se
   défendait isolément, l'ensemble donnait une page qui change de règle tous les dix
   centimètres.

   Tout est maintenant une CARTE, et les cartes se répartissent en masonry : chacune va
   dans la colonne la plus courte à cet instant, en suivant l'ordre de lecture. Aucune
   rangée n'est alignée, donc aucun trou sous les cartes courtes — c'est précisément ce
   qu'une grille produisait.

   La couleur du liseré porte une information, elle n'est pas décorative :
     accent  — l'émetteur, celui qui écrit
     vert    — le destinataire, celui qui reçoit
     orange  — les références du document
     rouge   — ce qui manque (une alerte, pas une donnée)
     gris    — tout le reste : des données, sans statut particulier
   Chaque carte porte son titre en toutes lettres : la couleur confirme, elle n'informe
   jamais seule. */
/* Les colonnes CSS (`column-count`) remplissaient la PREMIÈRE de haut en bas avant de
   passer à la suivante : les trois premières cartes s'empilaient à gauche, et il fallait
   descendre toute une colonne pour trouver la quatrième.
   La répartition se fait donc en JavaScript (`repartirCartes`), en travers — ligne 1 de
   gauche à droite, puis ligne 2 — chaque carte allant dans la colonne la plus courte à
   cet instant. C'est la mécanique d'un vrai masonry, que le CSS seul ne sait pas produire.
   Le CSS ne fait plus que poser les colonnes côte à côte. */
.cartes-detail { display: grid; gap: 12px; align-items: start; }
.cartes-detail[data-colonnes="1"] { grid-template-columns: 1fr; }
.cartes-detail[data-colonnes="2"] { grid-template-columns: 1fr 1fr; }
.cartes-detail[data-colonnes="3"] { grid-template-columns: 1fr 1fr 1fr; }
.colonne-cartes { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.section-detail {
  padding: 13px 15px; border-radius: var(--radius-s);
  border: 1px solid var(--border); border-top: 3px solid var(--border-fort);
  background: var(--surface);
}
.section-detail > h3,
.carte-donnee > h3 {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--texte-3); margin: 0 0 8px; font-weight: 700;
}

.groupe-entites + .groupe-entites { margin-top: 12px; }
.groupe-entites > h4 {
  font-size: .76rem; font-weight: 600; color: var(--texte-2); margin: 0 0 6px;
}
.pastilles-entites { display: flex; flex-wrap: wrap; gap: 6px; }
.pastille-entite {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 4px 11px; border-radius: 999px; text-decoration: none;
  background: var(--surface-2); border: 1px solid var(--border);
  color: var(--texte); font-size: .84rem; line-height: 1.5;
  transition: border-color .12s ease, background .12s ease;
}
.pastille-entite:hover { border-color: var(--accent); background: var(--accent-doux); }
.pastille-role { font-size: .72rem; color: var(--texte-3); }
.pastille-entite:hover .pastille-role { color: var(--accent); }

/* Le nombre de colonnes est décidé en JavaScript à partir de la largeur réelle, et
   redistribué au redimensionnement : trois colonnes au-delà de 1000 px, deux au-delà de
   700, une en dessous. Une bascule purement CSS ne suffirait pas — elle changerait la
   largeur sans redistribuer les cartes, et l'ordre de lecture en travers serait perdu. */

/* --- 5. Ce qui manque, à part --- */
.carte-donnee {
  padding: 13px 15px; border-radius: var(--radius-s);
  border: 1px solid var(--border); background: var(--surface);
}
.carte-manquants {
  margin-top: 14px; border-color: var(--danger);
  border-left-width: 3px; background: var(--surface);
}
.carte-manquants > h3 { color: var(--danger); }

@media (max-width: 640px) {
  .bloc-analyse-large .doc-meta dl,
  .bloc-analyse-large dl.doc-meta { grid-template-columns: 1fr; gap: 1px 0; }
  .bloc-analyse-large dl.doc-meta dt { margin-top: 8px; }
  .jauge-bloc { margin-left: 0; width: 100%; }
}

/* Référentiel des champs, onglet d'administration */
.champs-type-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; }
.champ-regle {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-2);
}
.champ-regle.inactif { opacity: .5; }
.champ-regle .champ-nom { flex: 1; font-size: .88rem; }
.champ-regle .segments { flex: 0 0 auto; }
.champ-regle .segment { font-size: .74rem; padding: 2px 8px; }

/* Indicateur d'analyse en cours, sur la fiche document.
   Une pastille qui respire plutôt qu'un compteur : personne n'a besoin de savoir qu'on
   interroge le serveur, seulement que quelque chose travaille encore. */
.suivi-analyse {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .82rem; color: var(--texte-2); white-space: nowrap;
}
.suivi-analyse::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: 0 0 auto;
  animation: suivi-pulse 1.4s ease-in-out infinite;
}
@keyframes suivi-pulse {
  0%, 100% { opacity: .25; transform: scale(.8); }
  50%      { opacity: 1;   transform: scale(1.15); }
}
/* Un point qui clignote sans fin gêne certaines personnes, et le respect de ce réglage
   n'est pas optionnel : l'information reste lisible sans l'animation. */
@media (prefers-reduced-motion: reduce) {
  .suivi-analyse::before { animation: none; opacity: .9; }
}

/* Saisie de mots-clés sur la fiche document. La pastille et sa croix réutilisent
   `.mot-pastille` / `.mot-x`, déjà définis plus haut pour la page d'envoi : une seule
   apparence pour un même objet, quel que soit l'écran où on l'édite. */
.carte-mots .mots-liste { min-height: 26px; }
.mots-vide { font-size: .86rem; color: var(--texte-3); font-style: italic; }
.mot-saisie { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.mot-saisie input[type="text"] { flex: 1; min-width: 0; }
/* Pendant l'enregistrement, la liste s'estompe sans bouger : un indicateur qui décale
   les pastilles ferait sauter la cible sous le curseur au moment d'en retirer une autre. */
.carte-mots .mots-liste.enregistre { opacity: .55; transition: opacity .12s ease; }

/* Valeurs copiables du bloc d'analyse.
   L'effet de survol reste discret : ces valeurs se lisent bien plus souvent qu'elles ne
   se copient, et un fond marqué sur chaque ligne survolée transformerait la lecture en
   parcours de boutons. */
[data-copier] {
  cursor: pointer; border-radius: 5px;
  margin: -2px -5px; padding: 2px 26px 2px 5px;
  transition: background .12s ease;
  position: relative;
}
[data-copier]:hover { background: var(--surface-3); }
[data-copier]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Le lien garde sa main de lien : à l'intérieur d'une valeur, cliquer dessus ouvre le
   courrier ou le site — ce n'est ni la recherche ni la copie. */
[data-copier] a { cursor: pointer; }

/* La loupe n'apparaît qu'au survol : présente en permanence, elle mettrait une icône sur
   chacune des vingt-cinq lignes de la fiche et la rendrait illisible.
   Elle reste dans le flux (`opacity`, pas `display`) pour que sa place soit réservée et
   que rien ne se décale au moment où elle paraît. */
.btn-rechercher-valeur {
  position: absolute; top: 50%; right: 3px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; padding: 0;
  border: 0; border-radius: 5px; background: none;
  color: var(--texte-3); cursor: pointer; opacity: 0;
  transition: opacity .12s ease, background .12s ease, color .12s ease;
}
[data-copier]:hover .btn-rechercher-valeur,
[data-copier]:focus-within .btn-rechercher-valeur { opacity: 1; }
.btn-rechercher-valeur:hover, .btn-rechercher-valeur:focus-visible {
  background: var(--surface); color: var(--accent); opacity: 1;
}
.btn-rechercher-valeur:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Sans survol — écran tactile — le bouton doit rester visible en permanence, sinon il
   n'existe pas du tout. */
@media (hover: none) {
  .btn-rechercher-valeur { opacity: .55; }
}
/* L'adresse tient sur plusieurs lignes : le bouton se cale en haut plutôt qu'au milieu. */
.partie-adresse .btn-rechercher-valeur { top: 4px; transform: none; }

/* Confirmation posée SUR la valeur, pas au coin de l'écran : on ne quitte pas des yeux
   ce qu'on vient de cliquer pour savoir si ça a marché. */
[data-copier].valeur-copiee { background: var(--info-doux); }
[data-copier].valeur-copiee::after {
  content: "✓ copié";
  margin-left: 7px; font-size: .74rem; font-weight: 650;
  color: var(--info); white-space: nowrap;
}
.tuile-valeur[data-copier].valeur-copiee::after { display: block; margin: 2px 0 0; }
@media (prefers-reduced-motion: reduce) {
  [data-copier] { transition: none; }
}

/* Bloc « Catégorie » de la fiche document.
   Une catégorie n'a PAS de couleur — c'est ce qu'est le document, pas la teinte qu'on lui
   a donnée. La puce reste donc neutre, à la différence des pastilles de mots-clés qui,
   elles, tirent leur teinte du mot. */
.puce-categorie {
  display: inline-flex; align-items: center;
  padding: 5px 14px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  color: var(--texte); font-size: .92rem; font-weight: 650;
  text-decoration: none; transition: border-color .12s ease, background .12s ease;
}
.puce-categorie:hover { border-color: var(--accent); background: var(--accent-doux); color: var(--accent); }
.categorie-saisie { margin-top: 10px; }
#categorie-valeur.enregistre { opacity: .55; transition: opacity .12s ease; }

/* Proposition de catégorie, quand personne n'a classé le document.
   Elle se distingue nettement d'un classement acquis : liseré pointillé et fond neutre.
   Une proposition qui ressemble à une décision serait prise pour une décision. */
.categorie-proposition {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding: 10px 12px;
  border: 1px dashed var(--border-fort); border-radius: var(--radius-s);
  background: var(--surface-2);
}
.proposition-texte { display: flex; flex-direction: column; gap: 2px; flex: 1 1 180px; min-width: 0; }
.proposition-titre {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texte-3); font-weight: 700;
}
.proposition-texte strong { font-size: .96rem; color: var(--texte); }
.proposition-motif { font-size: .78rem; color: var(--texte-2); }

/* Marque d'un classement qui n'a été validé par personne. Elle accompagne la puce sans
   la colorer : une catégorie n'a pas de couleur, et lui en donner une ici la ferait
   passer pour un statut. */
.categorie-origine {
  margin-left: 8px; font-size: .74rem; font-style: italic;
  color: var(--attention); cursor: help;
}

/* Pistes alternatives de classement, et bloc Statut. */
.categorie-autres { margin: 8px 0 0; font-size: .82rem; color: var(--texte-2); }
.lien-piste {
  border: 0; background: none; padding: 0 2px; cursor: pointer;
  color: var(--accent); font: inherit; text-decoration: underline;
}
.lien-piste:hover, .lien-piste:focus-visible { color: var(--accent-hover); }
.statut-saisie { margin-top: 10px; }
#statut-valeur.enregistre { opacity: .55; transition: opacity .12s ease; }

/* Termes fabriqués par l'analyse pour la recherche (synonymes, traductions, abréviations).
   Ils ne figurent souvent PAS sur le document : les présenter comme les mots-clés saisis
   les ferait passer pour du contenu. D'où le trait de séparation, le libellé de nature, et
   la pastille en contour plutôt qu'en aplat. */
.bloc-recherche {
  margin-top: 12px; padding-top: 11px; border-top: 1px dashed var(--border);
  display: flex; flex-direction: column; gap: 10px;
}
.ligne-recherche-titre {
  display: block; margin-bottom: 5px; cursor: help;
  font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texte-3); font-weight: 700;
}
.mot-pastille.mot-genere {
  background: transparent; border: 1px dashed hsl(var(--teinte, 250) 45% 62%);
  color: hsl(var(--teinte, 250) 55% 34%); font-weight: 550;
}
.mot-pastille.mot-genere:hover {
  background: hsl(var(--teinte, 250) 85% 94%); border-style: solid;
}
:root[data-theme="dark"] .mot-pastille.mot-genere {
  border-color: hsl(var(--teinte, 250) 40% 46%); color: hsl(var(--teinte, 250) 70% 74%);
}
:root[data-theme="dark"] .mot-pastille.mot-genere:hover {
  background: hsl(var(--teinte, 250) 38% 26%);
}

/* ---------- Bloc « Arborescence » et choix visuel du dossier ---------- */

.fil-emplacement {
  display: flex; align-items: center; flex-wrap: wrap; gap: 5px;
  font-size: .9rem; line-height: 1.7;
}
.fil-racine { display: inline-flex; color: var(--texte-3); }
.fil-sep { color: var(--texte-3); }
.fil-dossier {
  color: var(--texte); text-decoration: none;
  padding: 2px 8px; border-radius: 6px; background: var(--surface-2);
  border: 1px solid var(--border); transition: border-color .12s, background .12s;
}
.fil-dossier:hover { border-color: var(--accent); background: var(--accent-doux); color: var(--accent); }
/* Rappel non cliquable de l'emplacement (fenêtre de modification) : même pastille, mais
   elle ne doit pas se proposer au clic — il n'y a rien à ouvrir depuis un formulaire. */
span.fil-dossier { cursor: default; }
span.fil-dossier:hover { border-color: var(--border); background: var(--surface-2); color: var(--texte); }

/* L'arbre se PARCOURT des yeux : un niveau = un décalage, une pastille pour la couleur du
   dossier, le nombre de documents à droite. Un simple menu déroulant devient illisible
   passé une dizaine de dossiers, et perd totalement la notion de profondeur. */
.arbre-choix { max-height: 52vh; overflow-y: auto; padding: 4px; }
.arbre-choix ul { list-style: none; margin: 0; padding: 0; }
.noeud-dossier {
  display: flex; align-items: center; gap: 9px; width: 100%;
  /* Le décalage porte la profondeur : c'est la seule chose qui rende un arbre lisible. */
  padding: 7px 10px 7px calc(10px + var(--profondeur, 0) * 20px);
  border: 1px solid transparent; border-radius: var(--radius-s);
  background: none; color: var(--texte); font: inherit; text-align: left;
  cursor: pointer; transition: background .12s, border-color .12s;
}
.noeud-dossier:hover { background: var(--surface-2); }
.noeud-dossier:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* La destination retenue, marquée par la couleur ET par un repère : sur une liste longue,
   la seule teinte de fond se perd au défilement. */
.noeud-dossier.courant {
  background: var(--accent-doux); border-color: var(--accent); color: var(--accent);
  font-weight: 650;
}
.noeud-dossier.courant::after {
  content: "✓"; margin-left: auto; padding-left: 8px; font-weight: 700;
}
.noeud-pastille {
  flex: 0 0 auto; width: 10px; height: 10px; border-radius: 3px;
  background: var(--border-fort);
}
.noeud-pastille.racine { border-radius: 50%; background: var(--texte-3); }
.noeud-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noeud-ref { font-size: .74rem; color: var(--texte-3); font-variant-numeric: tabular-nums; }
.noeud-compte {
  flex: 0 0 auto; min-width: 22px; padding: 1px 7px; border-radius: 999px;
  background: var(--surface-3); color: var(--texte-2);
  font-size: .72rem; text-align: center;
}
.noeud-dossier.courant .noeud-compte { background: var(--accent); color: var(--accent-texte); }
/* Destination interdite (le dossier déplacé, ou l'un des siens). Elle reste AFFICHÉE :
   c'est elle qui situe ses voisins dans l'arborescence, la masquer ferait disparaître la
   branche entière. Elle ne réagit simplement à rien. */
.noeud-dossier.exclu { opacity: .4; cursor: not-allowed; }
.noeud-dossier.exclu:hover { background: none; }
/* Destination retenue, rappelée en toutes lettres : sur un arbre qui défile, la ligne
   marquée peut être sortie de l'écran au moment où l'on valide. */
.choix-dossier-resume { margin: 8px 0 0; font-weight: 600; color: var(--texte-2); }
/* Créer la destination sans quitter la fenêtre : sinon il faut sortir, aller créer le
   dossier ailleurs, puis reprendre le déplacement depuis le début. */
.choix-dossier-creation { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.choix-dossier-forme { display: flex; gap: 8px; align-items: center; }
.choix-dossier-forme input { flex: 1; min-width: 0; }
.choix-dossier-forme .btn { flex: 0 0 auto; }
/* L'arborescence dépliée DANS un formulaire (« Changer l'emplacement »). Elle est encadrée
   pour se distinguer des champs qui l'entourent : sans cela, un arbre de trente lignes
   posé au milieu d'une grille de champs se lit comme une liste de plus. */
.ed-arbre {
  margin-top: 10px; padding: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface-2);
}
/* Dans un formulaire, l'arbre partage la hauteur avec les champs : il en prend moins que
   la fenêtre de déplacement, où il est seul. */
.ed-arbre .arbre-choix { max-height: 34vh; }
.ed-emplacement .fil-emplacement { margin-top: 4px; }
.ed-emplacement-etat:empty { display: none; }

/* Fenêtre de conflit à l'import : deux faces, jamais une recommandation.
   « Plus récent » et « plus ancien » sont des faits affichés — réimporter volontairement
   une version antérieure pour restaurer de bonnes valeurs est un usage légitime, et
   l'écran n'a pas à souffler la réponse. D'où deux colonnes strictement symétriques. */
.conflit-alerte {
  display: flex; gap: 10px; align-items: flex-start; margin: 0 0 10px;
  padding: 10px 12px; border-radius: var(--radius-s);
  background: var(--attention-doux, var(--surface-2));
  border: 1px solid var(--border-fort);
}
.conflit-alerte svg { flex: 0 0 auto; margin-top: 1px; }
.conflit-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.conflit-face {
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface-2);
}
.conflit-face h4 { margin: 0 0 8px; font-size: .88rem; }
.conflit-infos { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0; font-size: .84rem; }
.conflit-infos dt { color: var(--texte-3); }
.conflit-infos dd { margin: 0; }
/* Les aperçus sont plafonnés : une fenêtre qui déborde de l'écran empêche justement de
   voir les deux fichiers côte à côte, qui est tout ce qu'on lui demande. */
.conflit-apercus { margin-top: 12px; }
.conflit-apercu {
  height: 34vh; min-height: 180px; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface-2); display: flex; align-items: center; justify-content: center;
}
.conflit-apercu img { max-width: 100%; max-height: 100%; object-fit: contain; }
.conflit-apercu iframe { width: 100%; height: 100%; border: 0; }
.conflit-apercu .mots-vide { padding: 12px; text-align: center; }
.conflit-choix { margin-top: 14px; }
.conflit-choix .btn { width: 100%; justify-content: center; }
.conflit-tous {
  display: flex; align-items: center; gap: 8px; margin-top: 12px;
  font-size: .86rem; font-weight: 400;
}
@media (max-width: 700px) {
  .conflit-grille { grid-template-columns: 1fr; }
}

/* Historique des versions, sur la fiche. Replié par défaut : la version courante est ce
   qu'on vient voir, les précédentes ne se consultent qu'à la demande. */
.versions-liste { display: flex; flex-direction: column; gap: 6px; }
.version-bloc { border: 1px solid var(--border); border-radius: var(--radius-s); overflow: hidden; }
.version-tete {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; background: var(--surface-2); border: 0; cursor: pointer;
  font: inherit; font-size: .87rem; color: var(--texte); text-align: left;
}
.version-tete:hover { background: var(--surface-3); }
.version-tete .chevron-version { flex: 0 0 auto; transition: transform .15s ease; }
.version-bloc.ouvert .chevron-version { transform: rotate(90deg); }
.version-nom { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.version-date { flex: 0 0 auto; font-size: .8rem; color: var(--texte-3); }
.version-corps { padding: 10px 12px; border-top: 1px solid var(--border); }
.version-corps dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0 0 8px; font-size: .84rem; }
.version-corps dt { color: var(--texte-3); }
.version-corps dd { margin: 0; }
.version-courante .version-tete { background: var(--accent-doux); color: var(--accent); font-weight: 650; }

/* Journal : la source se choisit sur une pilule, pas dans une liste déroulante. Les deux
   journaux n'ont pas les mêmes colonnes ni le même vocabulaire — c'est un changement de
   vue, pas un filtre parmi d'autres, et un bouton segmenté le dit mieux. */
.journal-pilule {
  display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px;
}
.journal-pilule-choix {
  padding: 6px 16px; border: 0; border-radius: 999px; background: none;
  font: inherit; font-size: .86rem; color: var(--texte-2); cursor: pointer;
  transition: background .13s ease, color .13s ease;
}
.journal-pilule-choix:hover { color: var(--texte); }
.journal-pilule-choix.actif {
  background: var(--surface); color: var(--accent); font-weight: 650;
  box-shadow: var(--ombre-1, 0 1px 3px rgba(0,0,0,.12));
}
/* Les filtres s'enroulent : leur nombre change avec la source, une grille à colonnes
   fixes laisserait un trou là où « Consultations » disparaît. */
.journal-filtres {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin-bottom: 14px;
}
.journal-filtres .champ { margin: 0; min-width: 150px; }
.journal-filtres .journal-filtre-large { flex: 1 1 260px; min-width: 220px; }
.journal-filtres > .btn { flex: 0 0 auto; }
/* En-tête de colonne triable : un vrai bouton, donc atteignable au clavier. La flèche dit
   le sens, et seule la colonne active la porte. */
.tri-colonne {
  display: inline-flex; align-items: center; gap: 5px; width: 100%;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.tri-colonne:hover { color: var(--accent); }
.tri-colonne.actif { color: var(--accent); }
.tri-sens { font-size: .7rem; }
.badge-source-fichier { background: var(--surface-3); color: var(--texte-2); }
.badge-source-action { background: var(--accent-doux); color: var(--accent); }
.tableau-journal td { vertical-align: top; }
/* Les deux formats d'export vont ensemble, poussés à droite de la barre de filtres : ce
   sont des sorties, pas des critères — les mêler aux filtres ferait chercher longtemps. */
/* Dans l'en-tête de la carte, à côté du compte de lignes : `.carte-titre .a-droite` porte
   déjà la marge automatique qui les pousse à droite. */
.journal-export { display: flex; gap: 6px; align-items: center; }
/* Quand les journaux ont-ils été archivés pour la dernière fois. Discret mais toujours
   là : c'est un état, pas une notification — il doit se lire d'un coup d'œil sans jamais
   réclamer d'attention. */
.journal-dernier {
  display: flex; align-items: center; gap: 6px; justify-content: flex-end;
  margin: -4px 0 10px;
}
.journal-dernier svg { flex: 0 0 auto; opacity: .7; }
.journal-dernier-jamais { color: var(--attention, var(--texte-2)); }

/* Emplacement des deux dossiers. Le chemin ACTIF est montré au-dessus du champ, et non
   dedans : ce qui est enregistré et ce qui est réellement utilisé peuvent différer — un
   chemin inaccessible retombe sur le défaut, et c'est précisément ce qu'il faut voir. */
.chemins-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.chemin-bloc {
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-s);
  background: var(--surface-2);
}
.chemin-tete { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.chemin-tete h3 { margin: 0; font-size: .9rem; flex: 1; min-width: 0; }
.chemin-actif { margin: 0 0 10px; font-size: .8rem; word-break: break-all; color: var(--texte-2); }
.chemin-bloc .champ { margin: 0; }
.encadre-alerte {
  display: flex; gap: 10px; align-items: flex-start; margin: 0 0 12px;
  padding: 10px 12px; border-radius: var(--radius-s);
  background: var(--danger-doux, var(--surface-2)); border: 1px solid var(--border-fort);
  font-size: .86rem;
}
.encadre-alerte svg { flex: 0 0 auto; margin-top: 1px; }
@media (max-width: 800px) { .chemins-grille { grid-template-columns: 1fr; } }

/* Bandeau du mode secours. Permanent, en haut, non refermable, et sur toute la largeur :
   il doit être vu avant qu'on commence à saisir, pas découvert au moment d'enregistrer.
   Les couleurs sont posées en dur plutôt qu'en variables de thème — c'est un état
   exceptionnel, il n'a pas à se fondre dans l'habillage. */
.bandeau-secours {
  position: sticky; top: 0; z-index: 400;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px;
  background: #8a2b12; color: #fff;
  font-size: .88rem; line-height: 1.45;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .25);
}
.bandeau-secours svg { flex: 0 0 auto; }
.bandeau-secours b { font-weight: 700; }

/* Couleurs déjà employées, dans le sélecteur de couleur/étiquette.
   Triées par usage : celle qui sert le plus arrive en tête, parce que c'est presque
   toujours celle qu'on cherche. */
.couleurs-utilisees { margin-bottom: 14px; }
.liste-utilisees {
  display: flex; flex-direction: column; gap: 3px;
  max-height: 190px; overflow-y: auto; padding-right: 2px;
}
.utilisee-ligne {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 5px 8px; border: 1px solid transparent; border-radius: var(--radius-s);
  background: none; color: var(--texte); font: inherit; text-align: left; cursor: pointer;
  transition: background .12s, border-color .12s;
}
.utilisee-ligne:hover { background: var(--surface-2); }
.utilisee-ligne.actif { background: var(--accent-doux); border-color: var(--accent); }
.utilisee-ligne:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.utilisee-pastille {
  flex: 0 0 auto; width: 16px; height: 16px; border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, .18);
}
.utilisee-nom {
  flex: 1; min-width: 0; font-size: .86rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Une couleur sans étiquette est justement celle qu'on vient nommer : elle se signale
   sans crier. */
.utilisee-nom.sans-nom { color: var(--texte-3); font-style: italic; }
.utilisee-compte {
  flex: 0 0 auto; min-width: 22px; padding: 1px 7px; border-radius: 999px;
  background: var(--surface-3); color: var(--texte-2);
  font-size: .72rem; text-align: center; font-variant-numeric: tabular-nums;
}
