/* ============================================================================
   Design system « Encre & grenat » — partagé par la fonderie, le validateur et
   le portail. Source UNIQUE : monté en lecture seule dans les trois.
   Ne jamais recopier une règle d'ici vers un CSS d'appli.

   REFONTE 2026-08-11. Le diagnostic de la version précédente (beige + bordeaux
   + or + Georgia) : fonds, filets, texte secondaire ET accents tenaient tous
   dans l'arc chaud 0-85° — soit, techniquement, une image sépia. D'où « triste
   et old school ». Trois principes en réponse :

   1. CHAMP NEUTRE, ACCENT CHAUD. Fonds, surfaces, filets et gris de texte sont
      quasi achromatiques ; toute la chaleur est concentrée dans le grenat, qui
      est nettement PLUS saturé qu'avant (le contraste laissait plus du double
      de marge : #7c1f2e mesurait 9,9:1 là où 4,5 suffit).
   2. ENCRE vs PLEIN. --wine/--ok/--bad sont des couleurs de TEXTE et de BORDURE
      (elles s'éclaircissent en sombre) ; --accent-solid/--ok-solid/--bad-solid
      sont des FONDS PLEINS, associés à --on-accent/--on-ok/--on-bad.
      Le bouton principal est de l'ENCRE : noir en clair, papier en sombre.
   3. L'OR N'EST PAS UNE COULEUR, C'EST UN MATÉRIAU. Aplati en une valeur, il
      donne de la moutarde ; assombri pour atteindre AA, il donne du kaki.
      --gold ne sert donc plus QU'À l'étoile pleine (petite forme, pas du texte).
   ============================================================================ */

/* ---------------------------------------------------------------- 1. tokens */
:root{
  color-scheme: light;

  /* Champ ARDOISE **discrète** : gris à peine bleutés (chroma ~0,008-0,016, contre
     0,037-0,043 dans le premier essai, qui virait franchement au bleu). Ce qui
     compte n'est pas la teinte, c'est l'ÉCART DE VALEUR fond <-> carte : il était
     à 1,11:1 et les cartes ne se détachaient pas ; il est ici à 1,23:1. */
  --bg:#e5e8ed; --bg-2:#d6d9de;
  --surface:#ffffff; --surface-2:#f4f6f9; --surface-sunk:#ebedf2;
  --border:#d7dbe2;
  /* --border-strong atteint 3:1 (WCAG 1.4.11) : un champ de saisie vide doit se
     voir. L'ancien #d5c2b3 était à 1,6:1 — invisible. Réservé aux champs. */
  --border-strong:#878c96;

  --fg:#171b21; --fg-muted:#4f545d; --fg-subtle:#676c75;

  /* Grenat : +34 % de chroma et +9 points de clarté par rapport à l'ancien
     bordeaux, et il mesure encore 7,3:1 sur blanc. C'est LUI qui doit chanter. */
  --wine:#a8203d; --wine-hover:#c02546;
  --wine-soft:color-mix(in srgb, var(--wine) 6%, var(--surface));
  /* Bouton principal = encre noire. Seul élément entièrement rempli de la page. */
  --accent-solid:#171b21; --accent-solid-hover:#333942; --on-accent:#ffffff;

  /* Laiton mat. UN SEUL usage autorisé : le glyphe d'étoile pleine (.stars__btn,
     .stars-inline). Pas de --gold-ink ni de --gold-soft : l'or en texte donne du
     kaki, l'or en aplat donne de la moutarde — c'était la moitié du « old school ». */
  --gold:#b07d10;

  --ok:#0f7a4d; --ok-ink:#0b5f3c; --ok-solid:#0e6e45; --on-ok:#ffffff; --ok-soft:#e6f4ec;
  /* Erreur poussée vers l'orangé : sur un badge de 12 px, un rouge trop proche
     du grenat de marque rendrait « erreur » et « marque » confondables. */
  --bad:#c2410c; --bad-ink:#9a3412; --bad-solid:#b23a12; --on-bad:#ffffff; --bad-soft:#fbeade;
  --info:#1b5fa8; --info-ink:#17518f; --info-soft:#e6eef8;

  --focus:#a8203d; --focus-halo:color-mix(in srgb, var(--wine) 22%, transparent);

  /* espacement (base 4 px) */
  --sp-1:.25rem; --sp-2:.5rem; --sp-3:.75rem; --sp-4:1rem;
  --sp-5:1.75rem; --sp-6:2.75rem; --sp-7:4rem; --sp-8:5.5rem;

  /* Typographie : Georgia est SORTIE des composants. Sur un poste sans les
     polices MS, sa chaîne de repli finissait sur Nimbus Roman — un clone de
     Times. Une partie de l'équipe voyait donc littéralement des titres en Times. */
  --font-ui:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-display:"Segoe UI Variable Display",system-ui,-apple-system,"Segoe UI",
    Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  --fs-xs:.75rem; --fs-sm:.875rem; --fs-md:1rem; --fs-lg:1.125rem;
  --fs-xl:clamp(1.2rem, 1.05rem + .5vw, 1.45rem);
  --fs-2xl:clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem);
  /* --lh-ui : interligne d'INTERFACE, qui manquait. 1,55 sur un libellé de
     12 px donnait de « l'aéré faible ». */
  --lh-tight:1.12; --lh-ui:1.35; --lh-body:1.55;

  /* Rayons resserrés et concentriques. 22 px sur une carte, c'est du widget
     iOS ; 12 px sur un bouton de 44 px, c'est le milieu mou.
     --r-full est RÉSERVÉ aux formes réellement en pilule (chip, badge, jauge). */
  --r-1:4px; --r-2:6px; --r-3:8px; --r-4:12px; --r-full:999px;

  /* Ombres NEUTRES (l'ancienne était teintée bordeaux sur un fond beige : un
     halo rose-brun, donc un bord sale) et à étalement NÉGATIF, pour que le flou
     reste sous l'élément au lieu de faire du brouillard latéral. */
  --sh-1:0 1px 2px -1px #0f0f1226;
  --sh-2:0 4px 12px -4px #0f0f1224, 0 1px 2px -1px #0f0f1214;
  --sh-3:0 24px 48px -16px #0f0f1233, 0 4px 12px -6px #0f0f1226;

  --dur-1:110ms; --dur-2:180ms; --dur-3:320ms; --ease:cubic-bezier(.2,.8,.2,1);
  --w-page:1240px; --w-prose:68ch; --tap:44px;
  /* Largeur du groupe d'étoiles : 5 boutons de 30 px (icône 22 + rembourrage 6 +
     bordure 2) et 4 gouttières de 2. Exposée pour aligner exactement dessous
     d'autres éléments — si la taille des étoiles change, ils suivent. */
  --stars-w:calc(5 * 30px + 4 * 2px);
}

