/* ==========================================================================
   OMNIA — Jetons de conception
   --------------------------------------------------------------------------
   Le principe directeur : la connaissance est de la lumière.
   Ce qui n'est pas encore su est graphite et sourd ; ce qui est maîtrisé
   rayonne. Toute la palette découle de là — un papier chaud, une encre
   profonde, et une seule couleur d'accent : Lumen, un ambre bruni.

   Aucune couleur n'est écrite « en dur » ailleurs que dans ce fichier.
   ========================================================================== */

:root {
  /* Nuit d'abord : c'est ce que doit annoncer le document aux contrôles natifs
     (ascenseurs, sélecteurs, champs) tant que Papier n'a pas été demandé. */
  color-scheme: dark light;

  /* Le seul point où l'ambre entre dans une couverture. Défini ici, au socle,
     parce qu'il vaut pour les deux thèmes : le laisser dans l'un des deux
     éteindrait toutes les couvertures de l'autre. */
  --cover-accent: var(--accent-bright);
  --cover-glow: oklch(var(--cover-glow-l) 0.13 calc(var(--accent-h) + var(--accent-shift)));

  /* — Accent unique : Lumen —————————————————————————————————————
     Exprimé en OKLCH pour pouvoir décaler la teinte de façon perceptuellement
     linéaire (couvertures de thèmes) sans jamais dériver vers une autre famille. */
  --accent-l: 66%;
  --accent-c: 0.132;
  /* La teinte est exprimée en degrés : elle est additionnée à --accent-shift
     dans un calc(), et mélanger un nombre nu avec un angle invaliderait tout
     l'accent — donc, en cascade, chaque lueur du produit. */
  --accent-h: 66deg;
  --accent-shift: 0deg;           /* décalage local, ex. couverture de thème */

  /* Clarté et chroma de la teinte lisible en petit corps (≥ 4,5:1).
     Ils sont sortis de --accent-ink pour que la famille entière puisse être
     recalculée ailleurs : voir « teinte locale » plus bas.

     ⚠ Ces valeurs-ci ne s'appliquent jamais telles quelles. Le bloc
     `:root, :root[data-appearance="nuit"]`, plus bas dans ce fichier, porte
     un `:root` nu de même spécificité et écrit après : c'est lui qui gagne
     sur tout document. Chaque thème doit donc redire ce dont il a besoin —
     Nuit le fait dans son propre bloc, Papier dans le sien.

     Ce qui est écrit ici sert de socle documentaire et de repli pour un
     document qui n'aurait aucun des deux blocs de thème. Modifier une valeur
     *uniquement* ici n'a aucun effet visible : c'est le piège dans lequel
     l'encre d'accent était tombée. */
  --accent-ink-l: 46%;
  --accent-ink-c: 0.126;
  --cover-glow-l: 70%;

  --accent: #c1811f;              /* repli pour les moteurs sans OKLCH */
  --accent: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-bright: oklch(calc(var(--accent-l) + 12%) calc(var(--accent-c) + 0.01) calc(var(--accent-h) + var(--accent-shift)));
  --accent-deep: oklch(calc(var(--accent-l) - 18%) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-ink: oklch(var(--accent-ink-l) var(--accent-ink-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-wash: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)) / 0.1);
  --accent-line: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)) / 0.32);

  /* Ce qui s'écrit *sur* l'ambre.
   *
   * Le jeton manquait, et trois composants l'appelaient déjà par un repli :
   * `.check` avec la bonne valeur, la pastille de notification et la marque
   * de non-lu avec `#fff`. Or l'ambre d'Omnia est clair — 74 % de
   * luminosité — et du blanc dessus donne 2,37:1, mesuré. Le chiffre du
   * compteur était donc là, ambre pâle sur ambre, et illisible à la taille
   * où il est écrit.
   *
   * La valeur n'est pas choisie ici : c'est celle que `btn--lumen` emploie
   * depuis toujours pour le même problème, et elle donne 7,7:1. En la
   * nommant, les trois appels retombent d'eux-mêmes sur la bonne encre, et
   * le quatrième composant qui écrira sur de l'ambre n'aura plus à la
   * redécouvrir.
   *
   * Elle est identique dans les deux thèmes : l'ambre, lui, ne change pas. */
  --on-accent: #1a1409;

  /* Vert et rouge existent uniquement pour la correction d'un exercice :
     l'information « juste / faux » ne peut pas être portée par l'ambre. */
  --right: #2f7d5a;
  --right: oklch(52% 0.096 158);
  --right-wash: oklch(52% 0.096 158 / 0.12);
  --wrong: #a83c2f;
  --wrong: oklch(52% 0.148 28);
  --wrong-wash: oklch(52% 0.148 28 / 0.12);
  /* Sur fond clair, l'aplat est déjà assez sombre pour servir d'encre. */
  --wrong-ink: oklch(52% 0.148 28);

  /* — Typographie ————————————————————————————————————————————
     Une serif d'écran pour le savoir (New York sur Apple, Iowan ailleurs) :
     elle donne à chaque connaissance le poids d'une page imprimée.
     Une grotesque système pour l'interface : neutre, précise, invisible. */
  --font-display: ui-serif, "New York", "Iowan Old Style", "Palatino Linotype",
                  Palatino, "Hoefler Text", "Times New Roman", serif;
  --font-ui: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
             "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo,
               Consolas, monospace;

  --text-2xs: 0.6875rem;
  --text-xs:  0.75rem;
  --text-sm:  0.8125rem;
  --text-md:  0.875rem;
  --text-base:0.9375rem;
  --text-lg:  1.0625rem;
  --text-xl:  1.1875rem;

  --display-1: clamp(2.5rem, 1.35rem + 4vw, 4.5rem);
  --display-2: clamp(1.875rem, 1.2rem + 2.4vw, 3rem);
  --display-3: clamp(1.375rem, 1.05rem + 1.3vw, 2rem);
  --display-4: clamp(1.125rem, 1rem + 0.6vw, 1.4375rem);

  --leading-tight: 1.08;
  --leading-snug:  1.28;
  --leading-body:  1.62;
  --leading-loose: 1.75;

  --track-display: -0.024em;
  --track-tight:   -0.012em;
  --track-normal:  0;
  --track-label:   0.09em;

  /* — Rythme spatial : progression de 4 px, généreuse en haut de gamme ——— */
  --s1:  0.25rem;
  --s2:  0.5rem;
  --s3:  0.75rem;
  --s4:  1rem;
  --s5:  1.25rem;
  --s6:  1.5rem;
  --s7:  2rem;
  --s8:  2.5rem;
  --s9:  3.5rem;
  --s10: 4.5rem;
  --s11: 6rem;
  --s12: 8rem;

  /* Respiration verticale des sections, fluide selon la largeur d'écran. */
  --section-gap: clamp(3rem, 2rem + 4vw, 6rem);
  --gutter: clamp(1.125rem, 0.6rem + 2.4vw, 2.75rem);

  /* — Rayons : francs, jamais timides ————————————————————————— */
  --r-xs: 0.5rem;
  --r-sm: 0.75rem;
  --r-md: 1rem;
  /* Le rayon des cartes du produit. Un seul, et c'est tout l'enjeu : treize
     composants avaient choisi `--r-xl` et soixante-quatre cartes s'arrondissaient
     à vingt-huit pixels quand les deux cent cinquante-quatre autres tenaient
     vingt-deux. Deux angles pour un même objet, d'un écran à l'autre. */
  --r-lg: 1.375rem;
  /* Réservé aux surfaces qui ne sont pas des cartes. Aucun composant ne
     devrait le reprendre pour arrondir une carte. */
  --r-xl: 1.75rem;
  --r-2xl: 2.25rem;
  --r-3xl: 3rem;
  --r-full: 999px;

  /* — Largeurs ——————————————————————————————————————————————— */
  --w-prose: 64ch;
  --w-content: 72rem;
  --w-wide: 88rem;
  --w-narrow: 30rem;

  /* — Mouvement ——————————————————————————————————————————————
     Une seule courbe pour tout ce qui entre (expo out, très longue traîne) :
     c'est elle qui donne la sensation « posé » plutôt que « lancé ». */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);

  --dur-1: 110ms;   /* état d'un contrôle */
  --dur-2: 190ms;   /* survol, focus */
  --dur-3: 320ms;   /* apparition d'un élément */
  --dur-4: 520ms;   /* retournement d'une carte, transition de page */
  --dur-5: 820ms;   /* remplissage d'une progression, célébration */

  --z-base: 0;
  --z-raised: 10;
  --z-nav: 100;
  --z-sheet: 200;
  --z-toast: 300;
  --z-celebration: 400;
}

