/* BLACKTOP — direction artistique « playground nocturne »
   Voir .impeccable.md pour le contexte et les principes.

   Le noir n'est jamais noir : tous les neutres sont tintés vers la teinte du
   ballon (hue 55). La lumière vient d'un seul point, comme un projecteur.   */

/* ─── Polices auto-hébergées ─────────────────────────────────────────────
   Big Shoulders Display : signalétique urbaine, dessinée pour Chicago.
   C'est le panneau de score, la plaque de rue, le dossard.
   Hanken Grotesk : chaud et très lisible, pour tout ce qui se lit vraiment. */

/* TROIS FICHIERS, PAS SIX.
 *
 * Les deux familles sont des polices VARIABLES : les trois « graisses » de Big
 * Shoulders et les deux de Hanken étaient le même fichier servi sous trois
 * noms — MD5 identiques. Le navigateur téléchargeait 196 ko et six requêtes
 * pour 84 ko de contenu réel, sur un jeu qui vise le téléphone.
 *
 * La plage de `font-weight` est ce qui remplace les déclarations multiples :
 * le navigateur interpole sur l'axe de la police et écrête tout seul si la
 * plage réelle est plus étroite. */
@font-face {
  font-family: 'Big Shoulders';
  src: url('fonts/big-shoulders.woff2') format('woff2');
  font-weight: 400 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Hanken';
  src: url('fonts/hanken.woff2') format('woff2');
  font-weight: 400 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Hanken';
  src: url('fonts/hanken-italic.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap;
}

:root {
  /* ── Surfaces : béton nocturne, tinté cuir ── */
  --nuit:        oklch(0.145 0.010 55);
  --beton:       oklch(0.198 0.013 55);
  --beton-haut:  oklch(0.255 0.015 55);
  --trait:       oklch(0.32 0.016 55);

  /* ── Texte : craie sur béton, jamais blanc pur ── */
  --craie:       oklch(0.955 0.008 72);
  /* Le ton des TEXTES LONGS, un cran sous le blanc des titres. Sur fond
     sombre, un blanc quasi pur produit de la halation : la lumière déborde de
     la lettre et la rend floue, surtout pour les yeux astigmates. Un titre de
     trois mots s'en moque, deux phrases à lire non. */
  --craie-lu:    oklch(0.905 0.010 70);
  --craie-mi:    oklch(0.745 0.013 62);
  --craie-bas:   oklch(0.575 0.014 58);

  /* ── Accents : rares, jamais décoratifs ── */
  --cuir:        oklch(0.685 0.178 48);   /* le ballon. Le choix en cours.   */
  --cuir-sourd:  oklch(0.48 0.115 48);
  --sodium:      oklch(0.87 0.118 90);    /* le projecteur. Un jalon franchi. */
  --sang:        oklch(0.545 0.155 26);   /* ce qui coûte.                    */

  /* ─── L'EXCEPTION À LA RÈGLE DU SEUL ACCENT ────────────────────────────
     La direction artistique tient sur un seul accent, rare : l'orange du
     ballon. Ces deux couleurs-ci en sortent, et c'est délibéré.

     Le vert et le rouge sur un gain et une perte ne sont pas de la
     décoration, ce sont des SIGNES : tout le monde les lit sans apprendre,
     et un joueur doit savoir en un dixième de seconde si son choix vient de
     lui rapporter ou de lui coûter. Employer l'accent pour les deux
     obligeait à lire le signe « + » ou « − », donc à réfléchir.

     Elles ne servent QU'À ÇA. Jamais un fond, jamais un titre, jamais un
     bouton — uniquement la valeur d'un écart chiffré. Utilisées ailleurs,
     elles redeviendraient de la décoration et casseraient la règle pour de
     bon. Chroma volontairement contenue : ce n'est pas un vert d'application
     bancaire, il vit dans la même famille que le cuir et le sang. */
  --gain:    oklch(0.705 0.142 150);
  --perte:   var(--sang);
  /* L'argent a sa propre couleur, comme chez eux (--money #96751a). Un contrat
     n'est ni un gain de niveau ni une perte : c'est une troisième nature, et
     lui donner l'or évite de la confondre avec le reste. Assez sourde pour ne
     pas se disputer avec le sodium, qui reste le projecteur. */
  --monnaie: oklch(0.755 0.096 84);

  /* ── Espacement : 4pt, nommé par intention ── */
  /* EN REM, PAS EN PIXELS. Une échelle en pixels ne suit pas la taille de
     police choisie par l'utilisateur : le texte grossit, les gouttières
     restent, et la page se casse. Le nombre du nom reste la référence à
     16 px de racine — `--sp-16` vaut 1 rem — pour que l'intention se lise
     encore. Seuls les filets d'un pixel restent en pixels : un liseré ne doit
     pas grossir. */
  --sp-2: 0.125rem;  --sp-4: 0.25rem;  --sp-8: 0.5rem;   --sp-12: 0.75rem;
  --sp-16: 1rem;     --sp-24: 1.5rem;  --sp-32: 2rem;    --sp-48: 3rem;
  --sp-64: 4rem;     --sp-96: 6rem;

  /* ── Typographie ── */
  --display: 'Big Shoulders', 'Haettenschweiler', 'Arial Narrow Bold', sans-serif;
  --texte:   'Hanken', ui-sans-serif, system-ui, sans-serif;

  /* Échelle modulaire, ratio 1.32 sur les titres */
  --t-micro: 0.813rem;   /* remonté : l'ancienne échelle était illisible */
  --t-petit: 0.938rem;
  --t-base:  1.063rem;
  --t-lu:    clamp(1.25rem, 1.12rem + 0.62vw, 1.5rem);
  --t-titre: clamp(2.8rem, 1.8rem + 4.8vw, 4.8rem);
  --t-geant: clamp(6.5rem, 3rem + 16vw, 11rem);   /* LE chiffre */

  /* Les chiffres : quatre échelons, pas neuf.
     Neuf tailles coexistaient dans cette feuille, et c'est la cause mécanique
     du « on lit pas bien » : quand tout est à peu près gros, plus rien ne l'est.
     Le rapport N1/N2 vaut 2,4 — en dessous de 2, deux chiffres se disputent
     l'attention et aucun ne gagne. UN SEUL --n1 par écran, jamais deux. */
  --n1: var(--t-geant);   /* 110 px — le verdict.                      */
  --n2: 2.8rem;           /*  45 px — le second chiffre. Deux maximum. */
  --n3: 1.85rem;          /*  30 px — chiffre de liste, nom de jalon.  */
  --n4: 1.2rem;           /*  19 px — chiffre en ligne, tabulaire.     */

  --ease-sortie: cubic-bezier(0.16, 1, 0.3, 1);

  /* L'accent courant. Le cuir du ballon en saison régulière, le sodium du
     projecteur en playoffs. Passer par une variable plutôt que par --cuir en
     dur est ce qui permet de faire basculer toute l'interface d'un coup. */
  --accent: var(--cuir);
  --accent-2: var(--sodium);
  --accent-sourd: var(--cuir-sourd);
}

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

/* ─── Le canevas ────────────────────────────────────────────────────────────
   CE QUE L'ON VOIT EN SUR-DÉFILEMENT VIENT D'ICI, PAS DE `.terrain`. Le fond
   de `html` se propage au canevas et peint toute la zone de rebond, au-delà du
   document. Comme le halo vivait sur `.terrain` et que `html` restait en noir
   plat, tirer la page vers le haut découvrait une frontière franche entre la
   lumière et du noir mat — l'écran avait l'air de se terminer en plein milieu.

   Deux mesures : le canevas reçoit la même base sombre que le bas du halo, et
   le rebond élastique est coupé. Il n'y a rien derrière l'écran, donc rien à
   découvrir. */
html {
  background: var(--nuit);
  overscroll-behavior-y: none;
  /* iOS gonfle les corps de texte au passage en paysage. On lui interdit :
     la mesure de lecture est calibrée, elle ne doit pas se recalculer seule. */
  -webkit-text-size-adjust: 100%;
}

/* ─── LA BOUCLE NE DÉFILE PAS (règle H5) ────────────────────────────────────
   C'était vrai en intention et faux en pratique : rien n'empêchait la PAGE de
   défiler quand la scène dépassait d'un pixel. Pendant qu'on pèse deux options,
   un écran qui glisse sous le doigt est un bug de sensation, pas un confort.

   Deux écrans sont exclus : la fiche, seul document long du jeu, et l'ACCUEIL
   depuis qu'il porte le défi du jour et le palmarès — sur un petit téléphone
   ça dépasse l'écran, et un contenu coupé sans défilement possible est pire
   qu'un défilement.

   ELLE NE VISE QUE LA BOUCLE DE JEU, ET C'EST UNE CORRECTION. Écrite sur `body`
   seul, elle bloquait le défilement de TOUTES les pages qui chargent cette
   feuille — les pages de contrôle et de comparaison comprises, qui sont par
   nature de longs documents. On ne pouvait littéralement pas les lire.
   `.page--jeu` n'existe que sur l'écran de jeu, et `game.js` la retire lui-même
   au moment d'afficher la fiche : la condition dit donc exactement ce qu'elle
   veut dire — « pendant qu'on joue, rien ne bouge ». */
body:has(.page--jeu):not(:has(.scene--fiche)):not(:has(.scene--accueil)) { overflow: hidden; }

/* `manipulation` supprime le double-tap-pour-zoomer, donc les 300 ms d'attente
   avant que le navigateur décide s'il s'agit d'un tap ou d'un zoom. Sur une
   partie de quatre-vingt-cinq taps, ça fait vingt-cinq secondes de latence
   perçue — et un double-tap involontaire zoomait l'écran en plein choix.
   ATTENTION : ceci ne désactive PAS le zoom à deux doigts, et c'est
   volontaire. WCAG 1.4.4 exige que la page reste agrandissable jusqu'à 200 %,
   et `maximum-scale=1` dans le viewport serait une régression d'accessibilité
   que le projet s'interdit. */
body { touch-action: manipulation; }

/* Un bouton n'est pas du texte à sélectionner : l'appui long faisait apparaître
   la loupe et la poignée de sélection au lieu de valider le choix. Les énoncés,
   eux, restent sélectionnables. */
.bouton, .option, .choix, .offre { user-select: none; -webkit-user-select: none; }

/* Le flash bleu du navigateur au tap n'est pas dans la palette. */
.bouton, .option, .choix, .offre { -webkit-tap-highlight-color: transparent; }

body {
  margin: 0;
  font-size: var(--t-base);
  background: var(--nuit);
  overscroll-behavior-y: none;
  color: var(--craie);
  font-family: var(--texte);
  line-height: 1.58;
  -webkit-font-smoothing: antialiased;
}

/* ─── Le halo de projecteur ──────────────────────────────────────────────
   Une seule source de lumière, en haut à gauche, hors champ. C'est ce qui
   donne au béton sa profondeur sans recourir à des ombres portées. */

.terrain {
  position: relative;
  min-height: 100svh;
  isolation: isolate;
  background:
    radial-gradient(120% 80% at 12% -10%,
      oklch(0.30 0.030 58 / 0.9) 0%,
      oklch(0.20 0.016 55 / 0.5) 38%,
      transparent 72%),
    var(--nuit);
  /* LA LUMIÈRE SUIT LE REGARD. Attaché à l'élément, le dégradé s'étire sur
     toute la hauteur de la fiche — le seul écran long du jeu — et la source
     lumineuse reste bloquée tout en haut : on perd la lumière dès le premier
     écran de défilement. Fixé au viewport, le projecteur reste au-dessus de
     l'épaule du joueur, ce qui est la seule lecture physique correcte. */
  background-attachment: fixed, fixed;
}

/* ─── Le tracé du terrain ───────────────────────────────────────────────────
   Un demi-terrain, panier en haut, sous tout le contenu. Voir index.html pour
   la géométrie et le choix du cadrage.

   FIXÉ AU VIEWPORT, comme le halo. Attaché au flux, il s'étirerait sur toute
   la hauteur de la fiche — le seul écran long du jeu — et le panier finirait à
   trois écrans de défilement du regard.

   OPACITÉ BASSE ET ASSUMÉE. Un fond qui se remarque au deuxième écran devient
   insupportable au vingtième. S'il faut plisser les yeux pour le voir, c'est
   le bon niveau. */
.trace {
  position: fixed;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: min(100%, 34rem);
  height: min(64svh, 30rem);
  z-index: -1;
  pointer-events: none;
  opacity: 0.20;
  color: var(--trait);
}
.trace rect, .trace circle, .trace line, .trace path {
  fill: none;
  stroke: currentColor;
  stroke-width: 0.5;
  /* Le filet garde UN pixel quelle que soit l'échelle du repère : sans ça, une
     géométrie en pieds mise à l'échelle d'un téléphone produirait des traits
     de trois pixels. La règle du dépôt est le filet d'un pixel. */
  vector-effect: non-scaling-stroke;
}

/* L'ambiance nationale est claire : un filet pensé pour le noir y disparaît.
   On le fonce et on le calme, plutôt que de le retirer — le tracé fait partie
   de l'identité, il ne doit pas clignoter d'un écran à l'autre. */
.terrain--nation .trace { color: oklch(0.62 0.02 250); opacity: 0.26; }

/* Sur la fiche, le tracé s'efface : ce n'est plus la boucle, c'est un document
   qu'on lit et qu'on partage, et il n'a pas besoin de décor. */
body:has(.scene--fiche) .trace { opacity: 0.08; }

/* Grain : le béton n'est pas lisse. Très léger, non animé. */
.terrain::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 10;
  opacity: 0.055;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

.ecran {
  position: relative;
  z-index: 1;
  max-width: 34rem;
  margin-inline: auto;
  padding: var(--sp-24) var(--sp-24) var(--sp-48);
  display: grid;
  gap: var(--sp-32);
  min-height: 100svh;
  grid-template-rows: auto 1fr auto;
}

/* ─── Bandeau : état permanent, en périphérie ───────────────────────────── */

.bandeau {
  display: flex;
  align-items: baseline;
  gap: var(--sp-16);
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: var(--t-petit);
  color: var(--craie-bas);
  border-bottom: 1px solid var(--trait);
  padding-bottom: var(--sp-12);
}
.bandeau b { color: var(--craie); font-weight: 700; }

/* ─── La situation : le texte EST l'interface ───────────────────────────── */

.acte {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--cuir);
  margin: 0 0 var(--sp-12);
}