:root[data-theme="dark"]{
  color-scheme: dark;
  /* Fond = GRIS TRÈS SOMBRE, pas noir (clarté 19,5 % contre 12,9 % auparavant),
     carte en ardoise juste au-dessus : 8 points de clarté d'écart.
     On juge cette séparation en CLARTÉ PERÇUE (OKLCH), pas en ratio WCAG : la
     formule WCAG se comprime dans les tons sombres (elle plafonne vers 1,25 quel
     que soit l'écart) et n'est pas faite pour comparer deux surfaces — elle reste
     l'outil pour le TEXTE, où check-contrast.py continue de l'appliquer. */
  --bg:#131519; --bg-2:#1a1c20;
  --surface:#24282e; --surface-2:#2e3238; --surface-sunk:#1a1d22;
  --border:#3a3f4980; --border-strong:#7a808b;
  --fg:#f0f2f6; --fg-muted:#b0b5be; --fg-subtle:#91959e;

  --wine:#ff8095; --wine-hover:#ff9aab;
  --wine-soft:color-mix(in srgb, var(--wine) 12%, var(--surface));
  /* Inversion assumée : en sombre, le bouton principal est du PAPIER sur encre. */
  --accent-solid:#f0f2f6; --accent-solid-hover:#ffffff; --on-accent:#171b21;

  --gold:#e0b558;

  --ok:#4ecf8c; --ok-ink:#6fdda6; --ok-solid:#1c7a4b; --on-ok:#ffffff; --ok-soft:#102b1d;
  --bad:#f0805f; --bad-ink:#f79a7e; --bad-solid:#a33c18; --on-bad:#ffffff; --bad-soft:#2b1710;
  --info:#8ab8ec; --info-ink:#a5c9f2; --info-soft:#16212e;

  --focus:#ff8095; --focus-halo:#ff809540;

  /* En sombre, une ombre NOIRE sur un fond déjà noir est invisible : l'élévation
     passe par la remontée de clarté de la surface + un liseré haut. */
  --sh-1:inset 0 1px 0 #ffffff0a;
  --sh-2:inset 0 1px 0 #ffffff0d, 0 2px 8px -4px #00000080;
  --sh-3:0 28px 64px -20px #000000b3, inset 0 1px 0 #ffffff14;
}

/* ---------------------------------------------------------------- 2. base */
*,*::before,*::after{box-sizing:border-box}

/* `hidden` doit gagner sur les display:flex/grid des composants ci-dessous. */
[hidden]{display:none!important}

body{
  margin:0;
  font:var(--fs-md)/var(--lh-body) var(--font-ui);
  color:var(--fg);
  /* Fond PLAT. Le dégradé diagonal en corps de page est une signature 2011-2014,
     pour un écart de clarté de 3,6 points — invisible, et sujet au banding. */
  background:var(--bg);
  min-height:100vh;
  -webkit-text-size-adjust:100%;
}

