/* ═══════════════════════════════════════════════════════════════════════════
   PECUNNIA — LE SYSTÈME. Un seul fichier, deux thèmes.

   POURQUOI CE FICHIER EXISTE (2026-09-07). L'audit du même jour a compté 116
   tailles de texte dont AUCUNE ne passait par un jeton, 24 rayons numériques
   distincts, 65 ombres, 96 hexadécimaux et 161 rgba. Mais le chiffre qui
   commande tous les autres est ailleurs : 33 des 57 gabarits n'étendent pas
   base.html, ne chargent donc pas style.css, et n'avaient AUCUN MOYEN
   d'atteindre un jeton. Chacun recopiait un :root et le laissait dériver —
   --bg, --or et --text étaient déclarés vingt fois chacun.

   Ce n'est donc pas un système mal appliqué qu'on remplace, c'est vingt-et-un
   systèmes qu'on réunit.

   ⚠ IL SE CHARGE EN PREMIER, ET PARTOUT. Avant style.css, avant le bloc <style>
   d'une page, avant tout. C'est la seule règle qui fait tenir le reste : un
   gabarit qui l'oublie retombe exactement dans le mode de panne que jetons.css
   documentait déjà — une variable absente ne lève aucune erreur, la déclaration
   est simplement invalide, et la propriété reprend sa valeur initiale.

   ⚠ ET IL EST LA SEULE SOURCE. Aucune autre feuille, aucun autre gabarit ne
   redéclare un de ces noms. Deux déclarations du même nom, c'est le défaut que
   jetons.css avait corrigé pour deux jetons ; on le corrige ici pour tous.

   ⚠ IL NE CONTIENT QUE DES JETONS, une remise à zéro, et les styles des
   éléments nus (body, titres, focus). Pas un seul composant. Un composant qui
   entrerait ici serait chargé par des pages qui ne l'utilisent pas, et le
   fichier redeviendrait ce que pecunnia-premium.css était : une couche qu'on
   consulte pour comprendre ce qu'une autre couche vient de dire.

   jetons.css et _terminal_tokens.html sont absorbés ici. polices.css reste
   séparé : il ne porte que des @font-face.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── REMISE À ZÉRO ───────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ─── JETONS INDÉPENDANTS DU THÈME ────────────────────────────────────────── */