/* ─── Les options de la MAQUETTE (apercu.html) ──────────────────────────── */
/* La maquette de DA (`apercu.html`) et ses règles cloisonnées sous `.apercu`
   ont été retirées le 9 août 2026 : elles avaient tranché la direction
   artistique, qui vit désormais dans le jeu lui-même. Une page de comparaison
   qui a répondu à sa question devient une source de vérité concurrente. */

/* L'ancien bloc d'issue de la maquette a été supprimé : `.issue`,
   `.issue__texte`, `.effets` et `.effet--*` n'étaient plus employés par
   apercu.html, et `.issue` entrait en collision avec celui du jeu. */

/* ─── Le jalon : la célébration, rare ──────────────────────────────────── */

.jalon {
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-16) 0;
  border-block: 1px solid oklch(0.87 0.118 90 / 0.35);
}

/* ─── Jauge : le classement, en périphérie ─────────────────────────────── */

.jauge { display: grid; gap: var(--sp-8); }
.verdict-principal__chiffre {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--t-geant);
  line-height: 0.76;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin: 0;
  color: var(--craie);
}
.verdict-principal__chiffre sup {
  font-size: 0.3em;
  vertical-align: super;
  color: var(--cuir);
  margin-left: 0.05em;
}
.verdict-principal__quoi {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.35rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cuir);
  margin: var(--sp-8) 0 0;
}
.verdict-principal__traduction {
  font-size: var(--t-lu);
  color: var(--craie-mi);
  margin: var(--sp-4) 0 0;
  max-width: 30ch;
}
.voisin {
  display: grid;
  grid-template-columns: 3.2rem 1fr auto;
  align-items: baseline;
  gap: var(--sp-12);
  padding: var(--sp-12) var(--sp-8);
  background: var(--nuit);
  font-size: var(--t-petit);
  color: var(--craie-bas);
}

/* ─── La carte finale : l'artefact ─────────────────────────────────────── */

.carte {
  background: var(--beton);
  border: 1px solid var(--trait);
  padding: var(--sp-32) var(--sp-24);
  display: grid;
  gap: var(--sp-24);
}
.moment {
  display: flex;
  gap: var(--sp-12);
  align-items: baseline;
  font-size: var(--t-base);
  color: var(--craie-mi);
}

/* « Il te manquait ça » — le moteur du rejeu (spec §9.5) */
.manque {
  font-size: var(--t-base);
  color: var(--craie-bas);
  font-style: italic;
  margin: 0;
}

/* ─── Mise en scène : trois moments, pas plus ──────────────────────────── */