/* Titres en ENCRE, pas en couleur d'accent : un titre coloré est le marqueur
   n°1 du web des années 2010. L'accent agit, il ne titre pas. */
h1,h2,h3{font-family:var(--font-display);line-height:var(--lh-tight);margin:0;
  color:var(--fg);letter-spacing:-.02em}
h1{font-size:var(--fs-2xl);font-weight:700}
h2{font-size:var(--fs-xl);font-weight:650}
h3{font-size:var(--fs-lg);font-weight:650;letter-spacing:-.01em}
p{margin:0}
a{color:var(--wine)}

:focus-visible{
  outline:2px solid var(--focus);
  outline-offset:2px;
  box-shadow:0 0 0 4px var(--focus-halo);
  border-radius:var(--r-1);
}
:focus:not(:focus-visible){outline:none}

::selection{background:color-mix(in srgb, var(--wine) 22%, transparent)}

/* --------------------------------------------------------- 3. structure de page */
.page{min-height:100vh;display:flex;flex-direction:column}
.wrap{width:100%;max-width:var(--w-page);margin:0 auto;padding:0 var(--sp-4)}

.app-header{
  border-bottom:1px solid var(--border);
  background:color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter:blur(10px);
  padding:var(--sp-4) 0;
}
.app-header__bar{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap}
.app-brand{display:flex;align-items:center;gap:var(--sp-3);min-width:0}
.app-brand .icon{width:24px;height:24px;color:var(--wine);flex:none}
.app-brand__text{min-width:0}
.app-brand__sub{color:var(--fg-muted);font-size:var(--fs-sm);line-height:var(--lh-ui);
  margin-top:3px}
.app-header__tools{margin-left:auto;display:flex;align-items:center;gap:var(--sp-2);
  flex-wrap:wrap}

.app-main{flex:1;padding:var(--sp-6) 0 var(--sp-8)}
/* `p{margin:0}` plus haut vaut pour TOUT le monde : sans la règle qui suit, une
   phrase d'introduction touche le bloc qu'elle introduit (barre d'outils, carte,
   grille de tuiles). Le `:not(:last-child)` évite l'espace mort quand l'intro
   termine une carte. */
.page-intro{color:var(--fg-muted);font-size:var(--fs-sm);line-height:var(--lh-ui);
  max-width:var(--w-prose)}
.page-intro:not(:last-child){margin-bottom:var(--sp-4)}

.layout--split{display:grid;grid-template-columns:minmax(380px, 470px) 1fr;
  gap:var(--sp-6);align-items:start}
/* Rail collant. max-height + overflow SONT INDISPENSABLES : sans eux, dès que le
   contenu du rail dépasse la hauteur de la fenêtre (c'est le cas quand le panneau
   de résultat s'ouvre dans la fonderie), son bas devient INATTEIGNABLE — il faut
   faire défiler toute la page, donc la colonne de droite, pour le révéler.
   Avec un défilement interne, le rail reste autonome quelle que soit sa hauteur. */
.rail--sticky{position:sticky;top:var(--sp-4);
  max-height:calc(100vh - var(--sp-4) * 2);
  overflow-y:auto;overscroll-behavior:contain}
@media (max-width:960px){
  .layout--split{grid-template-columns:1fr}
  .rail--sticky{position:static;max-height:none;overflow:visible}
}

.stack{display:flex;flex-direction:column;gap:var(--sp-5)}
.stack--tight{gap:var(--sp-2)}
.cluster{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.cluster--end{justify-content:flex-end}
.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2);
  margin-bottom:var(--sp-4)}
.toolbar__grow{flex:1;min-width:180px}
.section-head{display:flex;align-items:baseline;gap:var(--sp-3);flex-wrap:wrap;
  margin-bottom:var(--sp-3)}

/* ---------------------------------------------------------------- 4. cartes */
/* UNE seule frontière par niveau : la carte extérieure porte le filet, les
   niveaux internes se contentent d'un remplissage. Une carte de voix cumulait
   7 à 10 filets 1 px — la grammaire d'un formulaire d'administration. */
.card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-4);
  padding:var(--sp-5);
  box-shadow:var(--sh-1);
}
.card--flat{box-shadow:none}
.card--dashed{border-style:dashed;border-color:var(--border-strong);background:transparent;
  box-shadow:none}
.card__head{display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-2)}
.card__title{font-family:var(--font-display);font-size:var(--fs-xl);font-weight:650;
  letter-spacing:-.02em;color:var(--fg)}
.card__meta{color:var(--fg-muted);font-size:var(--fs-sm)}