:root {

  /* ── POLICES ────────────────────────────────────────────────────────────
     UNE FAMILLE DE TEXTE : INTER. C'est l'arbitrage du 2026-09-08, et il
     referme un compte qui allait de six familles à deux : Satoshi (74
     déclarations), Clash Display (36), Playfair (2), Plus Jakarta (2), puis
     Geist sans.

     L'argument n'est pas le goût. Deux familles dont le lecteur ne peut pas
     dire POURQUOI elles diffèrent ne sont pas une intention, ce sont deux
     couches. Inter est dessinée pour l'interface à petite taille — ce que ce
     produit affiche vraiment : des étiquettes de 10 à 13 px posées au-dessus de
     chiffres. Le caractère d'affichage se prend dans la GRAISSE et l'APPROCHE
     (600–700 à -0.03em au-dessus de 32 px), jamais dans une famille de plus.

     ⚠ LA SECONDE FAMILLE EST UN CHOIX ET ELLE A UN SEUL EMPLOI. --f-mono ne
     sert PAS « les chiffres » : <body> porte `font-variant-numeric:
     tabular-nums`, donc Inter aligne déjà les chiffres en colonne partout.
     --f-mono sert ce que les tabulaires N'alignent pas — le signe, la lettre,
     le séparateur : un ticker, un ISIN, un code, et la colonne du Terminal où
     `+1 234,50` doit tomber sous `-12,04` à la virgule près. Geist Mono est
     dessinée sur un squelette dérivé d'Inter (même hauteur d'x, terminaisons
     coupées à l'horizontale) ; elle pèse 38 Ko et elle est déjà chez nous.
     ⚠ Ne pas l'étendre à la prose ni aux titres : le jour où elle sert partout,
     elle cesse d'être un choix et redevient une couche.

     Les fichiers sont chez nous (polices.css), variables sur l'axe 100–900. */
  --f-sans:  'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-mono:  'Geist Mono', ui-monospace, 'SF Mono', Consolas, monospace;

  /* ── ÉCHELLE TYPOGRAPHIQUE ──────────────────────────────────────────────
     Onze pas pour 116 valeurs. Deux régimes, et c'est délibéré : fin en bas, où
     l'interface a besoin de nuances entre une étiquette et une donnée ; large
     en haut, où l'affichage a besoin de sauts francs.

     ⚠ UNE PAGE N'ÉCRIT PLUS JAMAIS UN font-size LITTÉRAL. Les tailles de la
     vitrine se posent en clamp() À PARTIR de ces jetons, jamais en valeurs
     libres — sinon la fluidité rouvre par la porte de derrière exactement le
     nuage qu'on vient de fermer. */
  /* ⚠ UN DOUZIÈME PAS, AJOUTÉ LE 2026-09-08 EN OUVRANT L'APPLICATION, et il
     n'est pas une entorse à l'échelle : il en referme le bas. Sous 11 px, le
     dépôt portait NEUF valeurs pour 145 déclarations — 8,5 · 9 · 9,28 · 9,5 ·
     9,6 · 9,92 · 10 · 10,24 · 10,4 px. C'est un registre réel (la micro-
     étiquette d'une interface de données : le libellé au-dessus d'un chiffre,
     l'unité, la place de cotation) écrit à neuf endroits différents.

     Il vaut 10 et pas 8,5 : le plancher REMONTE. Un libellé de 8,5 px n'est pas
     dense, il est illisible — c'est le même défaut que --text-ter à 4,09:1, la
     densité prise sur la lisibilité au lieu de l'être sur l'espace.
     ⚠ ET IL NE SERT QUE LÀ. Une page de prose n'a pas de micro-étiquette. */
  --txt-4xs: 0.625rem;    /* 10 — micro-étiquette d'interface dense, et rien d'autre */
  --txt-3xs: 0.6875rem;   /* 11 — mentions légales, sources                  */
  --txt-2xs: 0.75rem;     /* 12 — étiquettes, méta, badges                   */
  --txt-xs:  0.8125rem;   /* 13 — interface dense : Terminal, tableaux       */
  --txt-sm:  0.875rem;    /* 14 — interface courante                        */
  --txt-md:  0.9375rem;   /* 15 — corps applicatif                          */
  --txt-lg:  1.0625rem;   /* 17 — corps de la vitrine                       */
  --txt-xl:  1.3125rem;   /* 21 — chapô, sous-titre                         */
  --txt-2xl: 1.625rem;    /* 26 — h3                                        */
  --txt-3xl: 2.0625rem;   /* 33 — h2                                        */
  --txt-4xl: 2.625rem;    /* 42 — h1 applicatif, h2 de vitrine              */
  --txt-5xl: 3.5rem;      /* 56 — h1 de vitrine                             */
  /* ⚠ UN TREIZIÈME PAS, AJOUTÉ LE 2026-09-10 EN REPRENANT LA VITRINE, et il
     referme le HAUT comme --txt-4xs referme le bas. L'échelle s'arrêtait à 56,
     et 56 était l'affiche d'accueil pendant que 42 était le titre de section :
     un rapport de 1,33 entre le plus grand mot de la page et le suivant. Ce
     n'est pas un saut d'affichage, c'est un décalage — sur 1 200 px de mesure,
     une phrase de 56 px ne tient pas la page, elle la commence seulement, et
     tout le reste vient s'aligner à la même hauteur de voix.

     76 rétablit la progression que le haut de l'échelle annonçait déjà :
     26 → 33 → 42 → 56 → 76, soit 1,27 · 1,27 · 1,33 · 1,36. Le pas s'ouvre au
     fur et à mesure qu'on monte, ce qui est exactement ce que « pas fine en
     bas, large en haut » veut dire.
     ⚠ ET IL NE SERT QUE L'AFFICHE D'UNE PAGE PUBLIQUE — le moment où la page
     n'a qu'une chose à dire. Un écran d'application n'en a jamais l'emploi :
     il en a douze, et aucune ne mérite 76 px. */
  --txt-6xl: 4.75rem;     /* 76 — l'affiche de la vitrine, et rien d'autre   */

  /* Interlignes. Quatre, nommés par ce qu'ils servent et non par leur valeur :
     personne ne se demande s'il veut 1.45 ou 1.5, on se demande si on met en
     page un titre ou un paragraphe. */
  --inter-affiche: 1.05;
  --inter-titre:   1.2;
  --inter-ui:      1.45;
  --inter-texte:   1.65;

  /* Approches. Négatives en haut de l'échelle seulement : une étiquette de
     11 px resserrée devient illisible bien avant d'avoir l'air soignée. */
  --appr-affiche: -0.03em;
  --appr-titre:   -0.02em;
  --appr-normal:  0;

  /* ── ESPACEMENT ─────────────────────────────────────────────────────────
     Dix pas de 4. Une seule unité — le pixel — pour que `1rem` et `16px`
     cessent d'être deux mots pour la même chose : l'audit en comptait 156 d'un
     côté et 44 de l'autre, et aucune recherche ne trouvait les deux. */
  --esp-1:  4px;
  --esp-2:  8px;
  --esp-3:  12px;
  --esp-4:  16px;
  --esp-5:  24px;
  --esp-6:  32px;
  --esp-7:  48px;
  --esp-8:  64px;
  --esp-9:  96px;
  --esp-10: 128px;

  /* ── RAYONS ─────────────────────────────────────────────────────────────
     Six pour 24. --rayon reste à 12 : il porte déjà 35 déclarations, le bouger
     n'apportait rien à l'œil et touchait tout le dépôt.

     --rayon-lg passe de 18 à 16. Le 18 n'était pas un choix : c'était la valeur
     qu'un `border-radius: 18px !important` de pecunnia-premium.css imposait, et
     sur laquelle le jeton avait été aligné en 2026-08-29 « pour dire ce que
     l'écran affiche ». La contrainte disparaît avec le fichier.

     --rayon-sm existe enfin : il était LU sans être déclaré (index.html, avec un
     repli à 6px — le seul endroit où le défaut se voyait est le seul où il ne
     faisait rien). */
  /* ⚠ MÊME HISTOIRE QUE --txt-4xs, ET MÊME JOUR. Le Terminal et les écrans
     denses portaient CINQ micro-rayons — 1 · 2 · 3 · 4 · 5 px, 53 déclarations
     — qu'aucun œil ne sépare. Les envoyer sur --rayon-xs (6) aurait arrondi une
     puce de 20 px d'un tiers de plus qu'elle ne l'était. Un pas, à 4. */
  --rayon-2xs:    4px;    /* puces et jetons des écrans denses     */
  --rayon-xs:     6px;    /* pastilles, puces, petits badges       */
  --rayon-sm:     8px;    /* champs, contrôles, éléments imbriqués */
  --rayon:        12px;   /* boutons, tuiles, encadrés             */
  --rayon-lg:     16px;   /* cartes portant une section            */
  --rayon-xl:     24px;   /* grands panneaux, hero                 */
  --rayon-pilule: 999px;  /* une seule écriture : 99px, 100px et 999px coexistaient */

  /* ── MOUVEMENT ──────────────────────────────────────────────────────────
     Une courbe, deux durées. Le mouvement qui répond à un geste est bienvenu ;
     celui que personne n'a demandé est réduit à UN moment sur tout le site,
     l'entrée du hero. Vingt sections qui montent en fondu, c'est l'effet par
     défaut, pas une intention. */
  --ease:  cubic-bezier(0.22, 1, 0.36, 1);
  --vite:  120ms;
  --calme: 260ms;

  /* ── MISE EN PAGE ───────────────────────────────────────────────────────
     --lisible : la mesure de la prose. En dessous de 70 caractères, l'œil
     retrouve le début de la ligne suivante sans la chercher. */
  --maxw:     1200px;
  --lisible:  68ch;
  --rail:     64px;   /* la barre latérale de l'application */
  /* ⚠ --barre PASSE DE 60 À 44 LE 2026-09-10, ET C'EST LE TERMINAL QUI DONNE LA
     VALEUR. Il n'a jamais lu ce jeton : `.d-top` déclare `height: 44px` chez lui,
     et le reste de l'application portait 60 — deux barres hautes de deux hauteurs
     pour un seul produit, dont on passe de l'une à l'autre en un clic.

     C'est le même sens d'alignement que pour les gris en 2026-09-07 : le Terminal
     est le seul écran dont la densité ait été mesurée et argumentée, il gagne, et
     le système prend SA valeur. Seize pixels par écran ne sont pas un détail sur
     une interface de données — c'est une ligne de tableau.

     ⚠ ET LE JETON N'ÉTAIT LU QUE PAR auth.css. `base.html` écrivait `60px` cinq
     fois, `style.css` trois fois : le nom existait, la valeur était recopiée.
     C'est le mode de panne que l'audit du 2026-09-07 a compté 397 fois. Toutes
     les occurrences lisent maintenant le jeton. */
  --barre:    44px;   /* la barre du haut de l'application — celle du Terminal */

  /* ── ÉTATS ──────────────────────────────────────────────────────────────
     --inerte est une OPACITÉ, pas une couleur, et c'est la raison pour laquelle
     il n'y a que trois tons de texte. Un bouton éteint dont le libellé pâlit
     mais dont la bordure reste vive n'a l'air éteint qu'à moitié : ce qui
     s'éteint, c'est le contrôle entier.
     (Le nom figurait déjà parmi les jetons déclarés et jamais lus. Il sert.) */
  --inerte: 0.45;
}