@keyframes monte {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.monte { animation: monte 0.62s var(--ease-sortie) both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ═══ LES PALIERS : L'INTERFACE SE RECOLORE AVEC LA CARRIÈRE ════════════════
   Repris de Destiny Eleven, dont c'est la meilleure idée d'interface. Là-bas
   le niveau de club recolore tout : gris en régional, vert en D2, bleu en D1,
   or à l'élite, avec un halo. La progression ne se lit pas dans un chiffre,
   elle se VOIT — on change de division et l'écran change de teinte.

   Chez nous le palier vient de la carrière : le lycée, la fac, l'entrée dans
   la Ligue, puis le statut qu'on y atteint. Cinq états, du béton froid du
   playground au sodium d'une salle pleine. Le halo n'apparaît qu'au dernier :
   il faut qu'il reste quelque chose à atteindre.

   La bascule est une transition de couleur, jamais un mouvement. Elle doit se
   sentir sans se remarquer. */

.terrain--lycee    { --accent: oklch(0.66 0.032 62);  --accent-sourd: oklch(0.48 0.022 62); }
.terrain--fac      { --accent: oklch(0.70 0.098 168); --accent-sourd: oklch(0.50 0.062 168); }
.terrain--ligue    { --accent: var(--cuir);           --accent-sourd: var(--cuir-sourd); }
.terrain--star     { --accent: oklch(0.74 0.152 42);  --accent-sourd: oklch(0.53 0.105 42); }
.terrain--legende  { --accent: var(--sodium);         --accent-sourd: oklch(0.62 0.088 90); }

/* Le halo n'est accordé qu'au dernier palier. Le donner plus tôt retirerait
   sa raison d'être à celui qui le suit. */
.terrain--legende {
  background:
    radial-gradient(95% 60% at 50% -12%,
      oklch(0.42 0.058 88 / 0.95) 0%,
      oklch(0.24 0.024 72 / 0.55) 42%,
      transparent 76%),
    var(--nuit);
}

/* ═══ FÉVRIER — LE WEEK-END DES ÉTOILES ════════════════════════════════════
   On éteint la salle et on allume un seul faisceau.

   PREMIER ESSAI ABANDONNÉ : un lavis corail à trois sources, censé évoquer un
   plateau de télévision. C'était une invention, pas une référence, et ça se
   voyait — la couleur ne renvoyait à rien de réel.

   L'IMAGE VRAIE DU WEEK-END, C'EST LE CONCOURS DE DUNK. Les lumières de
   l'arène qui tombent, vingt mille personnes qu'on ne voit plus, et un seul
   projecteur blanc sur un joueur qui court seul vers le cercle. C'est le seul
   moment de la saison où l'on met un homme sous une lampe pour le regarder
   faire quelque chose d'inutile, et c'est pour ça qu'on s'en souvient.

   Le fond descend donc PLUS BAS que partout ailleurs dans le jeu — plus noir
   que le playground —, et la lumière est plus dure et plus étroite que le
   projecteur des playoffs : un cône serré, presque blanc, à peine tiédi. Le
   contraste fait tout le travail ; il n'y a aucune couleur à trouver.

   Elle dure un écran, deux au maximum. C'est sa condition d'existence. */

.terrain--allstar {
  --accent: oklch(0.94 0.042 88);
  --accent-2: oklch(0.94 0.042 88);
  --accent-sourd: oklch(0.66 0.048 88);
  background:
    radial-gradient(38% 62% at 50% -18%,
      oklch(0.86 0.055 88 / 0.30) 0%,
      oklch(0.52 0.038 86 / 0.16) 34%,
      transparent 68%),
    radial-gradient(120% 45% at 50% 118%,
      oklch(0.24 0.012 70 / 0.55) 0%, transparent 60%),
    oklch(0.095 0.006 66);
}

/* ═══ AVRIL — LES PLAYOFFS ══════════════════════════════════════════════════
   Le printemps arrive et la salle change de couleur.

   POURQUOI DU BLEU, ET PAS NOTRE ORANGE. C'est la couleur réelle de
   l'événement : la ligue habille ses playoffs en bleu marine depuis toujours,
   les parquets prennent des tabliers foncés, l'habillage télévisé passe au
   bleu nuit. Reprendre cette teinte n'est pas un caprice de palette, c'est la
   même règle que pour les salaires et les records — on s'ancre sur le réel,
   parce que le public visé le reconnaît sans qu'on le lui explique.

   Ce n'est PAS le dégradé violet-bleu que la direction artistique interdit :
   une seule teinte, froide, sans second ton qui viendrait faire du néon. Le
   contraste vient de la lumière, pas d'une transition de couleurs.

   Ce que ça produit à l'écran : le cuir chaud du terrain disparaît d'un coup,
   la salle se refroidit, et l'accent devient une lumière d'arène plutôt qu'un
   ballon. On sent qu'on a changé de saison avant d'avoir lu un mot. */

.terrain--playoffs {
  --accent: oklch(0.80 0.098 244);
  --accent-sourd: oklch(0.56 0.088 248);
  background:
    radial-gradient(88% 58% at 50% -12%,
      oklch(0.40 0.112 254 / 0.95) 0%,
      oklch(0.24 0.062 252 / 0.60) 42%,
      transparent 76%),
    oklch(0.155 0.026 254);
}

/* ═══ JUIN — LES FINALES ════════════════════════════════════════════════════
   Quatre victoires plus loin, la couleur change encore. Les Finales ont leur
   propre identité, or sur noir, et elles ne ressemblent à aucun autre moment
   de l'année.

   L'escalade est le sujet : bleu au premier tour, or en finale. Si les deux
   partageaient une teinte, franchir trois séries ne se verrait pas. Là, un
   joueur qui atteint les Finales sait qu'il y est arrivé avant qu'on le lui
   dise — et celui qui n'y arrive jamais n'aura jamais vu cet écran. */

.terrain--finales {
  --accent: oklch(0.84 0.132 88);
  --accent-sourd: oklch(0.60 0.098 88);
  background:
    radial-gradient(80% 52% at 50% -10%,
      oklch(0.46 0.098 86 / 0.92) 0%,
      oklch(0.24 0.042 78 / 0.55) 40%,
      transparent 74%),
    oklch(0.135 0.014 70);
}

@media (prefers-reduced-motion: reduce) {
  .terrain { transition: none; }
}

/* ═══ LA FICHE DE FIN DE CARRIÈRE ═══════════════════════════════════════════
   Partagée par la page de fiche et par la fin de partie du jeu. */

/* ═══════════════════════════════════════════════════════════════════════════
   LA FICHE DE FIN DE CARRIÈRE
   Carte partageable, puis le détail saison par saison.

   Rendue sur une VRAIE carrière : le moteur tourne dans la page, avec la
   boucle de tools/simulate.js. Rien n'est écrit en dur, donc ce qui s'affiche
   ici est ce que le jeu produira.
   ═══════════════════════════════════════════════════════════════════════════ */

.page {
  max-width: 30rem; margin-inline: auto;
  padding: var(--sp-32) 0 var(--sp-96);
}

/* Le conteneur du jeu centre la scène. La fiche, elle, est un document : elle
   part du haut et défile. */
.page--jeu {
  display: grid;

  /* LA PISTE EST DÉCLARÉE, PAS DÉDUITE. C'était la vraie cause de la largeur
     qui bougeait : avec `place-content: center`, la colonne d'une grille se
     dimensionne sur son CONTENU. Le `width: min(100%, 30rem)` de la scène
     devenait alors circulaire — cent pour cent d'une piste qui se réglait
     elle-même sur ce qu'elle contenait. D'où une colonne large sur l'écran des
     offres et étroite sur l'écran du corps.
     Ici la piste vaut `min(100%, 30rem)` en dur, la scène la remplit, et plus
     rien ne dépend du contenu. */
  grid-template-columns: min(100%, 30rem);
  justify-content: center;
  /* `safe` EST OBLIGATOIRE. Sans lui, un contenu plus haut que son conteneur
     est centré en débordant DES DEUX CÔTÉS, et la partie qui sort par le haut
     devient inatteignable : `scrollTop` reste bloqué à 0. Comme les barres de
     défilement sont masquées juste en dessous, rien n'indique qu'il manque
     quelque chose — l'écran a simplement l'air cassé et les boutons du haut ne
     répondent plus. Constaté sur l'écran de création dès qu'une description
     gagne une ligne. `safe` bascule l'alignement en `start` dans ce cas. */
  align-content: safe center;
  min-height: 100svh; max-width: none; padding: 0;
}

/* ═══ 1. LA CARTE ═══════════════════════════════════════════════════════════
   9:16, 360 × 640. C'est le format natif des stories : toute autre proportion
   est recadrée ou encadrée de bandes. 360 × 3 = 1080 exactement, donc l'export
   est un facteur entier et les chiffres de 110 px ne floutent pas.

   NEUF ÉLÉMENTS, PAS DIX : un chiffre géant, quatre moyens, trois libellés,
   une phrase. Tout le reste est sur la fiche, en dessous. */
.carte {
  /* ⚠ `.carte` EXISTE DÉJÀ dans style.css (ligne ~434) avec `background:
     var(--beton)` et une bordure : c'est la carte finale telle que la maquette
     l'avait dessinée. En réutilisant le nom, cette page héritait de la boîte —
     un rectangle plein, cerné d'un trait clair, autour de tout le verdict.
     On la neutralise ici, et on ne la rétablit que dans `.page--partage`, où
     la carte est un objet fermé qu'on exporte en image. */
  background: none;
  border: 0;
  padding: var(--sp-32) var(--sp-24) var(--sp-48);
  gap: 0;
  position: relative;
}

/* LE 9:16 N'EXISTE QU'À L'EXPORT.
   Le premier essai posait la carte à l'écran dans son cadre de partage : un
   rectangle bordé au milieu de la page, avec du vide autour. C'est le format
   de l'IMAGE, pas celui de la lecture. À l'écran le verdict occupe la largeur
   et le contenu s'enchaîne ; le cadre ne réapparaît qu'au moment de fabriquer
   l'image, où il a une raison d'être (1080 × 1920, plein écran d'une story). */
.page--partage .carte {
  background: var(--nuit);
  border: 1px solid var(--trait);
  width: min(22.5rem, 100vw - 2rem);
  aspect-ratio: 9 / 16;
  margin: var(--sp-24) auto;
  padding: var(--sp-24);
  background: var(--nuit);
  border: 1px solid var(--trait);
  display: grid;
  grid-template-rows: auto auto 1fr auto auto auto;
  overflow: hidden;
}
.page--partage .fiche { display: none; }
/* Pas de halo à l'écran. `.terrain` éclaire déjà la page depuis un seul point ;
   en superposer un second dessinait un rectangle flou au milieu du texte. Le
   halo n'a de sens que dans l'image partagée, où la carte est un objet fermé
   avec ses propres bords. */
.page--partage .carte::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(110% 60% at 50% 24%,
              oklch(0.685 0.178 48 / 0.13), transparent 64%);
}
.carte > * { position: relative; }
.marque::before {
  content: '●'; color: var(--cuir); margin-right: 0.45em; font-size: 0.8em;
}

.carte__nom {
  font-family: var(--display); font-weight: 700;
  font-size: 1.5rem; line-height: 1; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--craie);
}
.carte__sous {
  margin-top: var(--sp-4);
  font-size: var(--t-micro); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--craie-bas);
}

/* Le verdict. UN SEUL gros chiffre sur toute la carte — mais pas énorme.
   Le premier essai mettait 105 px de chiffre SOUS un libellé de 30 px : deux
   masses lourdes qui s'additionnaient au lieu de se hiérarchiser. Le chiffre
   descend à ~62 px, le libellé à 15 px espacé. Le rapport avec le second
   niveau reste supérieur à 2, donc la domination tient — c'est la charge
   totale d'encre qui baisse, pas la hiérarchie. */