.panel{border-radius:var(--r-3);padding:var(--sp-5);background:var(--surface-sunk)}
/* --accent : l'étape EN COURS d'un enchaînement (teintée, elle attire l'œil).
   --alt : l'étape suivante, neutre. Anciennement --wine/--gold, renommés :
   le second n'est plus doré, et un nom de couleur fige un choix graphique. */
.panel--accent{background:var(--wine-soft)}
.panel--alt{background:var(--surface-sunk)}
.panel--ok{background:var(--ok-soft)}
.panel[inert]{opacity:.45;filter:saturate(.5)}

/* Micro-libellés en casse NORMALE : le « uppercase + muted + small » est
   l'idiome administratif Bootstrap le plus reconnaissable, et les capitales
   détruisent la silhouette des mots. */
.panel__label{display:flex;align-items:center;gap:var(--sp-2);
  font-size:.8125rem;font-weight:600;line-height:var(--lh-ui);
  color:var(--fg);margin-bottom:var(--sp-3)}
.panel__num{display:grid;place-items:center;width:20px;height:20px;border-radius:var(--r-1);
  background:var(--accent-solid);color:var(--on-accent);font-size:11px;font-weight:700;flex:none}
.panel__opt{font-weight:400;color:var(--fg-muted)}

/* ---------------------------------------------------------------- 5. boutons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  font:inherit;font-size:var(--fs-sm);font-weight:500;line-height:var(--lh-ui);
  min-height:var(--tap);padding:var(--sp-2) var(--sp-4);
  border:1px solid var(--border);border-radius:var(--r-2);
  background:var(--surface);color:var(--fg);
  cursor:pointer;text-decoration:none;
  transition:background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease),
             color var(--dur-1) var(--ease);
}
/* Plus de translateY au survol : le bouton n'a pas d'ombre, il sautait donc
   sans que rien ne suive — tic de thème Bootstrap. */
.btn:hover{border-color:var(--border-strong);background:var(--surface-2)}
.btn:active{transform:scale(.985)}
.btn:disabled,.btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed}
.btn[aria-busy="true"]{cursor:progress}

.btn--primary{background:var(--accent-solid);color:var(--on-accent);
  border-color:var(--accent-solid);font-weight:600}
.btn--primary:hover{background:var(--accent-solid-hover);border-color:var(--accent-solid-hover)}
.btn--success{background:var(--ok-solid);color:var(--on-ok);border-color:var(--ok-solid)}
.btn--success:hover{background:var(--ok-solid);border-color:var(--ok-solid)}
.btn--danger{background:var(--bad-solid);color:var(--on-bad);border-color:var(--bad-solid)}
.btn--danger:hover{background:var(--bad-solid);border-color:var(--bad-solid)}
.btn--quiet{background:transparent;border-color:transparent;color:var(--fg-muted)}
.btn--quiet:hover{background:var(--surface-2);border-color:var(--border);color:var(--fg)}
.btn--ghost{background:transparent}
.btn--sm{min-height:32px;padding:var(--sp-1) var(--sp-3);font-size:var(--fs-xs)}
.btn--icon{min-width:var(--tap);padding:var(--sp-2)}
.btn--icon.btn--sm{min-width:32px;min-height:32px;padding:var(--sp-1)}
.btn--block{width:100%}

/* ---------------------------------------------------------------- 6. formulaires */
.field{display:flex;flex-direction:column;gap:var(--sp-2)}
.field__label{font-size:.8125rem;font-weight:600;line-height:var(--lh-ui);color:var(--fg);
  display:flex;align-items:center;gap:var(--sp-2)}
.field__label .opt{font-weight:400;color:var(--fg-muted)}
.field__row{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}

/* --border-strong seulement ici : ce qui accepte une saisie doit se voir. */
.input,.textarea,.select{
  width:100%;font:inherit;font-size:var(--fs-md);line-height:var(--lh-ui);
  padding:var(--sp-3);
  border:1px solid var(--border-strong);border-radius:var(--r-2);
  background:var(--surface);color:var(--fg);
  transition:border-color var(--dur-1) var(--ease);
}
.textarea{resize:vertical;min-height:5.5rem;line-height:var(--lh-body)}
.input:hover,.textarea:hover,.select:hover{border-color:var(--fg-subtle)}
.input::placeholder,.textarea::placeholder{color:var(--fg-subtle)}
.input--locked{background:var(--surface-sunk);color:var(--fg-muted);cursor:default;
  border-color:var(--border)}
.input--sm{padding:var(--sp-2) var(--sp-3);font-size:var(--fs-sm)}

.hint{font-size:var(--fs-sm);line-height:var(--lh-ui);color:var(--fg-muted)}
.counter{font-size:var(--fs-xs);color:var(--fg-muted);font-variant-numeric:tabular-nums;
  font-family:var(--font-mono)}
