/* ══════════════════════════════════════════════════════════════════════════
   archiflow-tokens.css — SOURCE UNIQUE des tokens du thème unique archiflow
   Phase 1a de la refonte UI. Cf. docs/diagnostic-refonte-ui.md

   ─── CONTRAT DE CE FICHIER ───────────────────────────────────────────────
   1. Il ne contient QUE des custom properties. Aucune règle de mise en forme,
      aucun sélecteur d'élément. Si tu as besoin d'écrire `.machin { … }`,
      ce n'est pas ici.
   2. Il se charge EN PREMIER, avant toute autre feuille. Tout le reste en
      dépend ; lui ne dépend de rien.
   3. Les valeurs viennent des maquettes (relevés au pixel, docs/maquettes/),
      normalisées sur une échelle propre. Elles ne sont pas inventées.

   ─── POURQUOI LA SECTION « PONT LEGACY » EXISTE ──────────────────────────
   Le repo consomme aujourd'hui ~4 000 fois une douzaine de noms de tokens
   historiques : --acc (877×), --acc-rgb (655×), --t1/--t3 (625× chacun),
   --brd (576×), --f (508×)… Redéfinir ces noms ici plutôt que d'en inventer
   de nouveaux fait basculer l'application entière sur la nouvelle palette
   SANS toucher aux 33 744 lignes de CSS existantes.
   La refonte page par page devient alors un travail de STRUCTURE et de
   MARKUP, pas un travail de couleur — c'est ce qui rend le chantier tenable.

   ⚠️ Ne pas supprimer le pont avant la Phase 4, et seulement après un grep
   prouvant que plus personne ne consomme le nom retiré.
   ══════════════════════════════════════════════════════════════════════════ */


/* ═════════════════════════════════════════════════════════════════════════
   1. PRIMITIVES — les échelles brutes. Préfixe --af-.
      On ne les consomme JAMAIS directement dans un composant : on passe par
      la couche sémantique (§2). Une primitive est une couleur ; un token
      sémantique est un rôle.
   ═════════════════════════════════════════════════════════════════════════ */

:root {

  /* ── Neutres — bleu-violet désaturé ────────────────────────────────────
     Relevés maquettes : sidebar #090E37 / #0C112A / #10112F / #13143E,
     canvas #F0ECFD / #F1EEFB / #F2F0FD, carte #F6F6FD / #FCFBFE.
     Toute l'échelle est construite sur cette teinte : le gris pur n'existe
     pas dans les maquettes, et un gris neutre y jurerait immédiatement. */
  --af-n-950: #070B24;
  --af-n-900: #0B1030;   /* sidebar — la valeur la plus structurante du système */
  --af-n-850: #111739;
  --af-n-800: #1A2050;
  --af-n-700: #2C3468;
  --af-n-600: #454D80;
  --af-n-500: #646B97;
  --af-n-400: #8C92B4;
  --af-n-300: #B4B8CF;
  --af-n-200: #D6D8E8;
  --af-n-150: #E6E5F3;
  --af-n-100: #EFEDF9;
  --af-n-75:  #F3F1FC;   /* canvas de contenu */
  --af-n-50:  #F8F7FD;
  --af-n-25:  #FCFBFE;   /* surface de carte */
  --af-n-0:   #FFFFFF;

  /* ── Accent violet ─────────────────────────────────────────────────────
     DEUX valeurs, pas une (arbitrage Q9). Les relevés montrent deux régimes
     distincts et cohérents d'une planche à l'autre :
       · sur fond SOMBRE (item de nav actif) : violet profond — #3E349B, #4D3098
       · sur fond CLAIR (bouton primaire, séries) : violet vif — #5837D0,
         #7651EE, #7434ED
     Une seule valeur écrase la hiérarchie : un violet vif sur la sidebar
     sombre vibre, un violet profond sur fond clair meurt. */
  --af-v-900: #2A1C6B;
  --af-v-800: #38258E;
  --af-v-700: #4A32A8;   /* item de nav actif, sur fond sombre */
  --af-v-600: #5B3FD1;
  --af-v-500: #6D46EC;   /* PRIMAIRE — bouton, focus, séries de données */
  --af-v-400: #8B6BF2;
  --af-v-300: #B39EF7;
  --af-v-200: #D6CAFB;
  --af-v-100: #E9E2FD;
  --af-v-50:  #F4EFFD;   /* pastille d'icône de carte KPI (relevé #F4EFFD) */

  /* ── Sémantiques ───────────────────────────────────────────────────────
     Trois tons par rôle : -ink (texte/icône, contraste AA sur fond clair),
     valeur pleine (remplissage, point, barre), -soft (fond de badge).
     ⚠️ Les fonds -soft partent des relevés de maquette mais ont été
     ASSOMBRIS : tels quels ils ne se détachaient pas de la carte (le vert
     « Payée » rendait 1,19:1, l'ambre 1,11:1) et le badge n'existait plus
     qu'en tant que texte. Chacun est calé à 1,25:1 de la carte. */
  --af-ok-ink:   #10583F;
  --af-ok:       #1E9268;
  --af-ok-soft:  #CDE9DC;   /* relevé #C5E4D6, éclairci pour tenir le texte */

  --af-warn-ink: #8A4E12;
  --af-warn:     #D9822B;
  --af-warn-soft:#FBDCC9;   /* relevé direct */

  --af-err-ink:  #8E1F2F;
  --af-err:      #D93A4E;
  --af-err-soft: #FADBE1;   /* relevé direct */

  --af-info-ink: #21458F;
  --af-info:     #3B6FE0;
  --af-info-soft:#D6E0FD;   /* relevé direct */

  --af-mute-ink: #4A5074;
  --af-mute:     #666D93;   /* aligné sur --af-text-3, même contrainte AA */
  --af-mute-soft:#E0E1F0;   /* brouillon / inactif — relevé #DFE1F4 */

  /* ── Palette de séries (graphiques, répartitions) ──────────────────────
     Relevés sur « Répartition par projet » de la planche 06. Cinq teintes,
     cadence claire, aucun dégradé. L'ordre est celui de la maquette et il
     compte : c'est l'ordre d'attribution automatique.
     ⚠️ Ces couleurs sont CATÉGORIELLES. Elles ne suivent pas l'accent et ne
     portent aucune sémantique — une série verte ne veut pas dire « bon ». */
  --af-serie-1: #7434ED;
  --af-serie-2: #4B7DFA;
  --af-serie-3: #3DB18E;
  --af-serie-4: #FEAD6D;
  --af-serie-5: #FA92D0;
  --af-serie-6: #64C7E8;
  --af-serie-7: #C88BF0;
  --af-serie-8: #9AA5C4;
}


/* ═════════════════════════════════════════════════════════════════════════
   2. TOKENS SÉMANTIQUES — la couche que consomment les composants.
      Un composant demande un RÔLE (« la surface d'une carte »), jamais une
      couleur (« le neutre 25 »).
   ═════════════════════════════════════════════════════════════════════════ */