.verdict { align-self: center; padding: var(--sp-32) 0 var(--sp-24); }
.verdict__chiffre {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(3.6rem, 1.6rem + 9vw, 5.2rem);
  line-height: 0.82; letter-spacing: -0.015em;
  color: var(--craie);
  font-variant-numeric: tabular-nums;
}
.verdict__chiffre sup { font-size: 0.28em; color: var(--cuir); margin-left: 0.05em; }
.verdict__chiffre--mot { font-size: 2rem; line-height: 1.05; letter-spacing: 0.01em; }
.verdict__libelle {
  margin-top: var(--sp-16);
  font-family: var(--display); font-weight: 700;
  font-size: 0.95rem; line-height: 1.25;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--cuir);
}
.verdict__appui {
  margin-top: var(--sp-12);
  font-size: var(--t-micro); line-height: 1.5; color: var(--craie-bas);
  font-variant-numeric: tabular-nums;
}

/* Les deux rangées de chiffres moyens. Rapport 2,4 avec le verdict : c'est ce
   qui fait qu'ils l'accompagnent au lieu de lui disputer l'attention. */
/* Un filet fin entre les rangées. Il structure sans enfermer — le problème
   n'a jamais été ces traits-là, mais le cadre qui entourait l'ensemble. */
.rangee {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: var(--sp-12);
  padding: var(--sp-24) 0 var(--sp-8);
  border-top: 1px solid var(--trait);
}
.rangee__val {
  font-family: var(--display); font-weight: 700;
  font-size: 1.75rem; line-height: 1; color: var(--cuir);
  font-variant-numeric: tabular-nums;
}
.rangee__val sup { font-size: 0.42em; }
.rangee__val--sodium { color: var(--sodium); }
.rangee__val--eteint { color: var(--craie-bas); }
.rangee__lib {
  margin-top: var(--sp-8);
  font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas); line-height: 1.3;
}

/* La ligne de moyennes. Elle remplace une phrase qui ne disait rien (« 1,0
   contre de moyenne » n'est pas une information, c'est du remplissage). Une
   ligne pts/reb/pas/ctr/int est ce que lit d'abord n'importe qui suit le
   basket, et elle se compare d'une carte à l'autre. */
.moyennes {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: var(--sp-8);
  padding: var(--sp-24) 0 var(--sp-8);
  border-top: 1px solid var(--trait);
}
.moyennes__val {
  font-family: var(--display); font-weight: 700;
  font-size: 1.25rem; line-height: 1; color: var(--craie);
  font-variant-numeric: tabular-nums;
}
.moyennes__lib {
  margin-top: var(--sp-4);
  font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}

/* ═══ 2. LA FICHE ═══════════════════════════════════════════════════════════ */
.section { padding: var(--sp-32) var(--sp-16) 0; }
.section__titre {
  font-family: var(--display); font-weight: 800;
  font-size: var(--n3); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--craie); margin-bottom: var(--sp-16);
}

/* La table. Six colonnes, 317 px sur les 342 disponibles à 390 px de large :
   AUCUN SCROLL HORIZONTAL. Basketball Reference fige la colonne saison et fait
   défiler le reste ; sur un écran de téléphone ça oblige à balayer pour lire
   une ligne, ce qui interdit la comparaison d'un coup d'œil — qui est
   précisément ce qu'on demande à cette table. */
/* MISE EN PAGE FIXE ET COLONNES DÉCLARÉES. Sans ça, les largeurs se règlent
   sur le contenu de chaque cellule et bougent d'une carrière à l'autre —
   « 2026 » et « 70 » n'ont pas la même largeur naturelle. */
.saisons { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* Largeurs déclarées, en pourcentage : la colonne des points est la plus
   large parce que c'est le champ de lecture, celle de l'équipe la plus étroite
   parce qu'elle porte trois lettres. */
.c-an  { width: 19%; }
.c-eq  { width: 13%; }
.c-mj  { width: 14%; }
.c-pts { width: 20%; }
.c-reb { width: 17%; }
.c-pas { width: 17%; }
.saisons th {
  padding: var(--sp-8) var(--sp-4);
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--craie-bas); text-align: right;
  border-bottom: 1px solid var(--trait);
}
.saisons th:first-child, .saisons th:nth-child(2) { text-align: left; }
.saisons td {
  padding: var(--sp-8) var(--sp-4);
  font-size: 1.05rem; color: var(--craie-mi);
  font-variant-numeric: tabular-nums; text-align: right;
  line-height: 1.1;
}
/* L'alignement se règle PAR TYPE DE LIGNE, jamais par rang de cellule.
   La ligne de total fusionne ses deux premières colonnes : sa 2e cellule est
   donc « MJ » et non « ÉQ ». Un `td:nth-child(2)` global alignait ce total à
   gauche pendant que toute sa colonne était à droite — c'est ce qui décalait
   le nombre de matchs. */
.saisons tr.saison td:first-child,
.saisons tr.saison td:nth-child(2) { text-align: left; }
.saisons tr.total td:first-child { text-align: left; }

/* L'année et l'équipe sont des repères, pas des valeurs : même corps que les
   chiffres pour que la ligne ne sautille pas, mais nettement en retrait. */
.saisons tr.saison td:first-child { color: var(--craie-bas); letter-spacing: 0.02em; }
.saisons tr.saison td:nth-child(2) {
  font-family: var(--display); font-weight: 700;
  letter-spacing: 0.1em; color: var(--craie-bas);
}
/* Rebonds et passes accompagnent, ils ne se lisent pas colonne par colonne.
   Les mettre en retrait dégage le champ de lecture, qui est la colonne PTS.
   Scopé aux lignes de saison, pour la même raison que ci-dessus. */
.saisons tr.saison td:nth-child(5),
.saisons tr.saison td:nth-child(6) { color: var(--craie-bas); }
/* Une ligne sur deux à peine éclaircie : c'est ce qui permet de suivre une
   ligne sur toute sa largeur sans perdre le fil. Aucun trait, aucune bordure —
   22 filets horizontaux transformeraient la fiche en grille de tableur. */
.saisons tbody tr.saison:nth-of-type(even) td { background: oklch(1 0 0 / 0.022); }

/* La colonne PTS est le champ de lecture : sa couleur encode trois états, et
   en balayant du pouce on voit le pic de carrière se former. Un graphique fait
   de chiffres, sans un pixel de décoration. */
.pts--bas    { color: var(--craie-bas); }
.pts--haut   { color: var(--craie); font-weight: 600; }
.pts--record { color: var(--cuir); font-weight: 700; }

/* Le repérage des grandes saisons se fait par un lavis de fond, jamais par une
   bordure latérale colorée — c'est l'empreinte de design générée la plus
   reconnaissable, et .impeccable.md l'interdit. */
tr.saison--titre  td { background: oklch(0.87 0.118 90 / 0.10); }
tr.saison--top    td { background: oklch(0.685 0.178 48 / 0.10); }

/* PLUS AUCUN TEXTE DANS LE TABLEAU.
   Deux essais ont échoué de la même façon : des lignes de mots intercalées
   entre les lignes de chiffres. Même réduites et décalées, elles cassaient le
   balayage vertical — on ne pouvait plus descendre la colonne des points, qui
   est la seule raison d'être de cette table.
   Un tableau, c'est des nombres. Les mots vont en dessous, dans « Les saisons
   qui comptent ». Ce qui reste ici pour repérer une grande saison : le lavis
   de fond et la couleur de la colonne des points. Deux signaux, zéro mot. */

/* Les saisons qui comptent — le texte, à sa place, hors de la grille. */
.marquante {
  display: grid; grid-template-columns: 3.4rem 1fr; gap: var(--sp-12);
  padding: var(--sp-12) 0;
  border-bottom: 1px solid var(--trait);
}
.marquante__an {
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--craie-bas);
  font-variant-numeric: tabular-nums;
}
.marquante__faits {
  font-family: var(--display); font-weight: 700;
  font-size: 0.875rem; letter-spacing: 0.12em; text-transform: uppercase;
  line-height: 1.55; color: var(--craie-mi);
}
.marquante__faits b { color: var(--sodium); font-weight: 700; }
.marquante__faits em { color: var(--cuir); font-style: normal; }
.marquante__faits i { color: var(--sang); font-style: normal; }
.marquante__ligne {
  margin-top: var(--sp-4);
  font-family: var(--texte); font-weight: 400;
  font-size: var(--t-micro); letter-spacing: 0; text-transform: none;
  color: var(--craie-bas); font-variant-numeric: tabular-nums;
}

.acte-sep td {
  padding: var(--sp-16) var(--sp-4) var(--sp-4);
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--cuir); text-align: left;
  border-top: 1px solid var(--trait);
}
.total td {
  padding-top: var(--sp-12);
  border-top: 1px solid var(--cuir-sourd);
  font-family: var(--display); font-weight: 800;
  font-size: var(--n4); color: var(--craie);
}