.counter--over{color:var(--bad-ink);font-weight:700}

.switch{display:inline-flex;align-items:center;gap:var(--sp-2);cursor:pointer;
  font-size:var(--fs-sm);color:var(--fg-muted);min-height:var(--tap)}
.switch input{accent-color:var(--accent-solid);width:17px;height:17px;cursor:pointer}
.switch:hover{color:var(--fg)}
.switch .icon{width:15px;height:15px}

/* -------------------------------------------------- 7. segmented & étoiles */
.segmented{display:inline-flex;background:var(--surface-sunk);
  border-radius:var(--r-2);padding:3px;gap:2px}
.segmented__opt{
  display:inline-flex;align-items:center;gap:var(--sp-2);
  font:inherit;font-size:var(--fs-sm);padding:var(--sp-2) var(--sp-3);
  border:1px solid transparent;border-radius:var(--r-1);
  background:transparent;color:var(--fg-muted);cursor:pointer;white-space:nowrap;
  transition:background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.segmented__opt:hover{color:var(--fg)}
.segmented__opt[aria-checked="true"]{background:var(--surface);color:var(--fg);
  font-weight:600;box-shadow:var(--sh-1)}
.segmented--verdict .segmented__opt{min-height:var(--tap);padding:var(--sp-2) var(--sp-4)}
.segmented--verdict .segmented__opt[aria-checked="true"][data-v="ok"]{
  background:var(--ok-solid);color:var(--on-ok)}
.segmented--verdict .segmented__opt[aria-checked="true"][data-v="bad"]{
  background:var(--bad-solid);color:var(--on-bad)}

/* Seul endroit où l'or survit : une petite forme PLEINE, jamais du texte. */
.stars{display:inline-flex;gap:2px;width:var(--stars-w)}
.stars__btn{background:none;border:1px solid transparent;border-radius:var(--r-1);
  padding:3px;cursor:pointer;color:var(--fg-subtle);line-height:0;
  transition:color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease)}
.stars__btn .icon{width:22px;height:22px}
.stars__btn[aria-checked="true"],.stars__btn.is-on{color:var(--gold)}
.stars__btn:hover{transform:scale(1.06);color:var(--gold)}
@media (hover:none){.stars__btn:hover{transform:none}}

/* ------------------------------------------------- 8. badges, puces, progression */
/* Sans filet : le remplissage suffit à les détacher de la carte. */
.badge{display:inline-flex;align-items:center;gap:var(--sp-1);
  font-size:var(--fs-xs);font-weight:600;padding:3px var(--sp-2);
  border-radius:var(--r-full);background:var(--surface-sunk);color:var(--fg-muted);
  white-space:nowrap}
.badge--ok{background:var(--ok-soft);color:var(--ok-ink)}
.badge--warn{background:var(--surface-sunk);color:var(--fg)}
.badge--info{background:var(--info-soft);color:var(--info-ink)}
.badge--danger{background:var(--bad-soft);color:var(--bad-ink)}
.badge .icon{width:13px;height:13px}

.chip{display:inline-flex;align-items:center;gap:var(--sp-1);
  font-size:var(--fs-xs);color:var(--fg-muted);
  background:var(--surface-sunk);border-radius:var(--r-full);
  padding:3px var(--sp-2);white-space:nowrap}
.chip .icon{width:13px;height:13px;flex:none}
.chip--live{color:var(--ok-ink);background:var(--ok-soft)}

.pill{display:inline-flex;align-items:center;gap:var(--sp-2);
  font-size:var(--fs-sm);background:var(--surface-sunk);
  border-radius:var(--r-full);padding:var(--sp-1) var(--sp-3)}
.pill b{color:var(--fg);font-weight:600}
.pill .icon{width:15px;height:15px;color:var(--fg-muted)}
/* La pastille d'identité est un LIEN vers l'administration dans les trois pages. */
a.pill{text-decoration:none;color:inherit;
  transition:background var(--dur-1) var(--ease)}
a.pill:hover{background:var(--surface-2);outline:1px solid var(--border-strong)}

/* Jauge en accent PLAT : le dégradé bordeaux -> moutarde était l'élément le
   plus daté de l'interface (registre « barre de gamification 2012 »). */
.progress{height:6px;border-radius:var(--r-full);background:var(--surface-sunk);
  overflow:hidden}
.progress__fill{display:block;height:100%;width:0;border-radius:inherit;
  background:var(--wine);transition:width var(--dur-3) var(--ease)}

/* ------------------------------------------------- 9. états de chargement */
.spinner{width:15px;height:15px;flex:none;border:2px solid var(--border);
  border-top-color:var(--wine);border-radius:50%;animation:ab-spin .7s linear infinite}