/* ─── THÈME SOMBRE — le défaut, et celui de l'application ─────────────────── */

/*  ⚠ LES VALEURS VIENNENT DU TERMINAL, PAS L'INVERSE.

    C'est le seul écran du dépôt dont les couleurs ont été mesurées au contraste
    et argumentées ligne à ligne (l'ancien _terminal_tokens.html). Le reste de
    l'application flottait à côté sans raison : #0c0d12 contre #0c0c0f, #71717f
    contre #9e9db0. Quand deux familles divergent et qu'une seule a été mesurée,
    ce n'est pas une moyenne qu'on prend.

    ⚠ --text-ter MONTE DE #71717f À #9e9db0 SUR TOUT LE SITE, et ce n'est pas un
    goût : #71717f donne 4,09:1 sur --bg et 3,71:1 sur --surface-2, sous le seuil
    de 4,5 dans les deux cas. Tout l'appareil qui rend un chiffre CONTESTABLE —
    méthode, bornes, périmètre, exclusions — était écrit dans ce ton. On avait
    rendu décoratif exactement le texte écrit pour être lu et discuté.
    Ne pas le redescendre pour « calmer » un écran : la densité se règle par la
    TAILLE et par l'ESPACE, jamais en effaçant le texte.

    Les 33 couples sont mesurés par scripts/contraste_palette.py. */