:root {

  /* ── Surfaces ──────────────────────────────────────────────────────────
     Le geste central du système, relevé sur les 7 planches : la carte se
     détache du canvas par son OMBRE, pas par son contraste. L'écart de
     luminance canvas→carte est volontairement faible (~4 %). Augmenter ce
     contraste « pour que ça se voie mieux » casserait le calme des
     maquettes — c'est l'ombre qu'il faut regarder, pas le fond. */
  --af-canvas:        var(--af-n-75);
  /* LA TOILE — le fond visible AUTOUR de la coquille, dans la marge de
     `.af-app`. Ce n'est pas `--af-canvas` : le canvas est le fond du
     CONTENU, la toile est ce sur quoi les panneaux sont posés. Elle est donc
     toujours d'un cran en retrait, dans les deux modes. */
  --af-toile:         var(--af-n-150);
  --af-surface:       var(--af-n-25);
  --af-surface-2:     var(--af-n-50);
  --af-surface-sunk:  var(--af-n-100);   /* champs, colonnes de kanban, pieds de tableau */
  --af-surface-hover: var(--af-n-100);

  /* Sidebar — surface sombre, son propre jeu de textes (voir --af-on-dark-*) */
  --af-nav-bg:        var(--af-n-900);
  /* ⚠️ ÉCART ASSUMÉ À LA MAQUETTE. Les planches montrent le pavé de nav actif
     dans un violet PROFOND (relevés #3E349B et #4D3098). Mesuré, ce violet ne
     se détache de la sidebar qu'à 2,04:1 — sous le seuil de 3:1 exigé pour un
     repère de composant (WCAG 1.4.11 : l'état « actif » en est un).
     Le violet vif y rend 3,30:1 tout en gardant du blanc lisible dessus
     (5,62:1). --af-accent-deep reste disponible pour les usages où le violet
     profond ne porte pas d'information (survol, filets). */
  --af-nav-item-active-bg: var(--af-v-500);
  --af-nav-item-hover-bg:  rgba(255, 255, 255, 0.06);

  /* ── Textes ────────────────────────────────────────────────────────────
     Quatre niveaux. La hiérarchie labels/valeurs passe désormais par la
     TAILLE, la GRAISSE et la COULEUR — plus par un contraste de police.
     (Révocation assumée de DESIGN.md D1 : les maquettes n'emploient qu'une
     seule famille. Cf. docs/diagnostic-refonte-ui.md §11.1.)

     ⚠️ Les quatre niveaux sont CALCULÉS, pas choisis à l'œil. Chacun tient
     son ratio sur le CANVAS (#F3F1FC), qui est le plus sombre des deux fonds
     clairs — un token calibré sur la carte échouerait sur le canvas.
     Mesuré : text-1 15,4:1 · text-2 7,6:1 · text-3 4,50:1 · text-4 3,01:1.
     Les valeurs relevées sur les maquettes (#767CA0 pour les libellés) ne
     passaient PAS le seuil AA (3,95:1) : elles ont été assombries à teinte et
     saturation constantes. C'est un écart assumé à la maquette. */
  --af-text-1: #14183A;   /* titres, valeurs, chiffres clés */
  --af-text-2: #4A5074;   /* texte courant, cellules */
  --af-text-3: #666D93;   /* libellés, méta, en-têtes de colonne */
  --af-text-4: #848AB0;   /* désactivé, filigrane */

  /* Textes sur surface sombre (sidebar). NE PAS réutiliser --af-text-* ici :
     ils sont calibrés pour du foncé-sur-clair et deviennent illisibles.
     Mesuré sur #0B1030 : 16,6:1 · 8,5:1 · 4,51:1. */
  --af-on-dark-1: #F3F1FC;
  --af-on-dark-2: #A9AECC;
  --af-on-dark-3: #757BA0;

  /* ── Bordures et filets ────────────────────────────────────────────────
     Jamais de bordure lourde dans les maquettes. Les séparations sont des
     filets de 1 px à très faible opacité. En rgba pour rester corrects
     par-dessus n'importe quelle surface. */
  --af-border:        rgba(20, 24, 58, 0.08);
  --af-border-strong: rgba(20, 24, 58, 0.14);
  --af-border-dark:   rgba(255, 255, 255, 0.08);   /* filets sur la sidebar */

  /* ── Accent ────────────────────────────────────────────────────────────
     --af-accent est la valeur PAR DÉFAUT. Elle est écrasée par la couleur
     d'accent du compte (users.accent_color), qui est conservée par la
     refonte — seul le système de THÈMES disparaît, pas la personnalisation. */
  --af-accent:       var(--af-v-500);
  --af-accent-hover: var(--af-v-600);
  --af-accent-deep:  var(--af-v-700);
  --af-accent-soft:  var(--af-v-50);
  --af-accent-rgb:   109, 70, 236;   /* = #6D46EC — pour rgba(var(--…), α) */
  --af-focus-ring:   0 0 0 3px rgba(109, 70, 236, 0.28);

  /* L'accent employé comme TEXTE (lien, valeur mise en avant) est un token
     distinct de l'accent employé comme REMPLISSAGE (bouton, pastille).
     En mode clair les deux coïncident (5,45:1 sur la carte). En mode sombre
     ils divergent : #6D46EC ne rend que 2,98:1 sur une carte sombre, alors
     que du blanc dessus en rend 5,62:1. Un seul token forcerait à choisir
     entre un bouton illisible et un lien illisible. */
  --af-accent-text:  var(--af-v-500);

  /* Texte posé SUR un aplat d'accent (libellé de bouton primaire, pavé de nav
     actif). Un token et non un `#fff` en dur, pour une raison concrète :
     users.accent_color est configurable par compte. Un accent clair — jaune,
     lime, pastel — rend le blanc illisible dessus.
     ✅ TRANCHÉ LE 2026-08-19, dans le sens « recalculé côté serveur » :
     `utils.accent.encre_sur()` choisit le blanc ou l'encre sombre par la
     formule WCAG et l'injecte en ligne avec la gamme. La valeur ci-dessous
     n'est donc plus que le défaut du violet — celui pour lequel le blanc est
     effectivement le bon choix. */
  --af-on-accent:    #FFFFFF;
  /* Voile posé sur un aplat d'accent : séparateur du bouton fendu, fond du
     compteur d'une chip active. Il SUIT l'encre : sur un accent clair, où
     l'encre passe au sombre, un voile blanc disparaîtrait. */
  --af-on-accent-veil: color-mix(in srgb, var(--af-on-accent) 22%, transparent);

  /* ── Typographie ───────────────────────────────────────────────────────
     Satoshi est auto-hébergée (static/fonts/satoshi) et déjà déclarée en
     @font-face dans style.css : AUCUNE dépendance nouvelle.
     --af-font-display : titres de page à empattements (arbitrage Q3).
     Playfair Display, retenu le 2026-08-17 — déjà chargée par un template du
     repo, donc pas de dépendance nouvelle. Repli Georgia, présente partout.
     ⚠️ Elle n'est PAS auto-hébergée : elle vient de Google Fonts, comme les
     15 autres requêtes de polices déjà éparpillées dans les templates. La
     Phase 1 les consolide en UNE seule requête déclarée dans base.html. */
  --af-font: 'Satoshi', 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
  --af-font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --af-font-numeric: var(--af-font);

  /* Échelle typographique — relevée sur les maquettes, pas déduite d'un ratio.
     Le saut brutal entre --fs-md (14) et --fs-2xl (30) est VOULU : les
     maquettes n'ont pas de tailles intermédiaires, elles opposent le texte
     de travail au chiffre qu'on vient lire.

     ⚠️ Un échelon supprimé : --af-fs-2xs (10 px) a été fusionné dans --fs-xs.
     Un rapport de 1,10 avec son voisin, pour deux tokens que l'œil ne
     distingue pas : les auteurs choisissaient au hasard et la « hiérarchie »
     n'était que du bruit. Les badges se distinguent déjà par leurs capitales
     et leur interlettrage, pas par 1 pixel.

     --fs-sm (13) et --fs-md (14) RESTENT proches (1,08), et c'est assumé :
     ces deux tailles ne se côtoient jamais dans un même bloc. 13 px est la
     densité des tableaux — sur une liste de factures à neuf colonnes, le
     pixel gagné par cellule décide de ce qui tient à l'écran. 14 px est le
     texte courant. Un rapport de hiérarchie ne s'applique pas entre deux
     tailles qui ne se comparent jamais. */
  --af-fs-xs:  11px;   /* badge, tag de phase, libellé, méta */
  --af-fs-sm:  13px;   /* cellule de tableau */
  --af-fs-md:  14px;   /* texte courant */
  --af-fs-lg:  16px;   /* titre de carte, titre de section */
  --af-fs-xl:  20px;
  --af-fs-2xl: 30px;   /* chiffre clé de carte KPI */
  --af-fs-3xl: 38px;   /* titre de page */

  --af-fw-regular: 400;
  --af-fw-medium:  500;   /* libellés */
  --af-fw-semi:    600;
  --af-fw-bold:    700;   /* valeurs, chiffres clés */

  /* Taille des icônes. Material Symbols se dimensionne par `font-size` :
     sans token, chaque site écrit ses pixels en dur et l'échelle se disperse.
     Trois tailles suffisent — mesuré sur les maquettes : l'icône accompagne
     soit un libellé, soit un texte courant, soit un titre de carte. */
  --af-ico-sm: 16px;   /* dans un libellé, un badge, une chip */
  --af-ico-md: 18px;   /* dans un bouton, une ligne de menu */
  --af-ico-lg: 24px;   /* pastille de carte KPI, état vide */

  --af-lh-tight: 1.15;    /* titres, chiffres */
  --af-lh-normal: 1.5;    /* texte courant */

  /* ── Espacements — grille de 4 px ──────────────────────────────────────
     Les maquettes sont sur une grille 4 px stricte. L'existant est sur une
     grille 2 px « de fait, non tokenisée » (DESIGN.md §1.5) : le passage à
     4 px est un resserrement volontaire, pas une divergence.
     Toute nouvelle valeur doit être un multiple de 4. */
  --af-sp-1:  4px;
  --af-sp-2:  8px;
  --af-sp-3:  12px;
  --af-sp-4:  16px;
  --af-sp-5:  20px;   /* gouttière entre cartes, padding interne de carte */
  --af-sp-6:  24px;
  --af-sp-8:  32px;
  --af-sp-10: 40px;
  --af-sp-12: 48px;
  --af-sp-16: 64px;

  /* ── Rayons — UNE seule échelle ────────────────────────────────────────
     Remplace les trois échelles concurrentes (Glass 28 / Rexora 12 /
     TermOS 8) et celle du module chantiers (28). */
  --af-r-xs:  4px;
  --af-r-sm:  6px;
  --af-r-md:  10px;   /* champ, bouton, chip */
  --af-r-lg:  12px;   /* vignette photo */
  --af-r-xl:  16px;   /* CARTE / BLOC — le rayon signature du système */
  --af-r-2xl: 20px;   /* modale */
  --af-r-pill: 999px; /* badge, tag, pilule */

  /* ── Ombres — une seule famille, douce et diffuse ──────────────────────
     Portée vers le bas, quasi sans teinte, jamais dure. C'est elle qui fait
     exister les cartes (cf. --af-surface). */
  --af-sh-1: 0 1px 2px rgba(16, 20, 50, 0.04),
             0 1px 3px rgba(16, 20, 50, 0.03);
  --af-sh-2: 0 2px 4px rgba(16, 20, 50, 0.04),
             0 8px 20px rgba(16, 20, 50, 0.06);   /* carte au repos */
  --af-sh-3: 0 12px 32px rgba(16, 20, 50, 0.10);  /* dropdown, popover */
  --af-sh-4: 0 24px 64px rgba(16, 20, 50, 0.16);  /* modale */
  --af-sh-nav: 0 0 0 1px rgba(255, 255, 255, 0.04) inset;

  /* ── Élévation (z-index) — échelle unique et explicite ─────────────────
     Aujourd'hui le repo empile des z-index arbitraires jusqu'à 99999.
     Toute nouvelle couche se place ICI, pas à la surenchère. */
  --af-z-base:      0;
  --af-z-sticky:    100;   /* en-tête de tableau collant */
  --af-z-nav:       200;   /* sidebar */
  --af-z-topbar:    300;
  --af-z-dropdown:  400;
  --af-z-overlay:   500;   /* voile de modale */
  --af-z-modal:     510;
  --af-z-popover:   600;   /* portalisé sur <body> */
  --af-z-toast:     700;
  --af-z-tooltip:   800;

  /* ── Durées et courbes ─────────────────────────────────────────────────
     ⚠️ RÈGLE ABSOLUE héritée (DESIGN.md §1.8) : une DONNÉE n'est jamais
     rendue visible par une animation. Elle est opaque par défaut ;
     l'animation n'est qu'un enrichissement. Ces tokens servent aux
     transitions d'ÉTAT (survol, ouverture), jamais à révéler un chiffre.

     Deux courbes suffisent, et il n'y en aura pas de troisième :
       --af-ease     : transitions d'état symétriques (survol, couleur)
       --af-ease-out : entrées et sorties (menu, modale, toast) — décélération
                       exponentielle, énergique sans jamais dépasser sa cible.

     ⚠️ PAS DE COURBE À REBOND (overshoot, type cubic-bezier(…, 1.4, …)).
     Ce n'est pas un oubli. Rien ne rebondit dans les sept planches : le
     langage y est calme — ombres diffuses, contrastes bas, aucun geste
     appuyé. Un dépassement élastique y sonnerait faux, et il vieillit mal.
     Si un composant semble en avoir besoin, c'est presque toujours qu'il est
     trop lent : raccourcir la durée avant d'ajouter du ressort. */
  --af-dur-instant: 80ms;
  --af-dur-fast:    140ms;
  --af-dur-normal:  220ms;
  --af-dur-slow:    380ms;
  --af-ease:        cubic-bezier(0.20, 0, 0.20, 1);
  --af-ease-out:    cubic-bezier(0.16, 1, 0.30, 1);

  /* ── Gabarit ───────────────────────────────────────────────────────────
     ⚠️ --af-bottombar-clearance : le conteneur de contenu réserve DÉJÀ
     104 px pour la bottombar (DESIGN.md §1.6). Ne pas redoubler cette garde
     dans un composant — c'est une erreur déjà commise. */
  --af-sidebar-w:           248px;
  --af-sidebar-collapsed-w: 72px;
  --af-topbar-h:            64px;
  --af-bottombar-clearance: 104px;
  --af-content-max:         1440px;
}