@keyframes ab-spin{to{transform:rotate(1turn)}}

.eq{display:inline-flex;align-items:flex-end;gap:2px;height:15px;flex:none}
.eq i{width:3px;background:currentColor;border-radius:1px;animation:ab-eq .9s ease-in-out infinite}
.eq i:nth-child(1){height:6px;animation-delay:-.2s}
.eq i:nth-child(2){height:13px;animation-delay:-.5s}
.eq i:nth-child(3){height:9px}
@keyframes ab-eq{0%,100%{transform:scaleY(.4)}50%{transform:scaleY(1)}}

.empty{text-align:center;color:var(--fg-muted);padding:var(--sp-6) var(--sp-4)}

/* ------------------------------------------------- 10. retours utilisateur */
.inline-msg{font-size:var(--fs-sm);line-height:var(--lh-ui);min-height:1.3em;
  display:flex;align-items:center;gap:var(--sp-2);color:var(--fg-muted)}
.inline-msg--ok{color:var(--ok-ink)}
.inline-msg--err{color:var(--bad-ink)}
.inline-msg .icon{width:15px;height:15px;flex:none}

.toast-region{position:fixed;inset-block-end:var(--sp-4);inset-inline:0;
  display:flex;flex-direction:column;align-items:center;gap:var(--sp-2);
  pointer-events:none;z-index:60;padding:0 var(--sp-4)}
.toast{pointer-events:auto;display:flex;align-items:center;gap:var(--sp-2);
  max-width:min(560px, 100%);
  background:var(--surface);color:var(--fg);
  border:1px solid var(--border);border-left:3px solid var(--accent-solid);
  border-radius:var(--r-2);box-shadow:var(--sh-3);
  padding:var(--sp-3) var(--sp-4);font-size:var(--fs-sm);
  animation:ab-toast var(--dur-2) var(--ease)}
.toast--ok{border-left-color:var(--ok-solid)}
.toast--err{border-left-color:var(--bad-solid)}
.toast .icon{width:17px;height:17px;flex:none}
@keyframes ab-toast{from{opacity:0;transform:translateY(8px)}}

dialog{
  border:1px solid var(--border);border-radius:var(--r-4);
  background:var(--surface);color:var(--fg);box-shadow:var(--sh-3);
  padding:var(--sp-5);max-width:min(560px, calc(100vw - 2rem));width:100%;
}
dialog::backdrop{background:#0f0f12a6;backdrop-filter:blur(2px)}
.dialog__title{font-family:var(--font-display);font-size:var(--fs-xl);font-weight:650;
  letter-spacing:-.02em;color:var(--fg);margin-bottom:var(--sp-3)}
.dialog__body{display:flex;flex-direction:column;gap:var(--sp-3);
  font-size:var(--fs-sm);line-height:var(--lh-ui);color:var(--fg-muted)}
.dialog__actions{display:flex;justify-content:flex-end;gap:var(--sp-2);
  margin-top:var(--sp-5);flex-wrap:wrap}
.dialog__code{display:flex;align-items:center;gap:var(--sp-2);
  background:var(--surface-sunk);border-radius:var(--r-2);
  padding:var(--sp-2) var(--sp-3);font:var(--fs-sm)/1.5 var(--font-mono);
  overflow-x:auto;color:var(--fg)}

/* ---------------------------------------------------------------- 11. divers */
.icon{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.icon--filled{fill:currentColor;stroke:none}

.serif{font-family:var(--font-display)}
.mono{font-family:var(--font-mono);font-size:var(--fs-sm)}
.muted{color:var(--fg-muted)}
.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

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

.skip-link{position:absolute;left:var(--sp-3);top:-3rem;z-index:70;
  background:var(--surface);color:var(--wine);border:1px solid var(--border-strong);
  border-radius:var(--r-2);padding:var(--sp-2) var(--sp-4);
  transition:top var(--dur-1) var(--ease)}
.skip-link:focus{top:var(--sp-3)}

details summary{cursor:pointer}
details summary::marker{color:var(--fg-subtle)}

audio{width:100%;height:38px;border-radius:var(--r-2)}

/* --------------------------------------------- 12. mouvement & contrastes forcés */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .spinner{animation:none;border-top-color:var(--wine);opacity:.7}
  .eq i{animation:none;height:10px}
  .stars__btn:hover{transform:none}
}

/* Le mode contraste forcé réinjecte les bordures retirées au §4/§8. */
@media (forced-colors: active){
  .btn,.card,.panel,.badge,.chip,.pill,.segmented,.toast,dialog{border:1px solid ButtonText}
  .segmented__opt[aria-checked="true"]{background:Highlight;color:HighlightText}
  .icon{stroke:currentColor}
}

/* --------------------------------------------- 13. coquille : rail de navigation */
/* Le cadre commun des trois outils et du portail (refonte du 2026-09-15, cf.
   Voix/docs/etudes/evaluation-ux-portail-2026-09-15.md). Construit par mountShell()
   dans ui.js : aucune appli ne le redessine. Déplié 232 px, replié 64 px (icônes
   seules, libellé en infobulle et hors écran pour les lecteurs d'écran), état mémorisé
   par origine. Sous 960 px : barre haute et tiroir <dialog>. */
.shell{display:grid;grid-template-columns:232px minmax(0,1fr);min-height:100vh;
  transition:grid-template-columns var(--dur-2) var(--ease)}
.shell[data-rail="closed"]{grid-template-columns:64px minmax(0,1fr)}
.shell-main{min-width:0;display:flex;flex-direction:column}
.shell-top{display:none}
/* Dans la coquille, le contenu s'aligne à gauche de sa colonne : centrer 1 240 px à
   côté d'un rail ferait flotter la page. */
.shell .wrap{margin:0;padding:0 var(--sp-6)}
.shell .wrap--reading{max-width:960px}

.rail-nav{position:sticky;top:0;height:100vh;overflow-y:auto;overscroll-behavior:contain;
  display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-4) var(--sp-3);
  background:var(--surface);border-right:1px solid var(--border);scrollbar-width:thin}