:root, [data-theme="dark"] {

  /* Fonds — charbon, jamais noir absolu */
  --bg:        #0b0b0f;
  --surface:   #111116;
  --surface-2: #17171d;
  --surface-3: #1e1e26;

  /* Lignes. Deux, et elles ne disent pas la même chose : --border ferme un
     objet, --border-2 marque celui qu'on survole ou qui a le focus. */
  --border:    rgba(255,255,255,.09);
  --border-2:  rgba(255,255,255,.16);

  /* Texte — trois tons, tous au-dessus de 4,5:1 sur les trois fonds */
  --text:      #f0f0f4;   /* 17,3 sur --bg */
  --text-sec:  #c9c8d6;   /* 11,9 — la prose secondaire, les explications */
  --text-ter:  #9e9db0;   /*  7,4 — étiquettes, méta, sources             */

  /* ── L'OR ────────────────────────────────────────────────────────────────
     L'OR EST UNE MARQUE, PAS UNE ATMOSPHÈRE. C'est l'arbitrage dont tout le
     reste de la refonte découle.

     Il était partout : trois halos radiaux en fond de body, un glow sous chaque
     carte au survol, un dégradé sur chaque bouton, une lueur sous chaque
     panneau — 26 des 65 ombres de l'audit contenaient du doré. À force d'être
     l'ambiance, il n'était plus l'accent. Et sur une vitrine claire, l'ambiance
     dorée ne tient tout simplement pas.

     Il ne paraît plus qu'à quatre endroits : le « P », l'action primaire,
     l'état « suivi », et le filet de la section courante. Partout ailleurs, le
     contraste se fait par le gris et par l'espace. */
  --or:         #dcb968;                   /* 10,5 sur --bg */
  --or-vif:     #ecd08a;                   /* le haut du dégradé du bouton  */
  --or-dark:    #b8963e;                   /* le bas                        */
  /* ⚠ EN SOMBRE, LE PROBLÈME INVERSE A ÉTÉ CHERCHÉ ET N'EXISTE PAS. On pouvait
     craindre qu'un or clarifié pour le blanc soit trop pâle sur le charbon :
     mesuré, #dcb968 donne 10,46:1 sur --bg, 10,02 sur --surface, 9,50 sur
     --surface-2 et 8,81 sur --surface-3. L'or SE LIT en sombre, --or-texte y
     garde donc la valeur de --or — et c'est ce qui rend le changement de la
     ligne clair-seulement SANS EFFET ici. */
  --or-texte:   #dcb968;                   /* 10,46 sur --bg — même valeur que --or */
  --or-light:   rgba(220,185,104,.15);     /* aplat teinté : état sélectionné */
  --or-border:  rgba(220,185,104,.32);
  --on-or:      #16171e;                   /* l'encre POSÉE sur l'or — 9,5:1 */

  /* ── SENS ────────────────────────────────────────────────────────────────
     Une hausse n'a pas à changer de vert selon la page qu'on regarde. Le dépôt
     en portait trois (#3ddc97, #16a34a, #0d6b46) et trois rouges. */
  --green:        #3ddc97;
  --green-soft:   rgba(61,220,151,.13);
  --green-border: rgba(61,220,151,.32);
  --red:          #f8746f;
  --red-soft:     rgba(248,116,111,.13);
  --red-border:   rgba(248,116,111,.32);
  --info:         #6fa8f5;
  --info-soft:    rgba(111,168,245,.13);
  --info-border:  rgba(111,168,245,.32);
  --warn:         #e0a44a;
  --warn-soft:    rgba(224,164,74,.13);
  --warn-border:  rgba(224,164,74,.32);
  --violet:       #a78bfa;
  --violet-soft:  rgba(167,139,250,.13);
  --violet-border: rgba(167,139,250,.32);

  /* ── OMBRES ──────────────────────────────────────────────────────────────
     Quatre pour 65, et elles ne sont PAS les mêmes qu'en clair : une ombre
     lisible sur #0b0b0f est invisible, et une ombre lisible sur du blanc est un
     aplat noir. Sur fond sombre, ce qui détache un objet est d'abord une ligne
     claire au-dessus, pas une tache noire en dessous. */
  --ombre-1:  0 1px 2px rgba(0,0,0,.5);
  --ombre-2:  0 8px 28px -10px rgba(0,0,0,.7), 0 1px 0 rgba(255,255,255,.04) inset;
  --ombre-3:  0 24px 64px -20px rgba(0,0,0,.8);
  --ombre-or: 0 8px 26px -10px rgba(220,185,104,.35);

  /* L'anneau de focus. UN SEUL, visible dans les deux thèmes et sur l'or. */
  --anneau: 0 0 0 3px var(--or-light), 0 0 0 1px var(--or-border);

  /* ── SURVOL ET SÉLECTION ─────────────────────────────────────────────────
     La direction annonçait « un survol, un actif, un désactivé, un sélectionné,
     définis une fois » ; il manquait les deux premiers. Le Terminal écrivait
     `rgba(255,255,255,.025)`, `.04`, `.06`, `.085`, `.09` — cinq voiles blancs
     pour un seul geste, et aucun ne pouvait suivre le thème clair, où un voile
     BLANC sur du blanc ne fait rien du tout. */
  --survol:    rgba(255,255,255,.04);
  --selection: rgba(255,255,255,.07);

  /* ── LE VOILE D'UNE SURCOUCHE ────────────────────────────────────────────
     ⚠ JETON AJOUTÉ LE 2026-09-10 (lot 3), ET IL RÉPARE UNE PANNE, pas un goût.
     Le fond des deux tiroirs de l'accueil s'écrivait `background: var(--surface-3)`
     avec `opacity: 1` à l'ouverture : `--surface-3` est OPAQUE, donc le voile ne
     voilait pas, il EFFAÇAIT. Ouvrir « Mon portefeuille » remplaçait la page
     entière par un aplat gris, et il fallait refermer pour savoir d'où l'on
     venait. Un voile doit laisser voir ce qu'il met en retrait — c'est ce qui
     dit qu'on est SUR la page, et pas AILLEURS.
     Il est ici, dans le système, et pas dans le gabarit, parce que trois autres
     écrans ont une surcouche (le calendrier du Terminal, la fenêtre de note,
     le paywall) et qu'aucun ne doit réinventer sa valeur. */
  --voile: rgba(6,6,9,.62);
}