/* — Thème Papier (clair) ——————————————————————————————————————————
   Papier ne s'applique jamais de lui-même : il faut l'avoir choisi, ou avoir
   demandé à Omnia de suivre le système. La résolution de « système » se fait
   avant le premier rendu, dans le script d'amorçage du gabarit : le document
   porte toujours un thème concret, jamais « à décider ». */
:root[data-appearance="papier"] {
  color-scheme: light;

  --paper:      #faf8f4;
  --paper-deep: #f2eee6;
  --surface:    #ffffff;
  --surface-2:  #f5f2ec;
  --surface-3:  #ebe6dc;
  --surface-inset: #f8f6f1;

  /* Les quatre niveaux d'encre, et le contraste qu'ils tiennent.

     Mesuré : `--ink-3` plafonnait à 2,84 contre la surface la plus claire, et
     `--ink-4` à 1,82. La recommandation WCAG AA demande 4,5 pour du texte
     courant. Ce n'était pas un écart de finition mais un défaut de fond :
     `--ink-3` porte `.faint`, `.section__aside` et toutes les métadonnées,
     c'est-à-dire une bonne moitié des mots de l'application — soixante-seize
     éléments sous le seuil sur la seule page d'accueil.

     Les nouvelles valeurs sont calculées, pas choisies à l'œil : on assombrit
     la teinte d'origine par un facteur constant jusqu'à franchir le seuil
     contre `--surface-2`, qui est le fond le plus défavorable où ces encres
     apparaissent. La teinte chaude est donc conservée ; seule la clarté bouge,
     du minimum nécessaire.

     `--ink-4` vise 3,0 et non 4,5 : il ne porte jamais de phrase, seulement
     des repères — l'initiale d'un jour sous une barre, un horodatage relatif
     déjà donné ailleurs. C'est le seuil des éléments d'interface, et le tenir
     à 4,5 effacerait la hiérarchie entre les quatre niveaux, qui est ce à quoi
     ils servent. */
  --ink:   #191712;
  --ink-2: #6a6459;
  --ink-3: #746e61;
  --ink-4: #928b7e;

  /* — L'encre d'accent, et pourquoi elle doit être redite ici —————————
   *
   * `--accent-ink` est l'ambre lisible en petit corps : les trente-deux
   * endroits qui l'emploient l'emploient tous en `color`, jamais en fond.
   * Sa clarté doit donc s'inverser d'un thème à l'autre — sombre sur du
   * papier, claire sur de la nuit — comme le fait `--ink`.
   *
   * Elle ne s'inversait pas, et la cause tient à l'ordre des blocs.
   * `:root` (en tête de fichier) pose 46 % pour le clair ; le bloc
   * `:root, :root[data-appearance="nuit"]`, plus bas, pose 80 % pour le
   * sombre. Or son sélecteur contient un `:root` nu, qui matche **tous** les
   * documents, y compris ceux en Papier. À spécificité égale, le dernier
   * écrit l'emporte : les 46 % du haut du fichier n'ont jamais été appliqués
   * une seule fois. Ils étaient du code mort qui décrivait une intention
   * juste.
   *
   * Le thème Papier, lui, ne redéclarait rien de la famille — il n'avait
   * aucune raison de le faire, puisque la valeur du socle semblait déjà
   * bonne. Résultat mesuré avant correction : un ambre pâle à 80 % de
   * clarté posé sur des surfaces à 96 %, soit **1,71:1** — sous le seuil
   * d'un texte lisible, et loin des 4,5:1 que le nom du jeton promet.
   *
   * Redire les deux composantes ici suffit, et c'est le bon endroit : le
   * sélecteur du thème porte un attribut, donc une spécificité supérieure au
   * `:root` nu du bloc Nuit — il gagne quel que soit l'ordre. `--accent-ink`
   * lui-même n'a pas à être redéclaré : il est calculé sur `:root`, donc il
   * lira ces valeurs-ci sur le même élément. */
  --accent-ink-l: 46%;
  --accent-ink-c: 0.126;

  /* — Le vert et le rouge de la correction ————————————————————————
   *
   * Même cause que l'encre d'accent juste au-dessus, mêmes conséquences,
   * et celles-ci portent sur ce qu'Omnia dit de plus important : juste ou
   * faux.
   *
   * Le socle déclare ces quatre jetons à 52 % de clarté — les valeurs
   * pensées pour un fond clair. Le bloc `:root, :root[data-appearance="nuit"]`,
   * plus bas, les réécrit à 66 % pour le fond sombre ; son sélecteur contient
   * un `:root` nu, de même spécificité et écrit après, donc il gagne sur
   * *tous* les documents. Papier ne les redisait pas : il affichait donc le
   * vert et le rouge de la nuit sur du papier.
   *
   * Mesuré avant correction, en thème clair :
   *
   *     `--wrong` sur `--surface`   3,33:1   (messages d'erreur, en 12 px)
   *     `--right` sur `--surface`   2,97:1
   *     `--right` sur `--surface-2` 2,66:1
   *     pastille « juste »          2,80:1   (--paper sur --right)
   *
   * Les valeurs ci-dessous donnent respectivement 5,93 · 5,28 · 4,97 — au-
   * dessus du seuil AA du texte normal, ce que ces couleurs portent
   * effectivement (`.field__error`, `.feedback__head`, les compteurs de
   * séance, la marque d'une proposition).
   *
   * Le repli hexadécimal précède l'OKLCH, comme au socle : un moteur qui ne
   * sait pas lire la seconde ligne garde la première. */
  --right: #2f7d5a;
  --right: oklch(52% 0.096 158);
  --right-wash: oklch(52% 0.096 158 / 0.12);
  --wrong: #a83c2f;
  --wrong: oklch(52% 0.148 28);
  --wrong-wash: oklch(52% 0.148 28 / 0.12);
  /* Sur fond clair, l'aplat est déjà assez sombre pour servir d'encre. */
  --wrong-ink: oklch(52% 0.148 28);

  --hairline:        rgba(25, 23, 18, 0.09);
  --hairline-strong: rgba(25, 23, 18, 0.16);
  --hairline-soft:   rgba(25, 23, 18, 0.05);

  /* Le liseré clair en haut d'une surface : ce qui fait « objet » et non « rectangle ». */
  --bevel: rgba(255, 255, 255, 0.9);
  --scrim: rgba(25, 23, 18, 0.4);

  --shadow-1: 0 1px 1.5px rgba(25, 23, 18, 0.04), 0 1px 3px rgba(25, 23, 18, 0.05);
  --shadow-2: 0 1px 2px rgba(25, 23, 18, 0.04), 0 4px 12px -2px rgba(25, 23, 18, 0.07);
  --shadow-3: 0 2px 4px rgba(25, 23, 18, 0.04), 0 12px 32px -8px rgba(25, 23, 18, 0.12);
  --shadow-4: 0 4px 8px rgba(25, 23, 18, 0.05), 0 28px 60px -16px rgba(25, 23, 18, 0.18);

  --grain-opacity: 0.032;
  --grain-blend: multiply;

  /* Couvertures : encre froide au repos, lumière chaude à mesure qu'on maîtrise. */
  --cover-ink: #262218;
  --cover-stroke: #f7f3ea;
}