.rail-brand{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);
  margin-bottom:var(--sp-3);color:var(--fg);text-decoration:none;border-radius:var(--r-3);
  border:1px solid transparent}
.rail-brand:hover{background:var(--surface-2)}
.rail-brand[aria-current="page"]{border-color:var(--border);background:var(--surface-2)}
.rail-brand .icon{width:22px;height:22px;color:var(--wine)}
.rail-brand b{display:block;font:700 var(--fs-lg)/1.1 var(--font-display);letter-spacing:-.02em}
.rail-brand small{display:block;font-size:var(--fs-xs);color:var(--fg-muted);margin-top:2px}
.rail-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--sp-1)}
.rail-item{position:relative;display:flex;align-items:center;gap:var(--sp-3);min-height:40px;
  width:100%;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-3);
  border:1px solid transparent;background:none;color:var(--fg-muted);text-decoration:none;
  font:600 var(--fs-sm)/var(--lh-ui) var(--font-ui);text-align:left;cursor:pointer;
  transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.rail-item:hover{background:var(--surface-2);color:var(--fg)}
.rail-item .icon{width:18px;height:18px;flex:none}
.rail-item__label{min-width:0}
.rail-item .badge{margin-left:auto}
.rail-item__ext{margin-left:auto;width:14px;height:14px;opacity:.7}
.rail-item[aria-current="page"]{background:var(--surface-2);border-color:var(--border);color:var(--fg)}
.rail-item[aria-current="page"]::before{content:"";position:absolute;left:calc(-1 * var(--sp-3) - 1px);
  top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;background:var(--wine)}
.rail-item[aria-disabled="true"]{opacity:.55;cursor:not-allowed}
/* Viviane : l'entrée principale, en encre pleine comme le bouton principal du système.
   La hiérarchie passe par la taille et le remplissage, jamais par la couleur. */
.rail-item--primary{min-height:48px;background:var(--accent-solid);color:var(--on-accent);
  border-color:var(--accent-solid);margin-bottom:var(--sp-2)}
.rail-item--primary:hover{background:var(--accent-solid-hover);border-color:var(--accent-solid-hover);
  color:var(--on-accent)}
.rail-item--primary[aria-current="page"]{color:var(--on-accent);background:var(--accent-solid)}
.rail-item--primary .icon{width:20px;height:20px}
.rail-foot{margin-top:auto;display:flex;flex-direction:column;gap:var(--sp-1);
  padding-top:var(--sp-3);border-top:1px solid var(--border)}
.rail-theme{margin:0 0 var(--sp-2) var(--sp-1)}
.rail-account{display:flex;align-items:center;gap:var(--sp-3);min-height:44px;
  padding:var(--sp-2) var(--sp-3);border-radius:var(--r-3);border:1px solid transparent;
  color:var(--fg);text-decoration:none}