/* ─── THÈME CLAIR — celui de la vitrine ───────────────────────────────────── */

/*  ⚠ LE FOND PASSE DU GRIS AU BLANC. --bg valait #d8d8dc : un gris moyen. La
    vitrine demande du blanc, et un système ne peut pas avoir deux thèmes
    clairs. Le contraste se fait alors par les SURFACES (#fafafa, #f4f4f6) et
    par une ligne à 10 % de noir, pas par un fond teinté.

    ⚠ ET L'OR N'EST JAMAIS UNE COULEUR DE TEXTE ICI. #b8963e sur blanc donne
    2,81:1, et 2,56 sur --surface-2. Un bouton d'appel à l'action dont le
    libellé tient à 2,8:1 est un bouton que certaines personnes ne lisent pas —
    et c'est l'écran qui décide de tout le reste du parcours.

    --or reste donc la couleur d'APLAT et d'ACCENT NON TEXTUEL — le bouton, la
    pastille, le filet, le trait sous l'onglet courant — où c'est --on-or qui se
    lit. Quand un mot doit être doré ET lu, c'est --or-texte.

    ⚠ --or-texte VAUT #8A6A00 DEPUIS LE 2026-09-08 (il valait #7d6420).
    C'est un or FRANC : la composante bleue tombe à zéro, la teinte reste sur
    l'axe du doré au lieu de virer au brun olive, et le ton se tient à 5,07:1
    sur blanc — au-dessus du seuil sans se déguiser en gris chaud.
      blanc 5,07 · --surface 4,86 · --surface-2 4,62 · --surface-3 4,23
    ⚠ LA DERNIÈRE LIGNE EST UNE CONTRAINTE, PAS UNE NOTE : --or-texte ne se pose
    PAS sur --surface-3 en clair. C'est le fond le plus foncé du thème et le
    couple passe sous 4,5. scripts/contraste_ecran.py mesure le fond RÉEL de
    chaque texte : si un écran l'y pose un jour, il le dira. */