/* ═════════════════════════════════════════════════════════════════════════
   3. PONT LEGACY — les noms historiques pointent sur les nouveaux tokens.
      C'est ce qui fait basculer l'application entière sur la nouvelle
      palette sans réécrire les 33 744 lignes de CSS existantes.

      Chaque ligne porte son nombre d'usages mesuré : c'est ce qui dira,
      en Phase 4, laquelle peut être retirée sans risque.

   ⚠️ POURQUOI `html[data-design]` ET NON `:root` — CORRIGÉ LE 2026-08-17.
   Ce bloc était en `:root`, soit une spécificité de (0,1,0). Or plusieurs
   feuilles héritées redéfinissent les MÊMES noms derrière un attribut de
   même spécificité, et elles sont chargées après :
     · `style.css:192`     [data-theme="light"] → --acc: #E5391C (rouge)
     · `style.css:11723`   [data-color-theme="steel"] → --acc: #D4AF37 (or)
     · idem pour --t1..--t4, --text-*, --ok, --err…
   À égalité de spécificité, le dernier chargé gagne. Le pont perdait donc
   silencieusement : la page affichait la coquille en violet et TOUT le
   reste — courbes, pills, barres — dans la teinte héritée. On l'a vu trois
   fois de suite en croyant chaque fois avoir trouvé la dernière source.

   `html[data-design="archiflow"]` vaut (0,2,0) : il gagne par SPÉCIFICITÉ,
   donc indépendamment de l'ordre de chargement. C'est la seule façon de
   tenir la promesse du pont sans toucher aux 26 feuilles.
   ═════════════════════════════════════════════════════════════════════════ */