/* — Thème Nuit (sombre) ——————————————————————————————————————————
   Ce n'est pas une inversion, c'est l'état par défaut d'Omnia : la maîtrise
   s'y lit comme une lumière qui monte, et une couverture gravée n'a de relief
   que sur fond sombre. On découvre donc toujours Omnia de nuit ; Papier est
   un choix, jamais un hasard de réglage système.

   Le sélecteur nu porte la valeur par défaut — il couvre le document avant
   toute intervention du script, et les pages autonomes (mise en service). */
:root,
:root[data-appearance="nuit"] {
  color-scheme: dark;

  --paper:      #100f0d;
  --paper-deep: #0a0908;
  --surface:    #171613;
  --surface-2:  #1e1c18;
  --surface-3:  #272420;
  --surface-inset: #131210;

  --ink:   #f3f0e9;
  --ink-2: #a9a293;
  /* Mêmes seuils, calculés dans l'autre sens : en thème sombre on éclaircit.
     Avant : 3,73 et 2,11 contre `--surface-2`. Après : 4,53 et 3,00. */
  --ink-3: #8b8374;
  --ink-4: #6d6751;

  --hairline:        rgba(243, 240, 233, 0.10);
  --hairline-strong: rgba(243, 240, 233, 0.18);
  --hairline-soft:   rgba(243, 240, 233, 0.055);

  --bevel: rgba(255, 252, 244, 0.06);
  --scrim: rgba(6, 5, 4, 0.62);

  --accent-l: 74%;
  --accent-ink-l: 80%;
  --accent-ink-c: 0.12;
  --cover-glow-l: 66%;

  --right: oklch(66% 0.11 158);
  --right-wash: oklch(66% 0.11 158 / 0.16);
  --wrong: oklch(66% 0.15 28);
  --wrong-wash: oklch(66% 0.15 28 / 0.16);
  /* L'encre d'erreur, plus claire que l'aplat.
     `--wrong` posé en texte sur son propre lavis donnait 4,44:1 de nuit, un
     dixième sous le minimum lisible — sur le bouton qui efface toute la
     progression, c'est-à-dire celui qu'il faut lire le mieux. Même teinte,
     même chroma, six points de clarté en plus. */
  --wrong-ink: oklch(74% 0.14 28);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, 0.34), 0 6px 18px -4px rgba(0, 0, 0, 0.4);
  --shadow-3: 0 4px 12px rgba(0, 0, 0, 0.4), 0 18px 40px -10px rgba(0, 0, 0, 0.55);
  --shadow-4: 0 8px 20px rgba(0, 0, 0, 0.45), 0 40px 80px -20px rgba(0, 0, 0, 0.7);

  --grain-opacity: 0.05;
  --grain-blend: soft-light;

  --cover-ink: #0d0c0a;
  --cover-stroke: #efe9dc;
}