/* Palmarès et classements */
.bloc { display: grid; gap: var(--sp-12); }
.ligne-cl {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-12); padding-bottom: var(--sp-12);
  border-bottom: 1px solid var(--trait);
}
.ligne-cl__gauche {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--craie-bas);
}
.ligne-cl__val {
  font-family: var(--display); font-weight: 800;
  font-size: var(--n3); color: var(--craie);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ligne-cl__val sup { font-size: 0.45em; color: var(--cuir); }

/* ═══ LES ÉCRANS DE JEU ══════════════════════════════════════════════════════

   UN ÉCRAN, UN GESTE, JAMAIS DE DÉFILEMENT.

   C'est la règle structurante, reprise de Destiny Eleven après relecture de
   son analyse. Trois zones fixes : la crête en haut (où on est), le corps au
   centre (ce qui se passe), les actions en bas dans la zone du pouce. La zone
   centrale est la seule élastique, et son contenu doit rentrer. Si ça ne
   rentre pas, on retire — on ne rapetisse pas, et on ne fait surtout pas
   défiler : un jeu qui se joue au pouce ne peut pas demander de remonter pour
   trouver le bouton.

   Seule exception assumée : la fiche de fin (`.scene--fiche`). Ce n'est plus
   la boucle, c'est l'archive qu'on relit et qu'on partage.

   Tout emploie --accent et non --cuir : c'est ce qui permet à l'ambiance de
   basculer en playoffs sans toucher au balisage. */

.scene {
  display: grid;
  grid-template-rows: auto 1fr auto;

  /* LARGEUR FIXE. La colonne du jeu ne varie pas : ni d'un écran à l'autre,
     ni d'un bloc à l'autre. C'est elle, et elle seule, qui porte la mesure de
     lecture — 27 rem de texte utile, soit une quarantaine de signes à la
     taille des énoncés, dans la fourchette confortable. Les blocs ne portent
     donc plus de `max-width` : ils remplissent la colonne.
     La largeur vient de la piste déclarée par `.page--jeu`, pas d'ici : la
     scène se contente de la remplir. */
  width: 100%;

  /* HAUTEUR PLAFONNÉE, ET CENTRÉE.
     Deux erreurs successives ici, la seconde née de la correction de la
     première. `min-height: 100svh` laissait la scène grandir et poussait le
     bouton hors du champ. `height: 100svh` l'a réglé sur téléphone, mais sur
     une fenêtre d'ordinateur haute le bouton se retrouvait à quarante
     centimètres du titre : techniquement visible, visuellement orphelin.
     La scène ne dépasse donc jamais 42 rem de haut, et se centre dans ce qui
     reste. Sur téléphone elle remplit l'écran ; sur grand écran elle reste un
     bloc compact, où le bouton appartient encore à ce qu'il valide. */
  /* SUR TÉLÉPHONE, LA SCÈNE REMPLIT L'ÉCRAN. Le plafond de 42 rem existait pour
     une raison réelle — sur une fenêtre d'ordinateur haute, le bouton finissait
     à quarante centimètres du titre — mais appliqué au téléphone il centrait une
     scène de 672 px dans 844, donc la crête flottait à quatre-vingts pixels du
     bord avec du vide au-dessus, pendant que le filet de progression, lui,
     restait collé en haut. Deux éléments d'en-tête à deux hauteurs différentes.
     Le plafond est donc réservé aux grands écrans, plus bas. */
  height: 100svh;
  /* L'ENCOCHE. Sans `safe-area-inset-top`, la crête passe sous la barre système
     sur tout téléphone récent. La marge visible se compte À PARTIR de l'encoche,
     pas du bord physique. */
  padding:
    calc(var(--sp-24) + env(safe-area-inset-top)) var(--sp-24)
    calc(var(--sp-24) + env(safe-area-inset-bottom));
  transition: opacity 180ms var(--ease-sortie), transform 180ms var(--ease-sortie);
}
.scene.entre { opacity: 0; transform: translateY(3px); }

/* La fiche est le seul écran qui défile, et c'est voulu. */
/* LES ZONES DE RESPIRATION DU DÉFILEMENT.
   Un document qui commence exactement au premier pixel et s'arrête exactement
   au dernier donne l'impression d'être coupé aux deux bouts — on voit la
   tranche. On réserve donc du vide en haut ET en bas, plus l'encoche et la
   barre système du téléphone. Le contenu ne touche jamais un bord.

   `scroll-padding-block` fait la même chose pour les ancres du rail : une
   section visée ne colle plus au sommet de l'écran, elle arrive avec de l'air
   au-dessus d'elle. */
.scene--fiche {
  display: block; height: auto; min-height: 0;
  padding:
    calc(var(--sp-32) + env(safe-area-inset-top)) 0
    calc(var(--sp-96) + env(safe-area-inset-bottom));
  scroll-padding-block: var(--sp-48) var(--sp-48);
}

/* Au-delà du téléphone, on replafonne et on recentre : une colonne de texte
   qui occupe deux mille pixels de haut n'est plus une interface, c'est une
   affiche, et le bouton s'éloigne de ce qu'il valide. */
@media (min-width: 43.75em) {
  /* `:not(.scene--fiche)` EST OBLIGATOIRE. Cette requête vient APRÈS la règle
     de la fiche et a la même spécificité — elle l'écrasait donc au-dessus de
     700 px de large, plafonnant un document de trois mille pixels à 42 rem et
     le recentrant. La fiche paraissait tronquée sur tout écran d'ordinateur,
     et seulement là : c'est le genre de régression qu'un test sur téléphone ne
     voit jamais. */
  .scene:not(.scene--fiche):not(.scene--accueil) { height: min(100svh, 42rem); margin: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .scene, .scene.entre { transition: none; opacity: 1; transform: none; }
}

/* ─── Les trois zones ─────────────────────────────────────────────────────── */

.crete {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-12); min-width: 0;
  padding-bottom: var(--sp-16);
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--craie-bas);
}
.crete:empty { padding: 0; }
.crete span { white-space: nowrap; }
.crete span:last-child { overflow: hidden; text-overflow: ellipsis; min-width: 0; }

/* Le corps est centré verticalement : sur un écran court le contenu reste
   dans le champ de vision, sur un écran long il ne flotte pas en haut. */
/* La seule zone élastique. Si son contenu déborde — écran court, texte long,
   corps de police agrandi par le système — c'est ELLE qui défile, et les
   actions restent collées en bas. Le bouton n'est jamais hors d'atteinte. */
.corps {
  display: grid; align-content: safe center; gap: var(--sp-12);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.corps::-webkit-scrollbar { display: none; }

.actions { display: grid; gap: var(--sp-8); padding-top: var(--sp-24); }

/* La crête est un bloc de deux lignes : où l'on est et sous quel maillot, puis
   les deux mesures qui bougent. Une grille plutôt qu'un `space-between`, pour
   que les quatre valeurs s'alignent sur DEUX bords et pas quatre.

   TOUTE LA COLONNE DE DROITE EST ALIGNÉE À DROITE, franchise comprise. Seule la
   ligne des mesures l'était : le nom du club restait calé à gauche de sa
   colonne et le niveau à droite de la même colonne, donc les deux ne tombaient
   jamais l'un sous l'autre. */
.crete {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-2) var(--sp-12);
  align-items: baseline;
}
.crete > :nth-child(2n) { text-align: end; }

.crete__mesure {
  display: inline-flex; align-items: center; gap: var(--sp-4);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  color: var(--craie-bas);
  font-variant-numeric: tabular-nums;
}
.crete__mesure b { color: var(--craie-mi); font-weight: 800; }
.crete > .crete__mesure:last-child { justify-content: end; }

/* ─── Les icônes ────────────────────────────────────────────────────────────
   Autorisées depuis le 8 août 2026, et tenues par la DA : filet d'un pixel,
   `currentColor`, aucun aplat, aucun coin arrondi. `non-scaling-stroke` est ce
   qui les garde cohérentes avec les filets de l'interface — sans lui, une
   forme dessinée dans un repère de 16 produirait un trait de deux pixels. */
.ico {
  inline-size: 0.95em; block-size: 0.95em;
  flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: square; stroke-linejoin: miter;
  vector-effect: non-scaling-stroke;
}

/* ─── Les faits ─────────────────────────────────────────────────────────────
   Même grammaire que les Moments — une année à gauche, le récit à droite —
   mais avec une ligne forte, parce qu'un fait a un titre et un Moment n'en a
   pas. */
/* Un repère : une année, un nom qui claque, une ligne qui le raconte.
   Portait la section « Les faits », supprimée parce qu'elle répétait la carte,
   le tableau et le palmarès. Elle sert désormais aux Moments, qui sont les
   seules entrées de la fiche dont le contenu n'existe nulle part ailleurs. */
.repere {
  display: grid; grid-template-columns: 3.5rem 1fr; gap: var(--sp-12);
  padding: var(--sp-16) 0;
  border-top: 1px solid var(--trait);
}
.repere:first-child { border-top: 0; }
.repere__an {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.12em;
  color: var(--craie-bas); font-variant-numeric: tabular-nums;
  padding-top: 0.2em;
}
.repere__fort {
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: var(--t-petit); letter-spacing: 0.1em;
  color: var(--craie);
}
.repere__texte {
  font-family: var(--texte); font-size: var(--t-petit); line-height: 1.5;
  color: var(--craie-mi); text-wrap: pretty; margin-top: var(--sp-2);
}

/* ─── La jauge de carrière ──────────────────────────────────────────────────
   UN FILET, EN HAUT, SANS CHIFFRE. La première version portait le palier nommé
   et le niveau au-dessus de la barre : une donnée que le joueur n'a pas
   demandée, posée là où il lit ses situations, et qui dévoilait une échelle
   qu'il vaut mieux découvrir. Retirée.

   Elle est FIXE et vit hors de la scène (voir index.html) : un élément recréé à
   chaque écran repartirait de zéro et ne pourrait pas transitionner. Permanent,
   il ne change que de largeur — donc il monte.

   FORMULE ÉCRITE, comme l'exige H10 : `1 − log(rang) / log(borne)`, calculée
   par `majJauge()` dans web/game.js. */