/* Le pont vaut pour les deux thèmes de la refonte : il traduit des NOMS,
   pas des valeurs. Chacun résout les mêmes `var(--af-*)`, redéfinis par
   le bloc §6 sous `html[data-design="atelier"]`. */
html[data-design="archiflow"],
html[data-design="atelier"] {
  /* Accent — 877 + 655 usages */
  --acc:     var(--af-accent);
  --accl:    var(--af-v-400);
  --accd:    var(--af-accent-hover);
  --acc-rgb: var(--af-accent-rgb);
  --accent:  var(--af-accent);          /* alias, 201 usages */
  --ink:     var(--af-text-1);          /* 100 usages */

  /* Textes — 625 + 625 + 441 + 73 usages */
  --t1: var(--af-text-1);
  --t2: var(--af-text-2);
  --t3: var(--af-text-3);
  --t4: var(--af-text-4);
  --text-primary:   var(--af-text-1);   /* 143 usages */
  --text-secondary: var(--af-text-2);   /* 100 usages */
  --text-muted:     var(--af-text-3);   /* 214 usages */
  --mute:           var(--af-text-3);   /*  84 usages */

  /* Surfaces — 232 + 105 + 86 usages */
  --bg:    var(--af-canvas);
  --bg2:   var(--af-surface-2);
  --card:  var(--af-surface);
  --card2: var(--af-surface-2);
  --inp:   var(--af-surface-sunk);
  --surface-1:     var(--af-surface);
  --surface-2:     var(--af-surface-2);
  --surface-hover: var(--af-surface-hover);

  /* Bordures — 576 + 138 usages */
  --brd:    var(--af-border);
  --border: var(--af-border);

  /* Statuts — 144 + 131 usages.
     ⚠️ Ces couleurs ne suivent JAMAIS l'accent : une facture payée reste
     verte quelle que soit la palette du compte. Registre : utils/statuts.py,
     source unique — ne jamais écrire un hex de statut en dur. */
  --ok:   var(--af-ok);
  --err:  var(--af-err);
  --warn: var(--af-warn);
  --info: var(--af-info);

  /* Typographie — 508 + 274 + 75 usages.
     --f-mono et --f-numeric pointent désormais sur la police unique : le
     contraste de familles labels/valeurs est révoqué (D1, cf. §11.1 du
     diagnostic). Les noms restent le temps de la migration. */
  --f:  var(--af-font);
  --fm: var(--af-font);
  --fd: var(--af-font);
  --fs: var(--af-font);
  --font-body:    var(--af-font);
  --font-heading: var(--af-font);
  --f-btn:        var(--af-font);
  --f-mono:       var(--af-font);
  --f-numeric:    var(--af-font-numeric);

  /* Rayons — 189 usages pour --r-pill.
     ⚠️ L'échelle historique était 4/6/8/10 (Glass). Les nouvelles valeurs
     sont plus généreuses, conformément aux maquettes : un composant non
     encore refondu s'arrondira davantage. C'est voulu et visible — c'est ce
     qui permet de repérer à l'œil ce qui n'est pas encore passé. */
  --r-sm: var(--af-r-xs);
  --r-md: var(--af-r-sm);
  --r-lg: var(--af-r-md);
  --r-xl: var(--af-r-lg);
  --r:    var(--af-r-md);
  --r-pill: var(--af-r-pill);
  --radius-sm:   var(--af-r-xs);
  --radius-md:   var(--af-r-sm);
  --radius-lg:   var(--af-r-md);
  --radius-xl:   var(--af-r-lg);
  --radius-full: var(--af-r-pill);
  --radius-block: var(--af-r-xl);       /* 28 / 12 / 8 → 16 px unique */
  --r-card:  var(--af-r-xl);
  --r-input: var(--af-r-md);
  --r-icon:  var(--af-r-md);
  --r-block: var(--af-r-xl);
  --r-compact: var(--af-r-sm);

  /* Gabarit */
  --sidebar-width:           var(--af-sidebar-w);
  --sidebar-collapsed-width: var(--af-sidebar-collapsed-w);

  /* Modales */
  --modal-backdrop: rgba(11, 16, 48, 0.40);
  --modal-surface:  var(--af-surface);
  --modal-border:   1px solid var(--af-border);
  --modal-shadow:   var(--af-sh-4);
  --modal-radius:   var(--af-r-2xl);

  /* Infobulles de graphique — tokens lus AU RENDU par charts-orbit.js.
     ⚠️ Un canvas ne résout pas var() : la config Chart.js passe des
     FONCTIONS qui relisent ces variables, pour suivre un changement sans
     rechargement. Ne pas les re-figer en valeurs littérales (DESIGN.md §1.9). */
  --orbit-tt-bg: var(--af-n-900);
  --orbit-tt-fg: var(--af-on-dark-1);
  --orbit-tt-bd: rgba(255, 255, 255, 0.10);
}


/* ═════════════════════════════════════════════════════════════════════════
   4. ACCENT PERSONNALISÉ PAR COMPTE — conservé par la refonte.
      Seul le système de THÈMES disparaît. users.accent_color reste, et
      continue d'être posé en ligne sur <html> par le serveur.
      Ce bloc n'existe que pour documenter le point d'entrée : la valeur
      réelle est injectée côté serveur, pas ici.
   ═════════════════════════════════════════════════════════════════════════ */