[data-theme="light"] {
  --bg:        #ffffff;
  --surface:   #fafafa;
  --surface-2: #f4f4f6;
  --surface-3: #eaeaee;

  --border:    rgba(14,14,19,.10);
  --border-2:  rgba(14,14,19,.20);

  --text:      #0e0e13;   /* 19,3 sur blanc */
  --text-sec:  #4a4a56;   /*  8,7 */
  /* ⚠ 5,2 sur blanc, 4,70 sur --surface-2, mais 4,31 SUR --surface-3. Comme
     --or-texte, ce ton ne se pose pas sur le fond le plus foncé du thème clair.
     --surface-3 y sert des surfaces imbriquées, rarement du texte tertiaire ;
     scripts/contraste_ecran.py mesure le fond réel et le dirait. */
  --text-ter:  #6c6c7a;   /*  5,2 sur blanc */

  --or:         #b8963e;
  --or-vif:     #cfa94c;
  --or-dark:    #96792f;
  --or-texte:   #8A6A00;                  /* 5,07 sur blanc — l'or qui se LIT */
  /* ⚠ EN CLAIR, L'APLAT TEINTÉ EST OPAQUE, ET C'EST UN CORRECTIF (2026-09-08).
     Il valait rgba(184,150,62,.13) — donc une couleur DIFFÉRENTE selon ce qu'il
     y avait dessous. Le même badge doré tenait 4,50:1 sur --bg, 4,33 sur
     --surface, 4,14 sur --surface-2 et 3,82 sur --surface-3 : trois échecs sur
     quatre, sans qu'une seule ligne de CSS ne change. Et c'est le motif le plus
     répandu du dépôt — 62 règles posent --or-texte sur --or-light : la pastille
     « Recommandé », le badge « Bientôt », l'étiquette d'un terme du glossaire,
     le pictogramme d'une carte.
     Aucune valeur d'alpha ne réglait le cas : à .06, --surface-3 plafonne
     encore à 4,04. Le défaut n'était pas l'opacité, c'était LA DÉPENDANCE AU
     FOND. Un aplat opaque vaut la même chose partout : 4,57:1 avec --or-texte,
     17,3:1 avec --text. Le fond cesse d'être une variable cachée.
     ⚠ En sombre il reste TRANSLUCIDE : là, il se pose sur quatre charbons très
     proches, et --or-texte y donne plus de 8:1 sur les quatre. Le problème est
     un problème du thème clair, la correction aussi. */
  --or-light:   #f8f3e4;
  --or-border:  rgba(184,150,62,.34);
  --on-or:      #16171e;                  /* 6,4:1 sur l'aplat or clair */

  /* Assombris : les valeurs du thème sombre plafonnent à 2,6 et 3,5 sur blanc. */
  --green:        #0d6b46;
  --green-soft:   rgba(13,107,70,.10);
  --green-border: rgba(13,107,70,.30);
  --red:          #b8322d;
  --red-soft:     rgba(184,50,45,.10);
  --red-border:   rgba(184,50,45,.30);
  --info:         #1d4ed8;
  --info-soft:    rgba(29,78,216,.09);
  --info-border:  rgba(29,78,216,.28);
  --warn:         #92400e;
  --warn-soft:    rgba(146,64,14,.09);
  --warn-border:  rgba(146,64,14,.28);
  --violet:       #6d28d9;
  --violet-soft:  rgba(109,40,217,.09);
  --violet-border: rgba(109,40,217,.28);

  --ombre-1:  0 1px 2px rgba(14,14,19,.06);
  --ombre-2:  0 2px 4px rgba(14,14,19,.04), 0 12px 28px -12px rgba(14,14,19,.14);
  --ombre-3:  0 4px 8px rgba(14,14,19,.05), 0 28px 64px -24px rgba(14,14,19,.22);
  --ombre-or: 0 6px 20px -8px rgba(184,150,62,.45);

  /* ⚠ EN CLAIR, LE VOILE EST NOIR. C'est tout l'intérêt de nommer l'état plutôt
     que sa valeur : `rgba(255,255,255,.04)` posé sur du blanc ne fait rien, et
     un survol qui ne se voit pas est un survol absent. */
  --survol:    rgba(14,14,19,.04);
  --selection: rgba(14,14,19,.07);

  /* En clair le voile reste sombre — c'est la seule façon de mettre une page
     blanche en retrait — mais il est plus léger : sur du blanc, 0,62 d'encre
     noire donne une nuit, pas un retrait. */
  --voile: rgba(14,14,19,.38);
}