.jauge {
  position: fixed;
  inset-block-start: env(safe-area-inset-top); inset-inline: 0;
  z-index: 20;
  block-size: 2px;
  pointer-events: none;
}
.jauge__part {
  display: block;
  block-size: 100%;
  inline-size: 0;
  background: var(--accent);
  /* Assez lent pour qu'on la voie bouger, assez court pour ne pas retarder la
     lecture de l'écran qui vient d'arriver. */
  transition: inline-size 900ms var(--ease-sortie);
}

@media (prefers-reduced-motion: reduce) {
  .jauge__part { transition: none; }
}

/* PAS DE JAUGE SUR LA FICHE. La carrière est finie : une barre de progression
   au-dessus d'un bilan définitif ne mesure plus rien, et un filet de couleur
   qui traverse le haut d'un document qu'on va screenshoter le salit. La fiche
   n'est plus la boucle, c'est l'archive. */
body:has(.scene--fiche) .jauge { display: none; }

/* ─── Titres et texte ─────────────────────────────────────────────────────── */

.sur {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--craie-bas);
}
.titre-jeu {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(4rem, 2rem + 12vw, 6.5rem); line-height: 0.86;
  letter-spacing: -0.01em; text-transform: uppercase; color: var(--craie);
}
.titre-ecran {
  font-family: var(--display); font-weight: 700;
  font-size: 1.6rem; line-height: 1.1; letter-spacing: 0.01em;
  text-transform: uppercase; color: var(--craie);
}
.chapo { font-size: var(--t-base); line-height: 1.55; color: var(--craie-mi); }
.texte { font-size: var(--t-petit); line-height: 1.55; color: var(--craie-bas); }
.texte-eteint { font-size: var(--t-petit); color: var(--craie-bas); }
.etiquette-fine {
  margin-top: var(--sp-4);
  font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}

/* ─── Les chiffres : un seul --n1 par écran ───────────────────────────────── */

.n1 {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(3.4rem, 1.4rem + 9vw, 5rem);
  line-height: 0.88; letter-spacing: -0.015em;
  color: var(--craie); font-variant-numeric: tabular-nums;
}
.n1__libelle {
  font-family: var(--display); font-weight: 700;
  font-size: 0.9rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--accent);
}
.n3 {
  font-family: var(--display); font-weight: 700;
  font-size: 1.5rem; line-height: 1;
  color: var(--craie); font-variant-numeric: tabular-nums;
}
.rangee-jeu {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: var(--sp-8);
  padding-top: var(--sp-16);
  border-top: 1px solid var(--trait);
}

/* ─── Boutons. Un seul fort par écran. ────────────────────────────────────── */

.bouton, .option, .choix {
  background: none; border: 1px solid var(--trait); border-radius: 0;
  text-align: left; cursor: pointer;
  transition: border-color 180ms var(--ease-sortie),
              background 180ms var(--ease-sortie), color 180ms var(--ease-sortie);
}
.bouton {
  padding: var(--sp-16) var(--sp-24);
  color: var(--craie);
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-base); letter-spacing: 0.14em; text-transform: uppercase;
}
.bouton--fort { border-color: var(--accent-sourd); color: var(--accent); }
.bouton:hover:not(:disabled), .option:hover, .choix:hover { background: oklch(1 0 0 / 0.04); }

/* ─── Cibles tactiles et focus ──────────────────────────────────────────────
   H9 : 44 px au minimum, toujours. Les paddings actuels y arrivent pour une
   ligne de texte, mais rien ne le GARANTISSAIT — une étiquette courte dans une
   police plus petite passait dessous sans que rien ne le signale.

   Et le jeu n'avait AUCUN style de focus : les seules règles `:focus-visible`
   de la feuille sont scopées `.apercu`, c'est-à-dire la maquette. Un joueur au
   clavier voyait donc l'anneau bleu par défaut de Chrome au milieu d'une
   palette béton et cuir. */
.bouton, .option, .choix, .offre { min-height: 2.75rem; }

.bouton:focus-visible,
.option:focus-visible,
.choix:focus-visible,
.offre:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.bouton:hover:not(:disabled) { border-color: var(--accent); }

.option {
  padding: var(--sp-12) var(--sp-16);
  color: var(--craie-mi);
  font-family: var(--texte); font-size: var(--t-petit); line-height: 1.4;
}
.option:hover { border-color: var(--accent); color: var(--craie); }

/* ─── La création : une question par écran ────────────────────────────────── */

.grille-choix { display: grid; gap: var(--sp-8); }
.choix { display: grid; gap: var(--sp-2); padding: var(--sp-12) var(--sp-16); }
.choix__nom {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-base); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--craie);
}
.choix__desc { font-size: var(--t-micro); line-height: 1.4; color: var(--craie-bas); }

/* ─── La situation et sa chute ────────────────────────────────────────────── */
/* Le texte EST l'interface : il occupe l'écran, le reste se tient en périphérie. */

.situation {
  font-size: var(--t-lu); line-height: 1.45; color: var(--craie);
}
.issue {
  font-size: var(--t-lu); line-height: 1.45; color: var(--craie);
  padding-bottom: var(--sp-8);
}
.recit {
  font-size: var(--t-petit); line-height: 1.5; color: var(--craie-mi);
}

/* ─── L'IMPACT D'UN CHOIX, EN PASTILLES ───────────────────────────────────
   Forme reprise de Destiny Eleven (`.fx-chips`), où l'effet d'un choix
   s'affiche en une rangée de pastilles colorées plutôt qu'en liste. On lit
   l'effet d'un coup d'œil au lieu de parcourir des lignes.

   Le mécanisme est le leur, la forme est la nôtre : coins vifs au lieu de
   999 px de rayon, filet d'un pixel, fond teinté à 10 %, nos polices. */

.pastilles {
  display: flex; flex-wrap: wrap; gap: var(--sp-8);
  padding-top: var(--sp-16);
  border-top: 1px solid var(--trait);
}
.pastille-fx {
  padding: 0.3rem 0.625rem;
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  border: 1px solid; background: transparent;
  opacity: 0;
  animation: pastilleEntre 350ms var(--ease-sortie) forwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}
.pastille-fx b { font-weight: 700; opacity: 0.72; margin-right: 0.45em; }

.pastille-fx--gain {
  color: var(--gain);
  border-color: color-mix(in oklch, var(--gain) 50%, transparent);
  background: color-mix(in oklch, var(--gain) 10%, transparent);
}
.pastille-fx--perte {
  color: var(--perte);
  border-color: color-mix(in oklch, var(--perte) 50%, transparent);
  background: color-mix(in oklch, var(--perte) 9%, transparent);
}
.pastille-fx--argent {
  color: var(--monnaie);
  border-color: color-mix(in oklch, var(--monnaie) 50%, transparent);
  background: color-mix(in oklch, var(--monnaie) 11%, transparent);
}
/* Un trophée n'est pas un gain de plus : il doit se voir de l'autre bout de la
   pièce. C'est la seule chose du jeu qui pulse en boucle. */
.pastille-fx--trophee {
  color: var(--sodium);
  border-color: color-mix(in oklch, var(--sodium) 65%, transparent);
  background: color-mix(in oklch, var(--sodium) 14%, transparent);
  animation: pastilleEntre 350ms var(--ease-sortie) forwards,
             lueurTrophee 1.8s ease-in-out 0.5s infinite;
}

@keyframes pastilleEntre {
  from { opacity: 0; transform: translateY(6px) scale(0.92); }
  to   { opacity: 1; transform: none; }
}
@keyframes lueurTrophee {
  0%, 100% { text-shadow: none; }
  50%      { text-shadow: 0 0 12px color-mix(in oklch, var(--sodium) 80%, transparent); }
}

/* ─── Bilan de saison ─────────────────────────────────────────────────────── */

.progression {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.palier__titre {
  font-family: var(--display); font-weight: 800;
  font-size: 1.2rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--sodium); line-height: 1.25;
}
.jalons-ligne {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--craie-bas);
}
/* Même gouttière latérale que `.carte` (24 px) : sans ça, « 34 ANS · 20
   SAISONS » et le nom du joueur ne commençaient pas sur la même verticale. */
.fin-tete { display: grid; gap: var(--sp-8); padding: var(--sp-48) var(--sp-24) 0; }
.carte__identite { margin-top: 0; }

/* ─── Ce qui vient après la fiche ───────────────────────────────────────────
   Le bas de la fiche était un cul-de-sac : plus un seul bouton après la
   dernière ligne de statistiques. Ces trois gestes sont l'endroit exact où se
   décide si quelqu'un joue une fois ou dix, donc ils respirent — la marge
   haute les détache du tableau au lieu de les y coller. */
/* ─── Le défi du jour ───────────────────────────────────────────────────────
   Un bloc, pas une ligne dans la pile d'actions : c'est une proposition
   différente de « commencer une partie », et elle doit se lire comme telle.
   Filets d'un pixel en haut et en bas, aucun fond, aucun rayon — la séparation
   se fait par le trait et la respiration, comme partout ailleurs.

   L'accent ne porte QUE sur la contrainte du jour. C'est la seule information
   qui intrigue : la date ne fait qu'horodater, la règle ne fait qu'expliquer. */
.dujour {
  margin-top: var(--sp-32);
  padding-top: var(--sp-16);
  border-top: 1px solid var(--trait);
  display: grid; gap: var(--sp-4);
}
.dujour__quoi {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}
.dujour__depart {
  margin: 0; font-family: var(--display); font-weight: 800;
  font-size: 1.35rem; letter-spacing: 0.02em; line-height: 1.15;
  color: var(--cuir);
}
.dujour__regle {
  margin: 0 0 var(--sp-8); font-size: var(--t-petit);
  color: var(--craie-mi); line-height: 1.45; text-wrap: pretty;
}
.dujour__bouton { text-align: center; }