/* Le serveur pose sur <html>, en ligne, la GAMME entière (--af-v-50 …
   --af-v-900) dérivée de users.accent_color — pas seulement --af-accent.
   Tout ce qui lit la gamme suit donc : le pavé de nav actif, les dégradés du
   rail, la pastille d'icône des cartes KPI, le violet de ChantierFlow.
   Écrit en ligne, l'accent du compte gagne la cascade : rien à forcer ici,
   et surtout aucun !important. Cf. utils/accent.py.

   ⚠️ DEUX VALEURS NE SE DÉRIVENT PAS DE LA GAMME et doivent être reprises
   quand une teinte est choisie : celles du mode sombre, écrites en dur parce
   qu'elles ont été CALIBRÉES sur le violet (cf. §5). On ne les remplace donc
   PAS par défaut — seulement quand le compte a choisi sa teinte, auquel cas
   la calibration violette ne veut plus rien dire de toute façon.
   Le sélecteur porte sur l'attribut `style` : c'est la marque de l'injection
   serveur, et il donne la spécificité (0,2,1) qui bat le bloc de §5. */
html[style*="--af-v-500"][data-theme="dark"] {
  --af-accent-text: var(--af-v-300);
  --af-accent-soft: color-mix(in srgb, var(--af-v-500) 18%, transparent);
}


/* ═════════════════════════════════════════════════════════════════════════
   5. MODE SOMBRE — conservé (décision du 2026-08-17), et EXTRAPOLÉ.

   ⚠️ AUCUNE MAQUETTE NE COUVRE CE MODE. Les 7 planches sont en canvas clair.
   Ce bloc n'est donc pas un relevé : c'est une déduction, calculée depuis les
   mêmes primitives et vérifiée par `tests/test_archiflow_tokens.py`.
   Il doit être validé à l'œil en Phase 1d au même titre que le mode clair —
   il n'a pas de maquette pour arbitrer à notre place.

   ─── L'INVERSION À COMPRENDRE AVANT DE TOUCHER À CE BLOC ────────────────
   En mode clair, le geste central du système est : « la carte se détache par
   son OMBRE, pas par son contraste » — écart carte/canvas de 1,08:1 seulement.

   Ce geste ne se transpose PAS. En mode sombre une ombre portée est
   invisible : reproduire 1,08:1 ferait littéralement disparaître les cartes.
   L'élévation s'y lit donc en CLARTÉ — la carte est plus CLAIRE que le
   canvas, écart porté à 1,27:1.

   C'est pourquoi le banc pose un PLAFOND de détachement en clair et un
   PLANCHER en sombre. Aligner les deux serait casser l'un ou l'autre.
   ═════════════════════════════════════════════════════════════════════════ */

html[data-theme="dark"] {

  /* ── Surfaces — TROIS MARCHES, et la sidebar MONTE ─────────────────────
     ⚠️ Première version corrigée après rendu réel : la sidebar y était la
     surface la plus sombre (#060A1E sur un canvas #0B1030, soit 1,06:1) et
     elle DISPARAISSAIT à l'écran. Le plancher de luminance interdit de
     contraster deux surfaces quasi noires : descendre encore ne donnait que
     1,10:1 au mieux.
     La sidebar monte donc AU-DESSUS du canvas, comme les cartes montent
     au-dessus d'elle. C'est cohérent avec le principe du mode sombre —
     l'élévation se lit en clarté — et ça redonne à la sidebar son rôle de
     bloc d'ancrage, qu'elle tient naturellement en mode clair.
     Mesuré : sidebar/canvas 1,22:1 · carte/canvas 1,48:1 · carte/sidebar 1,21:1 */
  /* ⚠️ LA NUIT EST GRISE DEPUIS LE 2026-08-24, ELLE ÉTAIT BLEU-NUIT.
     Demande de Jérôme, en toutes lettres : « pour la version nuit de tout le
     site je préfère des nuances de gris foncé ». Les valeurs ne sont pas
     choisies à l'œil : ce sont les MÊMES ÉCARTS DE LUMINANCE que la palette
     bleu-nuit qu'elles remplacent, transposés en neutre — sidebar/canvas
     1,21:1 et carte/canvas 1,47:1, mesurés sur les deux jeux. C'est ce qui
     permet de changer la teinte sans rejouer tout le calibrage des textes.
     Un gris rigoureusement neutre (r = g = b) rend une interface morte : les
     bleus sont 2 à 4 points au-dessus des rouges. On le voit à peine, on le
     verrait si ce n'était pas là. */
  --af-canvas:        #0F0F11;   /* la surface la plus sombre */
  --af-toile:         #0B0B0D;   /* la marge, un cran sous le canvas */
  --af-surface:       #313135;   /* carte */
  --af-surface-2:     #3A3A40;
  --af-surface-sunk:  #0F0F11;   /* champs : ils RECULENT jusqu'au canvas */
  --af-surface-hover: #3A3A40;

  --af-nav-bg:             #222225;   /* entre le canvas et les cartes */
  /* ⚠️ ÉCLAIRCI AVEC LA SIDEBAR (2026-08-24). Il valait #714BEC, calibré à
     3,02:1 sur la sidebar bleu-nuit ; sur le gris #222225 il retombait à
     2,96:1 — sous le seuil d'un repère de composant. La barre n'en fait plus
     un pavé, mais la page « design system » l'emploie toujours comme aplat :
     un token qui ne tient plus son contraste est un piège pour le prochain
     qui le consommera. */
  --af-nav-item-active-bg: #7C57F0;   /* 3,37:1 sur la sidebar grise */
  --af-nav-item-hover-bg:  rgba(255, 255, 255, 0.07);

  /* ── Textes — recalculés sur la CARTE, pas transposés ──────────────────
     En sombre c'est la carte qui contraint (c'est le fond le plus clair),
     exactement l'inverse du mode clair où c'est le canvas.
     Mesuré : 12,01 · 7,24 · 4,51 · 3,00. Écarts entre niveaux voisins :
     1,66 · 1,61 · 1,50 — la hiérarchie reste lisible, comme en clair. */
  /* Recalculés sur la nouvelle carte (#313135), pas transposés : le violet
     des anciens niveaux jurait sur du gris, et --af-text-3 y tombait à
     4,29:1 — sous le seuil AA qu'il tenait sur le bleu-nuit.
     Mesuré : 11,55 · 7,36 · 5,26 · 3,37. */
  --af-text-1: #F2F2F4;
  --af-text-2: #C2C3C8;
  --af-text-3: #A3A5AC;
  --af-text-4: #808289;

  /* Sur la sidebar (#222225) : 14,10 · 7,40 · 4,52 */
  --af-on-dark-1: #F2F2F4;
  --af-on-dark-2: #B1B1B6;
  --af-on-dark-3: #898990;

  /* ── Bordures — elles portent plus qu'en clair ─────────────────────────
     Aucune opacité de blanc raisonnable n'atteint 3:1 sur une carte sombre
     (22 % plafonne à 2,01:1). La délimitation des cartes est donc portée par
     la CLARTÉ de la surface, la bordure ne fait que l'appuyer. Ne pas
     compenser en montant l'opacité : à 30 % le filet devient un trait. */
  --af-border:        rgba(255, 255, 255, 0.12);
  --af-border-strong: rgba(255, 255, 255, 0.20);
  --af-border-dark:   rgba(255, 255, 255, 0.08);

  /* ── Accent ────────────────────────────────────────────────────────────
     Le remplissage NE bouge PAS (#6D46EC porte du blanc à 5,62:1 sur les
     deux modes). Seul l'accent-TEXTE est éclairci : #6D46EC ne rend que
     2,98:1 sur une carte sombre. */
  /* ⚠️ Calibré non pas sur la carte NUE mais sur la carte + --af-accent-soft,
     parce que c'est là que ce texte vit réellement : sous-navigation active,
     compteur d'onglet actif, bouton fantôme au survol. Sur la carte nue il
     rendait 4,50:1, mais 3,78:1 une fois le voile d'accent posé dessous —
     le voile ÉCLAIRCIT le fond et mange le contraste. Réduire l'alpha ne
     suffisait pas : à 0,08 on plafonnait encore à 4,24:1 pour un voile
     devenu invisible.
     Mesuré : 4,54:1 sur le voile · 5,23:1 sur la carte · 7,73:1 sur le canvas. */
  /* ⚠️ ÉCLAIRCI LUI AUSSI. Il tenait 4,54:1 sur le voile d'accent posé sur
     la carte bleu-nuit ; la carte grise (#313135) compose un voile plus
     clair (#3C3556) où il retombait à 4,46:1. Il sert désormais AUSSI
     d'encre à l'icône de nav active (le pavé a disparu) : 6,60:1 sur la
     sidebar. Mesuré : 4,85:1 sur le voile · 5,58:1 sur la carte. */
  --af-accent-text: #B09AF6;
  --af-accent-soft: rgba(109, 70, 236, 0.18);

  /* ── Badges sémantiques — fonds teintés SOMBRES, encres claires ────────
     Les fonds -soft du mode clair (#D6EDE2, #FDEDE3…) sont des pastels : ils
     éblouiraient sur une interface sombre.
     ⚠️ Un badge doit aussi se détacher de la CARTE qui le porte, pas
     seulement rendre son texte lisible. La première version l'oubliait : les
     fonds tombaient à 1,00–1,12:1 de la carte et le badge « Brouillon »
     n'existait plus qu'en tant que texte — vu au rendu, pas prédit.
     Chaque fond est donc calé à 1,25:1 de la carte, en restant PLUS SOMBRE
     qu'elle. Encre sur fond : 9,80 · 9,31 · 7,30 · 7,93 · 7,68. */
  --af-ok-ink:    #6FD9AE;
  --af-ok-soft:   #042217;
  --af-warn-ink:  #F5B473;
  --af-warn-soft: #2D1904;
  --af-err-ink:   #F58C9B;
  --af-err-soft:  #3F070E;
  --af-info-ink:  #8FB2FA;
  --af-info-soft: #051A49;
  --af-mute-ink:  #B1B1B6;
  --af-mute-soft: #1D1D21;

  /* ── Ombres — conservées mais assumées comme décoratives ───────────────
     Sur fond sombre elles ne séparent plus rien (cf. l'inversion ci-dessus).
     On les garde pour l'ancrage des couches flottantes (modale, popover),
     renforcées en opacité pour rester perceptibles. */
  --af-sh-1: 0 1px 2px rgba(0, 0, 0, 0.30);
  --af-sh-2: 0 2px 4px rgba(0, 0, 0, 0.28),
             0 8px 20px rgba(0, 0, 0, 0.32);
  --af-sh-3: 0 12px 32px rgba(0, 0, 0, 0.46);
  --af-sh-4: 0 24px 64px rgba(0, 0, 0, 0.58);

  /* ── Séries de graphiques ──────────────────────────────────────────────
     Les teintes catégorielles restent identiques : elles sont déjà calibrées
     pour tenir sur les deux fonds, et les faire varier par mode rendrait deux
     captures du même graphique non comparables. */
}