/* ─── ALIAS DE COMPATIBILITÉ ──────────────────────────────────────────────── */

/*  ⚠ CES SEPT NOMS ÉTAIENT LUS SANS ÊTRE DÉCLARÉS, et six d'entre eux SANS
    VALEUR DE REPLI. Ce ne sont pas des dettes cosmétiques, ce sont des pannes
    qui rendaient à l'écran sans lever la moindre erreur :

      --font, --mono   onboarding.html — la page entière tombait sur la police
                       par défaut du navigateur (une serif) au lieu de Geist.
      --ink, --muted   abonnement_succes.html, abonnement_annule.html — les deux
                       écrans qui suivent un paiement : le texte reprenait la
                       couleur héritée, les libellés secondaires aussi.
      --card-bg        les mêmes, sauvées par leur repli à #fff.
      --alerte         admin/dashboard.html, sauvé par son repli.

    Ils pointent maintenant sur le jeton dont ils étaient le surnom. On ne les
    laisse PAS s'installer : ils sont là pour que rien ne rende faux le temps que
    les gabarits concernés soient repris, et ils partiront avec eux. */
:root {
  --font:    var(--f-sans);
  --mono:    var(--f-mono);
  --ink:     var(--text);
  --muted:   var(--text-ter);
  --card-bg: var(--surface);
  --alerte:  var(--warn);

  /* Anciens noms des ombres — 32 lectures dans le dépôt. */
  --shadow-sm: var(--ombre-1);
  --shadow-md: var(--ombre-2);
  --shadow-or: var(--ombre-or);
}