/* ─── La série et la bascule ────────────────────────────────────────────────
   Les paris gagnés se comptent en TRAITS DE CRAIE à côté du niveau, comme les
   victoires au marqueur sur un poteau de playground. Invisibles à zéro, trois
   emplacements dès que la série vit. Pendant la saison de bascule, le ballon,
   le niveau, les traits et la jauge passent au sodium — la couleur du
   projecteur — et le halo du terrain monte d'un cran. À la redescente, tout
   tombe d'un coup, sans un mot : c'est la disparition qui donne envie de
   remonter. */
.serie { display: inline-flex; gap: 0.28em; margin-inline-start: var(--sp-8); align-items: center; }
.serie i {
  display: block; inline-size: 2px; block-size: 0.75em;
  background: var(--cuir); transform: rotate(8deg);
}
.serie i.a-venir { background: var(--trait); }
/* Le trait qui vient de se gagner se dessine — l'accusé de réception standard. */
@keyframes se-dessine { from { transform: rotate(8deg) scaleY(0); } to { transform: rotate(8deg) scaleY(1); } }
.serie i.neuf { animation: se-dessine 220ms var(--ease-sortie); transform-origin: bottom; }

.crete__mesure--feu, .crete__mesure--feu b, .crete__mesure--feu .ico { color: var(--sodium); }
.serie--feu i { background: var(--sodium); }
.n1--feu { color: var(--sodium); }

/* Le halo de la saison allumée : un voile fixe DERRIÈRE le contenu (z négatif,
   au-dessus du tracé), jamais un fond qui écrase les ambiances de club. */
.terrain--bascule::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(120% 70% at 50% -20%, oklch(0.32 0.05 78 / 0.5), transparent 62%);
}
.terrain--bascule .jauge__part { background: var(--sodium); }

/* Le palmarès personnel sur l'accueil. Un filet au-dessus, rien d'autre : ce
   n'est pas une carte, c'est une trace. */
.record {
  margin-top: var(--sp-24); padding-top: var(--sp-16);
  border-top: 1px solid var(--trait);
  display: grid; gap: var(--sp-8);
}
.record__quoi {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}
/* LE CHIFFRE ANNONCE, LE TEXTE PRÉCISE — la grammaire de tout le jeu. Une
   phrase (« Amir Rivas et fini 152e passeur… ») rangeait le palmarès dans le
   registre du récit ; c'est une MESURE, elle se présente comme les autres :
   valeur en display, étiquette en micro, détail en dessous. */
.record__corps {
  display: grid; grid-template-columns: auto 1fr;
  gap: var(--sp-16); align-items: center;
}
.record__score { display: grid; justify-items: center; }
.record__val {
  font-family: var(--display); font-weight: 800; font-size: 1.85rem;
  line-height: 1; color: var(--craie); font-variant-numeric: tabular-nums;
}
.record__lib {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}
.record__nom { margin: 0; font-weight: 600; font-size: var(--t-base); color: var(--craie); }
.record__sous { margin: 0; font-size: var(--t-petit); color: var(--craie-mi); line-height: 1.4; }

/* L'ACCUEIL EST UN DOCUMENT, PAS UN ÉCRAN DE JEU.
   Trois règles plus fortes le traitaient encore comme la boucle : le verrou de
   défilement du body, et les deux media queries d'ordinateur qui replafonnent
   la hauteur à 42 rem avec une spécificité supérieure. Résultat mesuré : le
   contenu débordait sous le pied de grille et les boutons flottaient
   par-dessus le texte. Les trois portent désormais l'exception, comme pour la
   fiche — même cause, même remède, voir le commentaire du verrou. */
.scene--accueil { height: auto; min-height: 100svh; }

/* L'adresse de carrière : une ligne sous les moyennes, dans le registre des
   étiquettes. Elle complète la lecture sans concurrencer les chiffres. */
.adresse {
  margin: var(--sp-12) 0 0;
  font-size: var(--t-petit); color: var(--craie-mi);
  text-align: center; text-wrap: balance;
}

.fin-actions {
  display: grid; gap: var(--sp-12);
  padding: var(--sp-48) var(--sp-24) var(--sp-32);
  max-width: 34rem; margin-inline: auto;
}
.fin-actions .bouton, .fin-actions .option { text-align: center; }

/* ─── Le mercato : offres de fac et de contrat ────────────────────────────── */
/* La décision la plus lourde du jeu mérite la carte la plus dense. Chaque
   offre montre ses trois chiffres côte à côte, parce que le choix est un
   arbitrage — l'argent, le temps de jeu et les chances de titre ne se trouvent
   jamais au même endroit. */

.offres { display: grid; gap: var(--sp-8); }
.offre {
  display: grid; gap: var(--sp-4);
  padding: var(--sp-12) var(--sp-16);
  background: none; border: 1px solid var(--trait); border-radius: 0;
  text-align: left; cursor: pointer;
  transition: border-color 180ms var(--ease-sortie), background 180ms var(--ease-sortie);
}
.offre:hover { border-color: var(--accent); background: oklch(1 0 0 / 0.04); }
.offre__tete { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-8); }
.offre__nom {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-base); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--craie);
}
.offre__tag {
  font-family: var(--display); font-weight: 700;
  font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--craie-bas);
}
.offre__role { font-size: var(--t-micro); line-height: 1.4; color: var(--craie-bas); }
.offre__chiffres {
  display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-12);
  margin-top: var(--sp-4);
}
.offre__chiffres b {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--craie-mi); font-variant-numeric: tabular-nums;
}
.v-gain   { color: var(--gain) !important; }
.v-argent { color: var(--monnaie) !important; }

/* Un mot peut occuper la place du chiffre géant : « Non drafté », le nom d'une
   franchise, « Option levée ». C'est le même emplacement, donc la même
   fonction — la réponse à la question du moment. */
.n1--mot { font-size: clamp(2.2rem, 1rem + 5.5vw, 3.2rem); line-height: 1.02; }

/* ═══ LA RÉACTION À UNE ISSUE ════════════════════════════════════════════════
   Trois degrés, jamais un seul. Toute issue favorable doit se sentir, sinon le
   joueur n'a pas l'impression d'avoir fait un choix — mais tout célébrer
   revient à ne rien célébrer, et les moments rares perdent leur prix.

   Une issue défavorable ne reçoit AUCUN des trois. Elle se lit, sèchement.
   C'est le contraste qui donne sa valeur au reste : si perdre faisait le même
   bruit que gagner, le bruit ne voudrait plus rien dire. */

/* Les écarts entrent un par un, le positif d'abord. 45 ms d'intervalle : au
   delà on attend, et attendre après un choix est insupportable. */
@keyframes monteEcart {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Le chiffre pulse une fois en arrivant. 220 ms, jamais bloquant. */
@keyframes pulseVal {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.09); }
  100% { transform: scale(1); }
}

/* Le filet au-dessus des écarts prend la couleur du résultat. Un signe de
   plus, gratuit, lisible avant même d'avoir lu un chiffre. */
.issue--fort .pastilles { border-top-color: var(--gain); }
.issue--net  .pastilles { border-top-color: color-mix(in oklch, var(--gain) 55%, var(--trait)); }
.issue--dur  .pastilles { border-top-color: var(--perte); }

/* LA MONTÉE DE LUMIÈRE. Le halo du terrain gonfle et retombe, sans rien
   déplacer. C'est la seule célébration du jeu — aucun confetti, aucune
   particule, aucun tremblement. */
.terrain::before {
  content: '';
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  opacity: 0;
  background: radial-gradient(70% 45% at 50% 8%,
    color-mix(in oklch, var(--accent) 40%, transparent), transparent 70%);
  transition: opacity 900ms var(--ease-sortie);
}
.terrain.pulse::before { opacity: 1; transition-duration: 260ms; }

/* Intensité 2 — le palier. Un trophée, deux ou trois fois par carrière. */
.palier {
  padding: var(--sp-12) 0;
  animation: monteEcart 420ms var(--ease-sortie) both;
  animation-delay: 120ms;
}

@media (prefers-reduced-motion: reduce) {
  .pastille-fx, .palier { animation: none; opacity: 1; transform: none; }
  .terrain::before, .terrain.pulse::before { transition: none; opacity: 0; }
}

/* ─── Fenêtres basses ─────────────────────────────────────────────────────
   Un écran d'ordinateur en demi-hauteur, ou un téléphone en paysage. Plutôt
   que de laisser déborder, on resserre : le chiffre géant perd un tiers, les
   blancs se referment. La hiérarchie tient, la densité monte. */
/* En `em` et non en pixels : une requête média en pixels ignore la taille de
   police choisie par l'utilisateur et le zoom du navigateur. 43,75 em valent
   700 px à racine standard, et davantage dès que l'utilisateur agrandit —
   ce qui est exactement le moment où le palier doit se déclencher. */
@media (max-height: 43.75em) {
  /* La fiche est exclue ici aussi : elle défile, elle n'a pas de hauteur. Sans
     le `:not`, un écran bas la replafonnait à 100svh et coupait le document. */
  .scene:not(.scene--fiche):not(.scene--accueil) {
    height: 100svh; padding-top: var(--sp-12); padding-bottom: var(--sp-16);
  }
  .corps { gap: var(--sp-8); }
  .n1 { font-size: clamp(2.4rem, 5vh + 1rem, 3.4rem); }
  .titre-jeu { font-size: clamp(2.8rem, 8vh, 4.2rem); }
  .rangee-jeu { padding-top: var(--sp-8); }
  .actions { padding-top: var(--sp-12); }
  .bouton { padding: var(--sp-12) var(--sp-16); }
}