/* Le pont legacy suit automatiquement : il pointe sur les tokens sémantiques
   ci-dessus, redéfinis par ce bloc. Aucune duplication n'est nécessaire —
   et surtout, aucune ne doit être ajoutée : ce serait deux sources de vérité. */
html[data-theme="dark"] {
  --modal-backdrop: rgba(0, 0, 0, 0.72);
  --orbit-tt-bg:    #3A3A40;
  --orbit-tt-fg:    #F3F1FC;
  --orbit-tt-bd:    rgba(255, 255, 255, 0.16);
}


/* ═════════════════════════════════════════════════════════════════════════
   6. ACCESSIBILITÉ — mouvement réduit.
      Un seul reset, global, comme aujourd'hui (DESIGN.md §1.8).
   ═════════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  :root {
    --af-dur-instant: 0ms;
    --af-dur-fast:    0ms;
    --af-dur-normal:  0ms;
    --af-dur-slow:    0ms;
  }
}


/* ═════════════════════════════════════════════════════════════════════════
   6. ATELIER · FONDU — le thème de la refonte 2026-09
      Transposition web de la maquette mobile
      (docs/design/refonte-2026-09/maquette-atelier-fondu-web.html).

      POURQUOI UN BLOC ET PAS UN FICHIER. Tout est déjà en place : les
      composants consomment la couche sémantique --af-*, et le pont legacy
      traduit les ~4 000 usages historiques. Redéfinir les PRIMITIVES sous
      `html[data-design="atelier"]` fait donc basculer l'application entière
      sans toucher une ligne des 26 autres feuilles. C'est exactement ce
      pourquoi le pont a été construit.

      ⚠️ CE QUE CE BLOC NE FAIT PAS. Il change la matière, pas la structure.
      Les pilules anthracite, les cartes à photo fondue, le tableau atelier,
      le rail de 76 px — tout cela demande du MARKUP, donc la Phase 3. Ici,
      l'accent devient orange, la page devient blanc cassé, les rayons
      s'arrondissent, la sidebar s'éclaircit. Ce qui n'est pas encore refondu
      se verra : c'est voulu, c'est le repère de ce qui reste à faire.

      ─── ÉCARTS ASSUMÉS À LA MAQUETTE MOBILE ────────────────────────────
      La maquette est une image ; elle n'a pas d'obligation de lisibilité.
      Trois valeurs ont été remontées à teinte constante, exactement comme
      la §12.2 du diagnostic l'avait fait pour le violet :

        · `ink3 #9C9CA4` rend 2,46:1 sur la page — il porte les libellés et
          les métas. Descendu d'un rang : il devient --af-text-4 (désactivé,
          3,09:1) et --af-text-3 prend #6E6E76 (4,57:1).
        · `accent-deep #B0421A` sur l'étiquette pêche rend 4,44:1 pour un
          texte de 9,5 px. Assombri à #A03B17 (5,16:1).
        · L'accent en TEXTE (lien, valeur) : #F0561F ne rend que 3,47:1 sur
          une carte. Le token de texte prend #C7481A (4,81:1) ; le
          remplissage garde l'orange exact de la maquette.

      Le texte posé SUR un aplat d'accent est l'ENCRE, pas le blanc :
      #1B1B1F sur #F0561F rend 4,95:1, le blanc seulement 3,47:1.
   ═════════════════════════════════════════════════════════════════════════ */