.rail-account:hover{background:var(--surface-2)}
.rail-account[aria-current="page"]{background:var(--surface-2);border-color:var(--border)}
.rail-account__text{min-width:0}
.rail-account b{display:block;font-size:var(--fs-sm);font-weight:600;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-account small{display:block;font-size:var(--fs-xs);color:var(--fg-muted)}
.rail-account .badge{margin-left:auto}
.rail-avatar{display:grid;place-items:center;width:30px;height:30px;border-radius:var(--r-full);
  background:var(--wine-soft);color:var(--wine);font-weight:700;font-size:var(--fs-xs);
  flex:none;text-transform:uppercase;text-decoration:none}
.rail-collapse{color:var(--fg-subtle);font-size:var(--fs-xs);min-height:36px}

/* replié : icônes seules, libellés hors écran (toujours lus), infobulle native. */
.shell[data-rail="closed"] .rail-nav{padding:var(--sp-4) 10px;align-items:center}
.shell[data-rail="closed"] .rail-brand{padding:var(--sp-2) 0;margin-bottom:var(--sp-2);
  justify-content:center;width:44px}
.shell[data-rail="closed"] .rail-brand span,
.shell[data-rail="closed"] .rail-item .badge,
.shell[data-rail="closed"] .rail-item__ext,
.shell[data-rail="closed"] .rail-account__text,
.shell[data-rail="closed"] .rail-account .badge{display:none}
.shell[data-rail="closed"] .rail-item__label{position:absolute;width:1px;height:1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.shell[data-rail="closed"] .rail-list{width:100%;align-items:center}
.shell[data-rail="closed"] .rail-item{width:44px;height:44px;min-height:44px;
  justify-content:center;padding:0}
.shell[data-rail="closed"] .rail-item[aria-current="page"]::before{left:-11px}
.shell[data-rail="closed"] .rail-foot{align-items:center;width:100%}
.shell[data-rail="closed"] .rail-theme{margin:0 0 var(--sp-2)}
.shell[data-rail="closed"] .rail-theme .segmented{flex-direction:column}
.shell[data-rail="closed"] .rail-account{padding:var(--sp-2) 0;justify-content:center;width:44px}

/* en-tête de page : remplace l'ancien bandeau haut dans la coquille */
.page-head{display:flex;align-items:flex-start;gap:var(--sp-3);flex-wrap:wrap;
  margin-bottom:var(--sp-5)}
.page-head__icon{width:24px;height:24px;color:var(--wine);margin-top:7px;flex:none}
.page-head__text{min-width:0}
.page-head__sub{margin-top:3px;font-size:var(--fs-sm);color:var(--fg-muted);line-height:var(--lh-ui)}
.page-head__tools{margin-left:auto;display:flex;align-items:center;gap:var(--sp-2);
  flex-wrap:wrap;align-self:center}

/* onglets horizontaux (administration) */
.tabs{display:flex;gap:var(--sp-1);border-bottom:1px solid var(--border);margin-bottom:var(--sp-5);
  overflow-x:auto;scrollbar-width:thin}
.tab{display:inline-flex;align-items:center;gap:var(--sp-2);padding:var(--sp-2) var(--sp-3) 10px;
  font-size:var(--fs-sm);font-weight:600;color:var(--fg-muted);text-decoration:none;
  border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;
  transition:color var(--dur-2) var(--ease)}
.tab:hover{color:var(--fg)}
.tab[aria-current="page"]{color:var(--fg);border-bottom-color:var(--wine)}
.tab .icon{width:16px;height:16px}
.tab .badge{margin-left:2px}
.tab .badge:empty{display:none}
.tab[hidden]{display:none}

/* barre haute + tiroir (mobile) */
.rail-drawer{position:fixed;inset:0 auto 0 0;margin:0;width:min(320px,88vw);max-width:none;
  height:100vh;max-height:100vh;border:0;border-right:1px solid var(--border);padding:0;
  background:var(--surface);color:var(--fg);box-shadow:var(--sh-3)}
.rail-drawer::backdrop{background:#0f0f12a6}
.rail-drawer__head{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-3) var(--sp-3) 0;
  font:700 var(--fs-lg)/1.1 var(--font-display);letter-spacing:-.02em}
.rail-drawer__head .icon{width:22px;height:22px;color:var(--wine)}
.rail-drawer__head .btn{margin-left:auto}
.rail-drawer .rail-nav{position:static;height:auto;min-height:calc(100vh - 60px);border:0;display:flex}
.rail-drawer .rail-brand{display:none}          /* la tête du tiroir porte déjà la marque */
@media (max-width:960px){
  .shell,.shell[data-rail="closed"]{grid-template-columns:1fr}
  .shell > .rail-nav{display:none}
  .shell .wrap{padding:0 var(--sp-4)}
  .shell-top{display:flex;align-items:center;gap:var(--sp-2);min-height:56px;
    padding:var(--sp-1) var(--sp-3);background:var(--surface);border-bottom:1px solid var(--border);
    position:sticky;top:0;z-index:30}
  .shell-top__brand{display:flex;align-items:center;gap:var(--sp-2);color:var(--fg);
    text-decoration:none;font:700 var(--fs-lg)/1.1 var(--font-display);letter-spacing:-.02em}
  .shell-top__brand .icon{width:20px;height:20px;color:var(--wine)}
  .shell-top__avatar{margin-left:auto}
  .page-head__tools{margin-left:0;width:100%}
}