/* ─── Le duel avec le rival, en bas de fiche ──────────────────────────────
   Trois colonnes fixes : toi, ce qu'on compare, lui. La colonne du milieu est
   la plus large parce qu'elle porte le mot ; les deux chiffres se lisent en
   miroir de part et d'autre, ce qui rend l'écart visible sans le calculer. */

.duel { display: grid; gap: var(--sp-2); }
.duel__tete {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: baseline; gap: var(--sp-12);
  padding-bottom: var(--sp-12);
  border-bottom: 1px solid var(--trait);
}
.duel__nom {
  font-family: var(--display); font-weight: 700;
  font-size: var(--t-base); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--craie);
}
.duel__tete .duel__nom:last-child { text-align: right; }
.duel__vs {
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--craie-bas);
}
.duel__ligne {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: baseline; gap: var(--sp-12);
  padding: var(--sp-8) 0;
}
.duel__toi, .duel__lui {
  font-family: var(--display); font-weight: 700;
  font-size: 1.35rem; color: var(--craie-bas);
  font-variant-numeric: tabular-nums;
}
.duel__lui { text-align: right; }
/* Celui qui mène prend l'accent. Aucun des deux ne prend le vert : ce n'est
   pas un gain, c'est une comparaison — et l'un des deux est toujours devant. */
.duel--devant { color: var(--accent); }
.duel__quoi {
  font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--craie-bas); text-align: center;
}
.duel__verdict {
  margin-top: var(--sp-12); padding-top: var(--sp-12);
  border-top: 1px solid var(--trait);
  font-size: var(--t-petit); line-height: 1.55; color: var(--craie-mi);
}

/* ─── Les couleurs du club habillent le fond ──────────────────────────────
   Une équipe ne se reconnaît pas à une teinte mais à une PAIRE. La première
   porte l'accent — boutons, libellés, chiffres. La seconde éclaire le fond
   depuis le côté, ce qui donne à chaque saison son atmosphère propre : deux
   lumières qui ne viennent pas du même endroit, comme dans une salle réelle.

   S'applique dès qu'on porte un maillot, à la fac comme dans la Ligue, et
   cède la place aux ambiances d'événement en février, avril et juin. */

.terrain--club {
  background:
    radial-gradient(72% 46% at 16% -6%,
      color-mix(in oklch, var(--accent) 62%, transparent) 0%, transparent 64%),
    radial-gradient(58% 40% at 92% 6%,
      color-mix(in oklch, var(--accent-2) 26%, transparent) 0%, transparent 62%),
    var(--nuit);
}
/* Au sommet de la carrière, la salle s'allume franchement — mais toujours aux
   couleurs du club, pas à celles de la ligue. */
.terrain--club.terrain--legende {
  background:
    radial-gradient(78% 52% at 18% -10%,
      color-mix(in oklch, var(--accent) 78%, transparent) 0%, transparent 68%),
    radial-gradient(62% 44% at 90% 2%,
      color-mix(in oklch, var(--accent-2) 40%, transparent) 0%, transparent 64%),
    var(--nuit);
}

/* ═══ LA LECTURE ════════════════════════════════════════════════════════════
   Ce qui se lit vraiment : la situation, la chute, le récit. Le reste de
   l'interface annonce ; ces trois-là demandent qu'on s'arrête.

   Quatre réglages, tous tirés de ce qu'on sait de la lecture sur fond sombre :

   1. INTERLIGNE À 1,58 et non 1,45. La recommandation générale est d'environ
      150 % du corps, et le fond sombre en demande davantage : un texte clair
      paraît plus léger qu'il ne l'est et se resserre à l'œil.

   2. UN SOUPÇON D'INTERLETTRAGE, +1,2 %. Sur fond sombre la halation fait
      déborder chaque lettre sur sa voisine ; écarter très légèrement rend les
      mots à nouveau distincts. Invisible consciemment, mesurable à la lecture.

   3. UN BLANC ADOUCI. `--craie-lu` au lieu de `--craie` : on garde un contraste
      très élevé sans le blanc quasi pur qui fatigue.

   4. `text-wrap: pretty` — plus de mot seul en dernière ligne. Un orphelin
      casse la chute d'un événement, et nos chutes sont écrites pour tomber
      d'un bloc.

   La largeur, elle, est déjà bonne : la colonne donne ~43 signes par ligne à
   la taille des énoncés, dans la fourchette de 30 à 50 recommandée en portrait
   sur téléphone. */

.situation, .issue, .recit, .chapo, .texte,
.moment__recit, .playoffs__recit, .duel__verdict, .carte__phrase {
  color: var(--craie-lu);
  letter-spacing: 0.012em;
  text-wrap: pretty;
}
.situation, .issue { line-height: 1.58; color: var(--craie-lu); }
.recit, .chapo { line-height: 1.6; }
.texte, .moment__recit, .playoffs__recit, .duel__verdict { line-height: 1.6; }

/* Les titres et les chiffres gardent le blanc franc : trois mots ne fatiguent
   personne, et c'est le contraste qui les fait ressortir. */
.titre-jeu, .titre-ecran, .n1, .n3, .carte__nom, .section__titre { color: var(--craie); }

/* Les libellés d'option se lisent aussi, mais courts (34 signes en médiane) :
   ils gardent leur interligne serré et gagnent seulement le confort de tonalité. */
.option { color: var(--craie-lu); text-wrap: pretty; }
.option:hover { color: var(--craie); }

/* Une signature hors d'atteinte reste visible, barrée : elle dit ce qu'on
   aurait pu devenir, ce qui donne rétroactivement du sens aux quatre années de
   construction. La cacher reviendrait à ne jamais montrer le prix du choix. */
.offre--fermee {
  opacity: 0.42;
  cursor: not-allowed;
  border-style: dashed;
}
.offre--fermee:hover { background: none; border-color: var(--trait); }

/* ═══ L'ÉTÉ — LA SÉLECTION ══════════════════════════════════════════════════
   La seule ambiance CLAIRE du jeu, et c'est tout l'argument.

   POURQUOI ELLE INVERSE TOUT. Le basket de club se joue le soir, en salle, sous
   des projecteurs — c'est la direction artistique entière du jeu, et elle est
   dérivée du contexte réel. Le basket international se joue l'été, en plein
   jour, dans des salles ouvertes et devant un public qui n'est pas celui de ta
   ville. Basculer en clair dit tout ça sans une ligne de texte, et le retour
   au noir la saison suivante se sent physiquement.

   CE QUE JE N'AI PAS FAIT, ET POURQUOI. Un dégradé aux cinq couleurs
   olympiques serait un arc-en-ciel — l'empreinte de design générée la plus
   reconnaissable après le violet-bleu, et notre feuille l'interdit. Les cinq
   couleurs sont donc là, mais en TRAITS FINS d'un pixel, jamais en lavis :
   elles marquent, elles ne colorent pas. C'est aussi ce que fait la vraie
   signalétique de ces compétitions, qui est blanche et sobre.

   ELLE DURE UN ÉCRAN, DEUX AU MAXIMUM. Une ambiance qui inverse le contraste
   ne peut pas s'installer : au-delà, ce n'est plus une respiration, c'est un
   autre jeu. */

.terrain--nation {
  /* Les neutres s'inversent. Aucun blanc pur : le papier n'est pas blanc, et
     le noir pur sur fond clair fatigue autant que l'inverse. */
  --nuit:       oklch(0.955 0.004 85);
  --beton:      oklch(0.915 0.006 85);
  --beton-haut: oklch(0.875 0.008 85);
  --trait:      oklch(0.80 0.010 85);
  --craie:      oklch(0.22 0.014 60);
  --craie-lu:   oklch(0.29 0.012 60);
  --craie-mi:   oklch(0.40 0.012 60);
  /* Assombri par rapport au mode nuit : à 0,55 il tombait à 3,3:1 sur fond
     clair, juste sous le seuil des petits textes. */
  --craie-bas:  oklch(0.47 0.011 60);

  /* L'accent passe au bleu profond de la signalétique internationale : c'est
     la seule des cinq couleurs qui tienne un texte long sur fond clair. */
  --accent:       oklch(0.46 0.145 250);
  --accent-2:     oklch(0.46 0.145 250);
  --accent-sourd: oklch(0.62 0.090 250);

  /* Le vert et le rouge se foncent : ceux du mode nuit disparaîtraient. */
  --gain:  oklch(0.48 0.135 150);
  --perte: oklch(0.48 0.155 27);
  --monnaie: oklch(0.52 0.095 84);

  background:
    radial-gradient(85% 55% at 50% -15%, oklch(1 0 0 / 0.85), transparent 70%),
    oklch(0.955 0.004 85);
  color: var(--craie);
}

/* Le grain du béton n'a rien à faire sur du blanc : il salit au lieu de
   texturer. */
.terrain--nation::after { opacity: 0.02; }

/* Les cinq couleurs, en cinq traits d'un pixel sous la crête. Elles se lisent
   comme une signature, pas comme un fond. */
.terrain--nation .crete {
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(to right,
    oklch(0.52 0.150 250) 0 20%,
    oklch(0.30 0.010 80) 20% 40%,
    oklch(0.62 0.165 30) 40% 60%,
    oklch(0.58 0.130 150) 60% 80%,
    oklch(0.72 0.155 85) 80% 100%) 1;
  padding-bottom: var(--sp-12);
}