html[data-design="atelier"] {
  /* ⚠️ LES MÊMES COULEURS SOUS LEURS AUTRES NOMS, ET SEULEMENT POUR CE THÈME.
     `theme.css:70` définit `--success/--danger/--warning`, que des gabarits
     entiers consomment (pastille de statut, barre d'encaissement, coches de
     suivi). Sans ce pont ils gardaient l'émeraude et le rouge vif de Glass au
     milieu d'un thème qui n'admet qu'un accent — relevé à la sonde sur la
     fiche facture le 2026-09-09.
     ⚠️ PAS dans le pont de la §6 : celui-là couvre AUSSI Rexora Renew, et
     Renew doit garder ses couleurs. Ici, la portée est le seul thème. */
  --success: var(--af-ok);
  --danger:  var(--af-err);
  --warning: var(--af-warn);

  /* ── Neutres — gris chaud. Le gris bleuté du violet n'a plus cours ─────
     Relevés de la maquette : page #F4F3F4, carte #FFF, surface douce
     #F1F0F2, filet #ECEBEE, anthracite #26262B, encre #1B1B1F. */
  --af-n-950: #0F0F12;
  --af-n-900: #1B1B1F;   /* encre */
  --af-n-850: #202024;
  --af-n-800: #26262B;   /* ANTHRACITE — pilules, onglet actif, panneau */
  --af-n-700: #303036;
  --af-n-600: #4E4E55;
  --af-n-500: #6E6E76;
  --af-n-400: #8A8A92;
  --af-n-300: #9C9CA4;
  --af-n-200: #D5D4D8;
  --af-n-150: #ECEBEE;   /* filet */
  --af-n-100: #F1F0F2;   /* surface douce DANS une carte */
  --af-n-75:  #F4F3F4;   /* LA PAGE — jamais #FFF, c'est la règle §6 */
  --af-n-50:  #FAFAFA;
  --af-n-25:  #FFFFFF;   /* carte */
  --af-n-0:   #FFFFFF;

  /* ── Accent — UN SEUL orange, et il ne sert qu'à signaler ─────────────
     La gamme garde les écarts de clarté de la gamme violette d'origine :
     c'est ce qui permet au reste du système (rail, focus, pastilles) de
     continuer à fonctionner sans être réécrit. */
  --af-v-900: #6B270E;
  --af-v-800: #8E3413;
  --af-v-700: #A03B17;   /* texte sur pastel pêche — 5,16:1 */
  --af-v-600: #C7481A;   /* accent en TEXTE — 4,81:1 sur carte */
  --af-v-500: #F0561F;   /* SIGNAL — pastille, coche, pin, jauge */
  --af-v-400: #F5834F;
  --af-v-300: #F8A984;
  --af-v-200: #FBDCC8;   /* étiquette pêche (fond) */
  --af-v-100: #FCE7D8;
  --af-v-50:  #FDF1E9;

  /* ── Statuts — les quatre pastels, jamais une couleur pleine ──────────
     §7.1 de la spec : un vert saturé et un rouge saturé sur le même écran
     font deux accents de plus. Les états passent par les pastels. */
  --af-ok-ink:   #3D6B45;
  --af-ok:       #3D6B45;
  --af-ok-soft:  #DFE9DC;   /* 4,97:1 pour le texte posé dessus */

  --af-warn-ink: #A03B17;
  --af-warn:     #C7481A;
  --af-warn-soft:#FBDCC8;   /* 5,16:1 */

  --af-err-ink:  #B03A47;
  --af-err:      #B03A47;
  --af-err-soft: #F9D9DC;   /* 4,51:1 */

  --af-info-ink: #2B5E9C;
  --af-info:     #2B5E9C;
  --af-info-soft:#D9E8F7;   /* 5,29:1 */

  --af-mute-ink: #4E4E55;
  --af-mute:     #6E6E76;
  --af-mute-soft:#E7E6EA;   /* 1,24:1 de la carte — #F1F0F2 s'y évaporait */

  /* ── Séries — catégorielles, elles ne suivent pas l'accent ────────────
     Tirées des tons profonds du thème : aucune couleur nouvelle. */
  --af-serie-1: #3D6B45;
  --af-serie-2: #2B5E9C;
  --af-serie-3: #B03A47;
  --af-serie-4: #C7481A;
  --af-serie-5: #6E6E76;
  --af-serie-6: #8FA8B8;
  --af-serie-7: #A08A6E;
  --af-serie-8: #26262B;

  /* ── Surfaces ─────────────────────────────────────────────────────────
     La carte se détache par son OMBRE : 1,11:1 avec la page, sous le
     plafond de 1,25 que le banc impose. */
  --af-canvas:        #F4F3F4;
  --af-toile:         #ECEBEE;
  --af-surface:       #FFFFFF;
  --af-surface-2:     #FAFAFA;
  --af-surface-sunk:  #F1F0F2;
  --af-surface-hover: #F1F0F2;

  /* ── La barre latérale devient CLAIRE ─────────────────────────────────
     C'est le changement le plus visible du thème, et il est délibéré : dans
     « Atelier · Fondu » le châssis ne s'oppose pas au contenu, il le porte.
     Les textes « sur fond sombre » deviennent donc des encres — sans ça,
     un #F3F1FC sur #F4F3F4 disparaîtrait purement et simplement. */
  --af-nav-bg:             #F4F3F4;
  --af-nav-item-active-bg: #F0561F;
  --af-nav-item-hover-bg:  rgba(20, 20, 30, 0.05);
  --af-on-dark-1: #1B1B1F;   /* 15,51:1 */
  --af-on-dark-2: #4E4E55;   /*  7,46:1 */
  --af-on-dark-3: #6E6E76;   /*  4,57:1 — le plancher AA, pas en dessous */

  /* ⚠️ ET L'INFOBULLE DES GRAPHIQUES DOIT ÊTRE REPRISE ICI, SINON ELLE
     DISPARAÎT. Le bloc commun pose `--orbit-tt-fg: var(--af-on-dark-1)` :
     ailleurs, « texte sur fond sombre » vaut du blanc cassé. Ici,
     `--af-on-dark-1` vient d'être redéfini en ENCRE (juste au-dessus, parce
     que la barre latérale du thème est claire) — et l'infobulle se retrouvait
     avec un fond #1B1B1F et un texte #1B1B1F. Noir sur noir : la pilule
     s'affichait, vide. Signalé par Jérôme le 2026-09-10 sur « Évolution CA
     mensuel ».
     La pilule reste sombre — c'est sa forme dans toutes les planches — et son
     texte redevient blanc. C'est le seul endroit du thème où du blanc sur
     anthracite est la bonne réponse, et c'est parce que la surface EST
     anthracite. */
  --orbit-tt-bg: var(--af-n-800);
  --orbit-tt-fg: #FFFFFF;
  --orbit-tt-bd: transparent;
  /* ⚠️ La barre latérale est AFFLEURANTE : elle a exactement la couleur de
     la page. Ce n'est pas un oubli, c'est le geste du thème — le châssis ne
     s'oppose pas au contenu. Le banc impose normalement 1,15:1 entre la
     sidebar et le canvas ; ce drapeau lui dit que l'écart est délibéré, et
     il exige alors que le pavé actif, lui, tranche (≥ 3:1). */
  --af-nav-flush: 1;

  /* ── Textes — l'échelle du mobile, remontée d'un rang (voir en-tête) ── */
  --af-text-1: #1B1B1F;   /* 15,51:1 */
  --af-text-2: #4E4E55;   /*  7,46:1 */
  --af-text-3: #6E6E76;   /*  4,57:1 — libellés, métas, en-têtes */
  --af-text-4: #8A8A92;   /*  3,09:1 — désactivé */

  /* ── Filets — la maquette n'a AUCUNE bordure sur les cartes ───────────
     Le filet ne sert plus qu'à séparer des rangées à l'intérieur d'un bloc. */
  --af-border:        #ECEBEE;
  --af-border-strong: #D5D4D8;
  --af-border-dark:   rgba(20, 20, 30, 0.08);

  /* ── Accent, tokens sémantiques ───────────────────────────────────────
     ⚠️ Valeurs LITTÉRALES, pas `var(--af-v-500)`. La teinte du compte est
     injectée en ligne sur <html> (utils/accent.py) et écraserait la gamme :
     un accent violet ferait revenir deux accents sur l'écran, ce que la
     §6 de la spec interdit. `base.html` cesse d'ailleurs d'injecter la
     gamme sous ce thème. */
  --af-accent:       #F0561F;
  --af-accent-hover: #C7481A;
  --af-accent-deep:  #A03B17;
  --af-accent-soft:  #FBDCC8;
  --af-accent-rgb:   240, 86, 31;
  --af-accent-text:  #C7481A;   /* 4,81:1 — le lien, la valeur mise en avant */
  --af-on-accent:    #1B1B1F;   /* 4,95:1 — l'encre, pas le blanc (3,47:1) */
  --af-focus-ring:   0 0 0 3px rgba(240, 86, 31, 0.28);

  /* ── Rayons — l'échelle de la maquette. Un rayon est une signature ──── */
  --af-r-xs:  8px;
  --af-r-sm:  10px;
  --af-r-md:  14px;   /* champ, bouton, chip */
  --af-r-lg:  18px;   /* vignette photo */
  --af-r-xl:  24px;   /* CARTE / BLOC */
  --af-r-2xl: 28px;   /* modale, panneau */
  --af-r-pill: 999px;

  /* ── Ombres — les deux couches de la maquette, natives en CSS ───────── */
  --af-sh-1: 0 1px 2px rgba(20, 20, 30, 0.04);
  --af-sh-2: 0 2px 6px -2px rgba(20, 20, 30, 0.06),
             0 18px 36px -20px rgba(20, 20, 30, 0.28);
  --af-sh-3: 0 6px 14px -6px rgba(20, 20, 30, 0.12),
             0 30px 60px -24px rgba(20, 20, 30, 0.38);
  --af-sh-4: 0 6px 14px -6px rgba(20, 20, 30, 0.12),
             0 30px 60px -24px rgba(20, 20, 30, 0.38);
  --af-sh-nav: none;

  /* ── Typographie — Satoshi seule ──────────────────────────────────────
     Révoque Q3/Q11 : plus de titres à empattements. La maquette n'a qu'une
     famille, et son contraste vient des graisses. */
  --af-font-display: var(--af-font);

  /* Voile de modale : l'écran se dépolit, il ne se teinte pas. */
  --modal-backdrop: rgba(120, 118, 126, 0.32);
}