/* — Teinte locale ————————————————————————————————————————————————
   Un jeton dérivé est calculé là où il est déclaré, pas là où il est lu :
   `--accent-ink` est résolu sur :root, avec la teinte de :root, et ce résultat
   est ce qui descend dans l'arbre. Poser `--accent-h: 250deg` sur une carte ne
   la rendait donc pas bleue — la substitution avait déjà eu lieu.

   Les éléments qui portent leur propre teinte redéclarent la famille entière.
   C'est ce qui fait enfin fonctionner le décalage de couverture des thèmes
   (`--accent-shift`), et c'est ce qui permet aux aperçus de la boutique de
   montrer la vraie couleur de ce qu'ils vendent.

   La liste est courte et le restera : recalculer ces jetons partout coûterait
   cher pour rien, puisque presque tout le produit vit sous l'ambre de Lumen. */
.cover,
.apercu,
[data-tint] {
  --accent: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-bright: oklch(calc(var(--accent-l) + 12%) calc(var(--accent-c) + 0.01) calc(var(--accent-h) + var(--accent-shift)));
  --accent-deep: oklch(calc(var(--accent-l) - 18%) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-ink: oklch(var(--accent-ink-l) var(--accent-ink-c) calc(var(--accent-h) + var(--accent-shift)));
  --accent-wash: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)) / 0.1);
  --accent-line: oklch(var(--accent-l) var(--accent-c) calc(var(--accent-h) + var(--accent-shift)) / 0.32);

  /* `--on-accent` n'est pas redéclaré ici, volontairement. Ce bloc ne
     recalcule que ce qui dépend de la teinte locale ; l'encre posée *sur*
     l'ambre est une constante, identique dans les deux thèmes et sous
     n'importe quelle teinte. Elle vit au socle, et une seule fois. */
  --cover-glow: oklch(var(--cover-glow-l) 0.13 calc(var(--accent-h) + var(--accent-shift)));
  --cover-accent: var(--accent-bright);
}

/* — « Suivre le système » ————————————————————————————————————————
   Aucune règle ici : le choix « système » est résolu avant le premier rendu
   par le script d'amorçage (app/Views/layouts/base.php), qui écrit un thème
   concret sur <html>. Le faire en CSS obligerait à dupliquer l'intégralité
   des deux palettes dans deux media queries — deux vérités à maintenir, donc
   une qui finit par diverger. Ici, chaque jeton n'est écrit qu'une fois. */

/* — Mouvement réduit ——————————————————————————————————————————————
   On ne supprime pas les transitions : on les ramène à un fondu bref.
   Un changement instantané est aussi désorientant qu'une animation excessive. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) {
    --dur-1: 1ms;
    --dur-2: 60ms;
    --dur-3: 90ms;
    --dur-4: 110ms;
    --dur-5: 130ms;
    --ease: linear;
    --ease-spring: linear;
  }
}

:root[data-motion="reduced"] {
  --dur-1: 1ms;
  --dur-2: 60ms;
  --dur-3: 90ms;
  --dur-4: 110ms;
  --dur-5: 130ms;
  --ease: linear;
  --ease-spring: linear;
}