/* ─── ÉLÉMENTS NUS ────────────────────────────────────────────────────────── */

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--f-sans);
  font-size: var(--txt-md);
  line-height: var(--inter-ui);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Les chiffres s'alignent en colonne dans les tableaux ET dans la prose.
     Sur un produit dont chaque écran empile des cours, ce n'est pas un détail
     de finition : c'est ce qui rend une colonne lisible sans police chassée. */
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--f-sans);
  font-weight: 600;
  line-height: var(--inter-titre);
  letter-spacing: var(--appr-titre);
  color: var(--text);
  text-wrap: balance;
}
h1 { font-size: var(--txt-4xl); line-height: var(--inter-affiche); letter-spacing: var(--appr-affiche); }
h2 { font-size: var(--txt-3xl); }
h3 { font-size: var(--txt-2xl); }
h4 { font-size: var(--txt-xl); }
h5 { font-size: var(--txt-lg); }
h6 { font-size: var(--txt-md); }

p { text-wrap: pretty; }

a { color: inherit; }

/* ─── LE PICTOGRAMME ──────────────────────────────────────────────────────── */

/*  ⚠ IL PREND LA COULEUR DU TEXTE QUI L'ENTOURE, et c'est tout l'écart avec ce
    qu'il remplace. Six gabarits posaient des ÉMOJIS à cette place — 33 en tout.
    Un émoji rend dans la palette du système d'exploitation : il ne suit ni le
    thème, ni --or, ni --text, il n'a pas la même forme d'un appareil à l'autre,
    et sa graisse ne s'accorde à aucun des traits de 1,4 à 1,6 du dépôt. Les
    formes sont dans app/templates/_pictos.html, une fois chacune.
    `flex: none` : dans une pastille ou un bouton, un SVG s'étire sinon sur
    l'axe transversal comme n'importe quel enfant de flex. */
.picto { flex: none; vertical-align: -0.15em; }

/* Les chiffres, les tickers, les codes. La classe est la même partout. */
.mono, code, kbd, samp {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

/* ─── FOCUS ───────────────────────────────────────────────────────────────── */

/*  Un anneau, un seul, et il ne disparaît jamais. :focus-visible ne le montre
    qu'au clavier — la souris ne le déclenche pas, donc personne n'a de raison
    de vouloir l'éteindre. C'est la raison pour laquelle on peut se permettre
    qu'il soit franc. */
:focus { outline: none; }
:focus-visible {
  outline: none;
  box-shadow: var(--anneau);
  border-radius: var(--rayon-sm);
}

/* ─── ÉTAT INERTE ─────────────────────────────────────────────────────────── */

[disabled], [aria-disabled="true"], .inerte {
  opacity: var(--inerte);
  cursor: not-allowed;
}

/* ─── MOUVEMENT RÉDUIT ────────────────────────────────────────────────────── */

/*  ⚠ CETTE RÈGLE N'EXISTAIT NULLE PART. Le dépôt portait des transitions, des
    transforms au survol et un IntersectionObserver qui faisait monter chaque
    section de la vitrine, et rien n'écoutait la préférence système. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