/* ── Atelier · Fondu, mode sombre ─────────────────────────────────────────
   ⚠️ EXTRAPOLATION, pas un relevé : la maquette mobile est claire, et rien
   d'autre. Construit sur la même règle que le sombre existant — en sombre
   l'élévation se lit en CLARTÉ, pas en ombre portée : la carte est plus
   claire que la page (1,22:1, au-dessus du plancher de 1,20 du banc), alors
   qu'en clair elle est plus claire de 1,11:1 et c'est l'ombre qui la pose.
   Reproduire le geste clair ici ferait disparaître les cartes.
   ═══════════════════════════════════════════════════════════════════════ */
html[data-design="atelier"][data-theme="dark"] {
  --af-canvas:        #111114;
  --af-toile:         #0A0A0C;
  --af-surface:       #242429;   /* 1,22:1 avec la page */
  --af-surface-2:     #2B2B31;
  --af-surface-sunk:  #0C0C0E;
  --af-surface-hover: #2B2B31;

  /* En sombre la sidebar ne peut PAS être affleurante : sans ombre, deux
     surfaces quasi noires ne se séparent plus. Elle monte donc d'un cran. */
  --af-nav-flush: 0;
  --af-nav-bg:             #202025;   /* 1,16:1 avec la page */
  --af-nav-item-active-bg: #F0561F;
  --af-nav-item-hover-bg:  rgba(255, 255, 255, 0.07);
  --af-on-dark-1: #F2F2F4;
  --af-on-dark-2: #B1B1B6;
  --af-on-dark-3: #898990;

  --af-text-1: #F2F2F4;   /* 13,82:1 sur la carte */
  --af-text-2: #C6C6CC;   /*  9,55:1 */
  --af-text-3: #A2A2AA;   /*  6,09:1 */
  --af-text-4: #84848C;   /*  4,16:1 */

  --af-border:        rgba(255, 255, 255, 0.09);
  --af-border-strong: rgba(255, 255, 255, 0.16);

  /* L'orange plein reste le signal ; en TEXTE il s'éclaircit, sinon il
     tombe à 4,68:1 là où sa version claire tenait 4,81:1 sur blanc. */
  --af-accent:       #F0561F;
  --af-accent-hover: #F5834F;
  --af-accent-deep:  #F8A984;
  --af-accent-text:  #F5834F;   /* 6,06:1 */
  --af-accent-soft:  rgba(240, 86, 31, 0.18);
  --af-on-accent:    #1B1B1F;

  /* Les pastels ne survivent pas au mode sombre : on garde le RÔLE, on
     inverse le couple fond/encre.
     ⚠️ ET LE FOND MONTE, IL NE DESCEND PAS. Premier jet : des fonds plus
     SOMBRES que la carte (#1B2A20, #2D1A0E…). Mesuré : 1,03 à 1,10:1 de la
     carte — le badge n'existait plus en tant qu'objet, il ne restait que son
     texte. En sombre, deux surfaces quasi noires ne se séparent plus ; c'est
     la clarté qui porte l'élévation, exactement comme pour la carte. Les
     fonds sont donc plus CLAIRS que la carte, teinte conservée. */
  --af-ok-ink:    #9FD3AC;
  --af-ok-soft:   #2C3A30;   /* 1,29:1 de la carte · encre 7,06:1 */
  --af-warn-ink:  #F7B084;
  --af-warn-soft: #442F1E;   /* 1,23:1 · 6,88:1 */
  --af-err-ink:   #F4AEB7;
  --af-err-soft:  #412D35;   /* 1,22:1 · 7,01:1 */
  --af-info-ink:  #9CC6F0;
  --af-info-soft: #293845;   /* 1,28:1 · 6,73:1 */
  --af-mute-ink:  #C6C6CC;
  --af-mute-soft: #33333A;   /* 1,23:1 · 7,37:1 */

  --af-sh-1: 0 1px 2px rgba(0, 0, 0, 0.30);
  --af-sh-2: 0 2px 6px -2px rgba(0, 0, 0, 0.36), 0 18px 36px -20px rgba(0, 0, 0, 0.60);
  --af-sh-3: 0 12px 32px rgba(0, 0, 0, 0.46);
  --af-sh-4: 0 24px 64px rgba(0, 0, 0, 0.55);

  --modal-backdrop: rgba(8, 8, 10, 0.62);
}
