/* =============================================================================
   Destiny Five - styles.css
   Design sombre, esthetique esport sobre. Accent orange/ambre. Mobile-first.
   Typographie systeme (aucune police externe). 100% autonome.
   ============================================================================= */

:root {
  --bg: #0d0d0f;
  --bg-2: #16161a;
  --bg-3: #1e1e24;
  --bg-card: #1a1a20;
  --line: #2a2a32;
  --txt: #ececf0;
  --txt-dim: #9a9aa6;
  --txt-faint: #6b6b76;
  --accent: #ff8a1e;
  --accent-2: #ffb35c;
  --accent-dim: #7a4410;
  --good: #4ec17a;
  --bad: #e5564b;
  --info: #4aa3e0;
  /* Roles ajoutes le 2026-07-31 en preparation des themes : ils portaient jusque-la
     une couleur ecrite en dur dans la regle. Valeurs identiques au chiffre pres. */
  --btn-txt: #201200;                 /* texte du bouton principal, sur le degrade d'accent */
  --txt-note: #767676;                /* repere de version en pied d'accueil (style en ligne) */
  --field-bg: var(--bg-2);            /* fond d'un champ de saisie */
  --field-line: var(--line);          /* son lisere */
  /* Ecran compact du calendrier (2026-07-31) : quatre surfaces d'etat et le rail
     neutre d'un interrupteur. Roles, pas couleurs — un theme les redefinit d'un bloc. */
  --c2-ok-bg: rgba(78, 193, 122, .12);   /* encadre d'etat FAVORABLE */
  --c2-ok-line: rgba(78, 193, 122, .32);
  --c2-ko-bg: rgba(229, 86, 75, .12);    /* encadre d'etat DEFAVORABLE */
  --c2-ko-line: rgba(229, 86, 75, .32);
  --c2-ac-bg: rgba(227, 154, 31, .14);   /* pastille d'etat A LA LIMITE (quota atteint) */
  --c2-rail: #3a3a44;                    /* rail d'interrupteur / point de refus disponible */
  --c2-knob: #ffffff;                    /* pastille mobile de l'interrupteur */
  /* LES QUATRE COUCHES DU PLAN DU MODE « LE MATCH »   (2026-08-08)
     ⚠️ ELLES SONT ICI, ET PAS DANS LE BLOC DU MODE, POUR UNE RAISON PRECISE :
     le bloc du mode ne doit porter AUCUN hexadecimal (le controle lit la feuille
     du marqueur « ECRAN PROGRESSION » jusqu'a la fin). Une couleur est un JETON,
     et un jeton vit dans le socle.
     Les plans vectorises de site/plans/ ne portent aucune couleur : c'est
     js/match-cartes.js qui relie chaque couche a l'un de ces quatre jetons, en
     attribut de presentation `fill="var(--mt-plan-*)"` — une propriete
     personnalisee traverse le `<use>`, contrairement a un selecteur de classe.
     ⚠️ LE PLAN RESTE SOMBRE QUEL QUE SOIT LE THEME, comme la vitrine de « Mon
     arme » : des zones claires derriere des points clairs ne se liraient pas.
     Un theme qui voudrait le repeindre n'a que ces quatre lignes a redefinir. */
  --mt-plan-fond: #0A0D16;               /* le cadre du plateau, sous la carte */
  --mt-plan-sol: #38435F;                /* la surface praticable */
  --mt-plan-detail: #1F2740;             /* batiments, caisses, obstacles */
  --mt-plan-bas: #46375C;                /* etage INFERIEUR (Nuke) */
  --radius: 14px;
  --maxw: 640px;
}

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

html, body {
  background: var(--bg);
  color: var(--txt);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
}
body { padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom); }

#app { max-width: var(--maxw); margin: 0 auto; min-height: 100vh; position: relative; }

/* ---------------------------------------------------------------- Screens */
.screen { display: none; padding: 18px 16px 40px; animation: fade .25s ease; }
.screen.active { display: block; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---- FONDU CROISE ENTRE ECRANS                                (2026-08-23) ----
   L'ecran qui PART s'estompe pendant que le suivant ARRIVE. Deux constats ont
   dicte la technique, et pas un choix esthetique :
     1. UN ECRAN NON ACTIF EST MASQUE PAR `display:none` (ligne 72, et
        `#screen-home` ligne 101). Deux ecrans ne peuvent donc pas etre visibles
        ensemble sans que l'un SORTE DU FLUX : dans le flux, ils s'empileraient
        verticalement et toute la page sauterait.
     2. LE LAYOUT DES DOUZE ECRANS NE DOIT PAS BOUGER. Seul le SORTANT quitte le
        flux, en absolu dans `#app` (qui est deja `position:relative`, ligne 69),
        et seulement pendant son estompe. L'ecran ENTRANT ne change pas d'un
        pixel : il reste dans le flux et garde le fondu d'entree d'origine.
   ⚠️ `max-height` ET `overflow` NE SONT PAS COSMETIQUES. Un element absolu compte
   dans la zone de defilement de son conteneur : sans eux, quitter la Progression
   (2087 px mesures) pour l'accueil rendrait la page defilante pendant toute
   l'estompe. Borne a une hauteur de fenetre, le fantome ne peut plus rien
   allonger — et il n'a rien de plus a montrer, la page etant remise en haut.
   ⚠️ `pointer-events: none` EST LA REGLE QUI PROTEGE LE PREMIER GESTE : sans elle,
   le fantome intercepte le tap destine au nouvel ecran pendant l'estompe.
   ⚠️ LA DUREE VIT ICI ET NULLE PART AILLEURS. `js/ui.js` RELIT `--fondu-sortie`
   pour savoir quand retirer la classe ; l'ecrire une seconde fois dans le script
   ferait diverger les deux en silence. La mettre a zero desactive proprement le
   fondu (le script ne pose alors aucun fantome). */
.screen { --fondu-sortie: 150ms; }
.screen.sortante {
  display: block;
  position: absolute; top: 0; left: 0; right: 0;
  max-height: 100vh; overflow: hidden;
  pointer-events: none;
  animation: fade-sortie var(--fondu-sortie) ease forwards;
}
/* ⚠️ L'ACCUEIL EST EN `display:flex` ET SON SELECTEUR EST UN ID (ligne 101) : sans
   cette ligne de meme portee, il resterait `display:none` en partant, donc AUCUNE
   sortie depuis l'ecran le plus visite du jeu. */
#screen-home.sortante { display: flex; }
@keyframes fade-sortie { from { opacity: 1; } to { opacity: 0; } }

/* Mouvement reduit : aucune des deux moities du fondu. Le sortant disparait net
   (js/ui.js ne pose meme pas le fantome), l'entrant arrive a son etat final —
   exactement ce que `#boot`, `.titlecard`, `.gscard` et `.kf-line` font deja. */
@media (prefers-reduced-motion: reduce) {
  .screen { animation: none; }
}

.wrap { max-width: 560px; margin: 0 auto; }
.screen-title { font-size: 1.5rem; margin-bottom: 16px; letter-spacing: .5px; }
.group-title { font-size: .82rem; text-transform: uppercase; letter-spacing: 1.4px; color: var(--accent-2); margin: 22px 0 10px; }

/* ---------------------------------------------------------------- Boutons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; font-weight: 600; cursor: pointer;
  border: 1px solid var(--line); background: var(--bg-3); color: var(--txt);
  padding: 13px 18px; border-radius: 12px; width: 100%;
  transition: transform .08s ease, background .15s ease, border-color .15s ease;
  -webkit-tap-highlight-color: transparent; text-align: center;
}
.btn:active { transform: scale(.98); }
.btn-primary { background: linear-gradient(180deg, var(--accent-2), var(--accent)); color: var(--btn-txt); border-color: transparent; }
.btn-primary:hover { filter: brightness(1.05); }
.btn-ghost { background: transparent; color: var(--txt-dim); }
.btn-ghost:hover { color: var(--txt); border-color: var(--accent-dim); }
.btn.big { padding: 16px; font-size: 1.05rem; }
.btn.small { padding: 9px 12px; font-size: .85rem; width: auto; }
.btn.tiny { padding: 6px 11px; font-size: .78rem; width: auto; border-radius: 9px; }
.btn + .btn { margin-top: 10px; }
.hidden { display: none !important; }

/* ---------------------------------------------------------------- Accueil */
#screen-home { display: none; min-height: 100vh; flex-direction: column; justify-content: center; }
#screen-home.active { display: flex; }
.home-hero { text-align: center; margin: auto 0; }
.logo { font-size: 2.7rem; font-weight: 800; letter-spacing: 3px; line-height: 1; }
.logo span { color: var(--accent); }
.tagline { color: var(--txt-dim); max-width: 420px; margin: 16px auto 30px; font-size: 1rem; }
.home-actions { max-width: 320px; margin: 0 auto; }
.save-info { color: var(--txt-faint); font-size: .85rem; margin-top: 14px; }
.footer-note { color: var(--txt-faint); font-size: .72rem; text-align: center; margin-top: 30px; padding: 0 10px; }

/* ---------------------------------------------------------------- Création */
.field { margin-bottom: 8px; }
.field label { display: block; font-size: .82rem; color: var(--txt-dim); margin-bottom: 6px; }
input[type=text] {
  width: 100%; font: inherit; padding: 12px 14px; border-radius: 12px;
  background: var(--field-bg); border: 1px solid var(--field-line); color: var(--txt);
}
input[type=text]:focus { outline: none; border-color: var(--accent); }

.cards { display: grid; gap: 10px; }
.card {
  background: var(--bg-card); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 13px 15px; cursor: pointer; transition: border-color .15s, background .15s, transform .08s;
}
.card:active { transform: scale(.99); }
.card:hover { border-color: var(--accent-dim); }
.card.selected { border-color: var(--accent); background: #241a10; }
.card h4 { font-size: 1rem; margin-bottom: 3px; }
.card p { color: var(--txt-dim); font-size: .85rem; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  background: var(--bg-card); border: 1.5px solid var(--line); border-radius: 20px;
  padding: 8px 14px; cursor: pointer; font-size: .9rem; transition: border-color .15s, background .15s;
}
.chip:hover { border-color: var(--accent-dim); }
.chip.selected { border-color: var(--accent); background: #241a10; color: var(--accent-2); }

.create-actions { display: flex; gap: 10px; margin-top: 26px; }
.create-actions .btn { margin-top: 0; }

/* ---------------------------------------------------------------- HUD */
.hud {
  position: sticky; top: 0; z-index: 5; background: rgba(13,13,15,.96);
  backdrop-filter: blur(8px); border-bottom: 1px solid var(--line);
  padding: 12px 16px 10px; margin: -18px -16px 16px;
}
.hud-line1 { display: flex; align-items: center; gap: 10px; }
.hud-name { font-weight: 700; font-size: 1.05rem; }
.hud-age { color: var(--txt-dim); font-size: .85rem; }
.hud-line1 .btn { margin-left: auto; }
.hud-team { color: var(--accent-2); font-size: .85rem; margin: 5px 0 6px; }
/* Conteneurs de l'en-tete introduits par la mise en page « blocs flottants » du
   2026-07-27. Ils sont ici a l'etat NEUTRE, pour que l'en-tete reste lisible si le theme
   clair est retire (chemin de rollback) ; toute leur apparence — pastille, tuiles,
   carte, bandeau de titre — vit dans le bloc `html.theme-clair`, en fin de fichier. */
/* PASTILLE SUR UNE SEULE LIGNE (2026-07-28) : drapeau + pseudo · age · [blason]
   organisation · VRS #rang. `flex-wrap: nowrap` interdit tout repli.
   ORDRE DE CESSION DE LA PLACE, quand la ligne est trop longue :
     1. le NOM D'EQUIPE se tronque en « … » — il absorbe tout le manque de place
        (`flex-shrink` tres eleve sur `.hud-team`, cf. le bloc du theme clair) ;
     2. le PSEUDO n'est abrege qu'en DERNIER RECOURS, une fois le nom d'equipe
        entierement replie : le cas ne se rencontre qu'avec un pseudo proche du
        maximum de 20 caracteres ET une organisation au nom tres long, a 390 px.
   L'AGE et le RANG VRS ne se coupent jamais et restent toujours visibles. */
.hud-pill { display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; min-width: 0; flex: 1 1 auto; }
.hud-pill .hud-name { flex: 0 1 auto; min-width: 3ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hud-pill .hud-age { flex: 0 0 auto; white-space: nowrap; }
.hud-tier { font-size: .68rem; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--accent-2); white-space: nowrap; }
/* `.hud-role` : la sous-ligne « poste · contrat » a ete retiree de l'en-tete le
   2026-07-28 (ces informations sont dans la fiche joueur). La regle est conservee pour
   le seul cas ou un ancien document reintroduirait le conteneur. */
.hud-role { margin: 5px 0 6px; }
.hud-tiles { display: flex; align-items: stretch; gap: 8px; }
.hud-tile { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center; }
/* Etat NEUTRE des deux tuiles introduites / remaniees le 2026-07-27 (chemin de rollback,
   cf. le bloc `html.theme-clair` en fin de fichier, qui porte leur vraie apparence) :
   le Niveau se lit sur une ligne (« ⚡ N ») et l'acces a la fiche est un bouton a plat. */
.hud-tile-niv { flex-direction: row; align-items: center; gap: 5px; }
.hud-tile-fiche { border: 0; background: none; color: var(--accent-2); font: inherit; cursor: pointer; }
.ht-v { font-weight: 700; line-height: 1.1; }
.ht-sub { font-size: .66rem; color: var(--txt-dim); line-height: 1.1; font-variant-numeric: tabular-nums; }
.ht-k { font-size: .6rem; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--txt-faint); line-height: 1.2; }
.hud-eyebrow { font-size: .68rem; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--txt-dim); margin-bottom: 9px; }
/* Bloc classement de l'en-tete : chaque information sur SA PROPRE LIGNE, de la plus
   importante (rang mondial) a la plus discrete (rang regional), l'encadre d'objectif
   fermant le bloc en pleine largeur. Colonne stricte -> aucun chevauchement possible,
   quelle que soit la largeur de l'ecran. */
.hud-vrs { display: flex; flex-direction: column; align-items: stretch; gap: 2px; margin: 0 0 9px; }
.hud-vrs-rang { font-size: .82rem; color: var(--txt); }
.hud-vrs-rang strong { color: var(--accent-2); font-weight: 700; }
/* Ligne de synthese de l'en-tete : note de niveau (+ etoiles) et gains cumules.
   flex-wrap : sur un ecran etroit les deux blocs passent l'un sous l'autre au lieu de
   deborder ; ils restent cote a cote des qu'il y a la place. La Forme et les deux
   statistiques de poste, elles, ne bougent pas d'un pixel. */
.hud-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 5px 14px; margin: 0 0 9px; }
.niveau { display: inline-flex; align-items: baseline; gap: 5px; font-size: .78rem; color: var(--txt-dim); }
.niv-lab { text-transform: uppercase; letter-spacing: .6px; font-size: .66rem; color: var(--txt-faint); }
.niv-note { color: var(--accent-2); font-size: 1rem; font-weight: 700; line-height: 1; }
.niv-sur { font-size: .66rem; color: var(--txt-faint); }
.niv-mot { color: var(--txt-dim); font-size: .74rem; }
.stars { letter-spacing: 1px; line-height: 1; white-space: nowrap; }
.stars .star { color: var(--bg-3); font-size: .8rem; }
.stars .star.on { color: var(--accent); }
.hud-gains { display: inline-flex; align-items: baseline; gap: 5px; font-size: .78rem; }
.hg-lab { text-transform: uppercase; letter-spacing: .6px; font-size: .66rem; color: var(--txt-faint); }
.hg-val { color: var(--good); font-size: .95rem; font-weight: 700; line-height: 1; white-space: nowrap; }
/* Note/etoiles dans la fiche joueur : meme information, un cran plus lisible. */
.niveau.niv-fiche { font-size: .86rem; }
.niveau.niv-fiche .niv-note { font-size: 1.35rem; }
.niveau.niv-fiche .stars .star { font-size: 1rem; }
/* Evolution de la note dans la fiche : une ligne par saison, barre proportionnelle. */
.niv-evo { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.niv-evo .nl { display: flex; align-items: center; gap: 8px; font-size: .8rem; }
.niv-evo .nl-s { color: var(--txt-faint); min-width: 34px; }
.niv-evo .nl-n { color: var(--accent-2); font-weight: 700; min-width: 24px; text-align: right; }
.niv-evo .nl-b { flex: 1 1 40px; min-width: 30px; height: 5px; background: var(--bg-3); border-radius: 3px; overflow: hidden; }
.niv-evo .nl-b i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
.niv-evo .nl-e { flex: 0 0 auto; }
.hud-gauges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.gauge { }
.gauge .g-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .6px; color: var(--txt-faint); display: flex; justify-content: space-between; }
.gauge .g-track { height: 6px; background: var(--bg-3); border-radius: 4px; overflow: hidden; margin-top: 3px; }
.gauge .g-fill { height: 100%; border-radius: 4px; transition: width .4s ease; }
.g-form .g-fill { background: linear-gradient(90deg, var(--info), #7cc6f5); }
.g-rep .g-fill { background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
.g-pop .g-fill { background: linear-gradient(90deg, #b565e0, #d79bf0); }

/* ---------------------------------------------------------------- Season body */
.season-body { animation: fade .2s ease; }
.phase-tag { font-size: .72rem; text-transform: uppercase; letter-spacing: 1.5px; color: var(--accent); margin-bottom: 8px; }
.narr {
  background: var(--bg-2); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: 10px; padding: 15px 16px; font-size: 1.02rem; margin-bottom: 16px;
}
.narr.soft { border-left-color: var(--info); }
.narr.good { border-left-color: var(--good); }
.narr.bad { border-left-color: var(--bad); }
.season-h { font-size: 1.25rem; margin-bottom: 4px; }
.season-sub { color: var(--txt-dim); font-size: .85rem; margin-bottom: 16px; }

.choice-btn {
  display: block; width: 100%; text-align: left; background: var(--bg-card);
  border: 1.5px solid var(--line); border-radius: 12px; padding: 14px 16px; margin-bottom: 10px;
  color: var(--txt); font: inherit; cursor: pointer; transition: border-color .15s, background .15s, transform .08s;
}
.choice-btn:hover { border-color: var(--accent); }
.choice-btn:active { transform: scale(.99); }
.choice-btn .c-label { font-weight: 600; }
.choice-btn .c-hint { display: block; color: var(--txt-faint); font-size: .78rem; margin-top: 3px; }

/* offers */
.offer { background: var(--bg-card); border: 1.5px solid var(--line); border-radius: 12px; padding: 14px; margin-bottom: 11px; }
.offer h4 { font-size: 1.05rem; }
.offer .tier-badge { font-size: .7rem; padding: 2px 8px; border-radius: 20px; background: var(--bg-3); color: var(--accent-2); margin-left: 8px; }
.offer p { color: var(--txt-dim); font-size: .85rem; margin: 6px 0 10px; }
.offer .warn { color: var(--accent); }

/* effect chips shown after a choice */
.fx { display: inline-block; font-size: .78rem; padding: 2px 8px; border-radius: 6px; margin: 3px 4px 0 0; background: var(--bg-3); }
.fx.up { color: var(--good); } .fx.down { color: var(--bad); }

/* tournaments */
.trow { display: flex; align-items: center; gap: 10px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.trow:last-child { border-bottom: none; }
.trow .t-main { flex: 1; }
.trow .t-name { font-weight: 600; }
.trow .t-city { color: var(--txt-faint); font-size: .78rem; }
.trow .t-res { font-size: .85rem; text-align: right; }
.res-titre { color: var(--accent); font-weight: 700; }
.res-finale { color: var(--accent-2); }
.res-demi { color: var(--info); }
.res-quart { color: var(--txt); }
.res-groupes, .res-qualif { color: var(--txt-dim); }
.badge-mvp { color: var(--accent); font-size: .72rem; font-weight: 800; }
.badge-evp { color: var(--accent-2); font-size: .68rem; font-weight: 700; opacity: .9; }
/* rating par tournoi (colonne du tableau de resultats) */
.res-rating { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.res-rating.rt-hi { color: var(--good); }
.res-rating.rt-mid { color: var(--txt); }
.res-rating.rt-lo { color: var(--bad); }
/* Mise en contexte du rating : le chiffre affiche reste le rating BRUT, cette ligne
   indique ou il se situe par rapport a la moyenne du poste (data/roles.json). */
.perf-ctx { margin: -2px 0 8px; text-align: center; font-size: .84rem; color: var(--txt-dim); }
.perf-inline { font-size: .82rem; color: var(--txt-dim); }
.perf-ctx.perf-forte, .perf-inline.perf-forte { color: var(--good); }
.perf-ctx.perf-faible, .perf-inline.perf-faible { color: var(--accent-2); }
.perf-ctx.perf-insuffisante, .perf-inline.perf-insuffisante { color: var(--bad); }
/* recap distinctions de l'annee (bilan) */
.distinc-annee { margin: 8px 0 2px; font-size: .92rem; }
.distinc-detail { margin: 0 0 4px; font-size: .8rem; color: var(--txt-dim); }
/* section MVP / EVP (fiche, fin de carriere, palmares) */
.mvp-summary { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.mvp-pill { padding: 5px 12px; border-radius: 20px; font-size: .82rem; border: 1px solid var(--line); background: var(--bg-3); }
.mvp-pill.mvp { border-color: var(--accent-dim); color: var(--accent-2); }
.mvp-pill.evp { color: var(--txt-dim); }
.mvp-breakdown { margin: 4px 0 8px; }

/* bilan / stats */
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 12px 0; }
.stat-box { background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.stat-box .s-name { font-size: .72rem; color: var(--txt-dim); text-transform: uppercase; letter-spacing: .5px; }
.stat-box .s-val { font-size: 1.35rem; font-weight: 700; }
.stat-bar { height: 5px; background: var(--bg-3); border-radius: 3px; margin-top: 6px; overflow: hidden; }
.stat-bar > div { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); }

.big-metric { text-align: center; padding: 14px; background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; margin-bottom: 14px; }
.big-metric .m-val { font-size: 2.4rem; font-weight: 800; color: var(--accent); line-height: 1; }
.big-metric .m-lab { color: var(--txt-dim); font-size: .8rem; margin-top: 4px; text-transform: uppercase; letter-spacing: 1px; }

.award-list { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.award { background: #241a10; border: 1px solid var(--accent-dim); color: var(--accent-2); padding: 6px 12px; border-radius: 20px; font-size: .82rem; font-weight: 600; }

/* BADGES DE DISTINCTION — deux portees, deux allures.
   Une pastille de SAISON (bilan de l'annee) garde l'ambre plein du reste du jeu :
   c'est un resultat chaud, de l'annee qui vient de se jouer.
   Une pastille de CARRIERE (fiche joueur, ecran de fin) est volontairement plus
   sobre — fond froid, contour discret, angles moins ronds — pour qu'on ne puisse
   pas la confondre d'un coup d'oeil avec un statut de la saison en cours. Le
   libelle le dit deja (« A ete #1 mondial »), la forme le confirme.
   Aucun nombre, aucune regle : uniquement de l'apparence. */
.award.carriere { background: rgba(255, 255, 255, .035); border-color: var(--line);
  color: var(--txt-dim); border-radius: 9px; font-weight: 600; }
.badge-note { font-size: .74rem; line-height: 1.45; margin: -2px 0 4px; max-width: 62ch; }

.section-label { font-size: .78rem; text-transform: uppercase; letter-spacing: 1.2px; color: var(--txt-faint); margin: 20px 0 8px; }
.list-line { display: flex; justify-content: space-between; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); font-size: .9rem; }
.list-line:last-child { border-bottom: none; }
.list-line .l-r { color: var(--txt-dim); text-align: right; }

/* fin de carriere */
.legend-title { text-align: center; }
.legend-title .l-honor { font-size: 1.9rem; font-weight: 800; color: var(--accent); margin: 6px 0; }
.legend-title .l-style { font-size: .82rem; color: var(--txt-faint); text-transform: uppercase; letter-spacing: .5px; margin: -2px 0 4px; }
.legend-title .l-sub { color: var(--txt-dim); }
.l-manque { text-align: center; color: var(--accent-2); font-size: .86rem; margin: 2px 0 6px; padding: 0 10px; }
.score-pctl { margin-top: 8px; }
.leg-palier { color: var(--accent); font-weight: 700; }
.legend-reason { text-align: center; font-style: italic; color: var(--txt-dim); margin: 14px 0 20px; padding: 0 8px; }
.copybox { width: 100%; background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; color: var(--txt-dim); font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .8rem; padding: 12px; white-space: pre-wrap; margin-top: 8px; }
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); background: var(--accent); color: #201200; padding: 10px 18px; border-radius: 20px; font-weight: 600; font-size: .88rem; z-index: 50; box-shadow: 0 6px 20px rgba(0,0,0,.4); }

.spacer { height: 8px; }
.center { text-align: center; }
.dim { color: var(--txt-dim); }
.mt { margin-top: 16px; }

/* ---------------------------------------------------------------- v3 : offres chiffrees */
.offer-rel { font-size: .78rem; color: var(--accent-2); margin: 2px 0 8px; }
.offer-grid { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 4px 0 10px; }
.or-k { color: var(--txt-faint); font-size: .82rem; }
.or-v { font-size: .88rem; text-align: right; }
.offer-arg { color: var(--txt-dim); font-size: .84rem; font-style: italic; margin-bottom: 12px; }
.offer h4 .tier-badge { text-transform: none; }
.warn { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------- v3 : tableau resultats */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 6px 0; }
.res-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.res-table th { text-align: left; color: var(--txt-faint); font-weight: 600; font-size: .72rem; text-transform: uppercase; letter-spacing: .5px; padding: 6px 8px; border-bottom: 1px solid var(--line); }
.res-table td { padding: 8px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.res-table td .t-city { color: var(--txt-faint); font-size: .78rem; }
.res-table tr:last-child td { border-bottom: none; }

/* Sous 600 px (telephone) : le tableau a 5 colonnes devient UNE LIGNE PAR TOURNOI.
   1re ligne = nom du tournoi + ville ; 2e ligne = les valeurs en plus petit, precedees
   de leur intitule (l'en-tete du tableau est masque). Aucun defilement horizontal.
   Au-dela de 600 px, rien ne change : la disposition en tableau est conservee. */
@media (max-width: 599.98px) {
  .table-scroll { overflow-x: visible; }
  .res-table, .res-table tbody, .res-table tr { display: block; width: 100%; }
  .res-table thead { display: none; }
  .res-table tr { padding: 9px 0; border-bottom: 1px solid var(--line); }
  .res-table tr:last-child { border-bottom: none; }
  .res-table td { display: inline-block; padding: 0; border-bottom: none; vertical-align: baseline; }
  /* 1re ligne : le nom occupe toute la largeur, jamais tronque, jamais coupe lettre a lettre */
  .res-table td.res-nom { display: block; font-weight: 600; line-height: 1.25; margin-bottom: 3px; overflow-wrap: break-word; }
  .res-table td.res-nom .t-city { white-space: nowrap; }
  /* 2e ligne : valeurs en plus petit, separees par des espaces, elles seules peuvent passer a la ligne */
  .res-table td[data-lab] { font-size: .74rem; margin-right: .6rem; }
  .res-table td[data-lab]::before {
    content: attr(data-lab) " "; color: var(--txt-faint);
    font-size: .62rem; text-transform: uppercase; letter-spacing: .3px; font-weight: 600;
  }
  /* la place se lit d'elle-meme ("Quart de finale", "Vainqueur") : pas d'intitule,
     on gagne la place necessaire pour tenir sur une seule seconde ligne */
  .res-table td.res-place::before { content: none; }
  .res-table td.res-vide { display: none; }        /* pas de gains : on n'affiche pas un tiret seul */
  .res-table td.res-place { white-space: normal; }
  .res-table .res-trophy svg, .res-table .res-badge svg { vertical-align: -3px; }
}

/* ---------------------------------------------------------------- v3 : onglets fiche */
.tabs { display: flex; gap: 8px; margin-bottom: 16px; }
.tab { flex: 1; background: var(--bg-3); border: 1px solid var(--line); color: var(--txt-dim); border-radius: 10px; padding: 10px; font: inherit; font-weight: 600; cursor: pointer; }
.tab.on { background: #241a10; border-color: var(--accent); color: var(--accent-2); }

/* ---------------------------------------------------------------- v3 : historique relations */
.histo-row { background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; padding: 11px 13px; margin-bottom: 9px; }
.histo-top { display: flex; justify-content: space-between; align-items: baseline; }
.histo-org { font-weight: 700; }
.histo-tier { font-size: .72rem; color: var(--accent-2); }
.histo-meta { color: var(--txt-dim); font-size: .82rem; margin: 3px 0 6px; }
.histo-rel { font-size: .82rem; font-weight: 600; }
.rel-good { color: var(--good); }
.rel-bad { color: var(--bad); }
.rel-neutral { color: var(--txt-dim); }

/* ============================================================ v4 : emblemes & trophees */
.emb, .trophy, .fbadge { display: inline-block; vertical-align: middle; }
.emb { filter: drop-shadow(0 1px 2px rgba(0,0,0,.45)); }

/* HUD : embleme a cote du nom d'equipe.
   `.hud-team` ne porte plus QUE l'identite (embleme + nom + tier/poste/contrat) : les lignes
   de classement et l'encadre d'objectif vivent dans `.hud-vrs` (bloc plus bas), sinon ils
   redeviendraient des colonnes de cette ligne flex et se tasseraient sur telephone. */
.hud-team { display: flex; align-items: center; gap: 8px; }
.hud-emb { display: inline-flex; flex: 0 0 auto; }
/* min-width:0 : sans lui, un nom d'organisation long empeche l'element flex de retrecir et
   pousse l'en-tete au-dela de la largeur de l'ecran. */
.hud-team-main { display: flex; flex-direction: column; min-width: 0; }
.hud-team-nom { font-weight: 700; font-size: .95rem; line-height: 1.2; color: var(--accent-2); overflow-wrap: anywhere; }
.hud-team-sub { font-size: .76rem; line-height: 1.3; color: var(--txt-dim); overflow-wrap: anywhere; }

/* ---- Recapitulatif de palmares : ligne SECONDAIRE de l'en-tete de saison (2026-07-26)
   Compteurs « icone + nombre + LIBELLE COURT » a la place de l'ecart de points et du
   rang regional, tous deux restes dans la fiche joueur. Sept compteurs depuis la refonte
   du 2026-07-27 : Major, Grand Slam, MVP, EVP (ligne 1), puis titres, Top 20, Awards
   (ligne 2) — le compteur « moments » ne figure plus dans l'en-tete (il reste dans la
   fiche joueur) et la pastille « #1 » a ete supprimee. Le LIBELLE ECRIT a ete ajoute le 2026-07-26 : les icones seules ne
   disaient pas ce qu'elles comptaient et plusieurs se ressemblaient en petit. C'est
   donc le texte qui porte le sens, l'icone n'est plus qu'un reperage forme/couleur.
   Contraintes tenues ici :
     - flex-wrap : etiquetes, les compteurs ne tiennent PLUS sur une seule ligne a
       390 px ; ils se repartissent proprement sur DEUX lignes, sans debordement ni
       troncature. `flex: 0 0 auto` interdit tout ecrasement d'un compteur ;
     - `white-space: nowrap` sur le compteur : il ne se coupe jamais en deux au milieu
       (« 2 Grand » sur une ligne, « Slams » sur la suivante). Le plus long compteur
       possible (« 999 Grand Slams ») mesure ~135 px, tres loin de la largeur
       disponible : un compteur seul ne peut donc pas deborder ;
     - tabular-nums : tous les chiffres ont la meme largeur, la ligne ne « saute » donc
       pas quand un compteur passe de 9 a 10 ;
     - les zeros sont estompes, jamais masques : la ligne garde la meme hauteur et la
       meme position du premier au dernier jour de la carriere ;
     - gap horizontal genereux (14 px) : il joue le role du point median entre deux
       compteurs sans risquer un separateur orphelin en fin de ligne apres un repli. */
.hud-palm { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin-top: 4px; }
.hp-item { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; line-height: 1.15; white-space: nowrap; }
.hp-item.zero { opacity: .45; }
.hp-ic { display: inline-flex; flex: 0 0 auto; }
.hp-ic .trophy { display: block; }
.hp-n { font-size: .82rem; font-weight: 700; color: var(--txt); font-variant-numeric: tabular-nums; }
.hp-lab { font-size: .76rem; font-weight: 600; color: var(--txt-dim); letter-spacing: .1px; }
.hp-item.zero .hp-n { color: var(--txt-dim); }
/* « × » du compteur Top 20 (« 3× Top 20 ») : il appartient au NOMBRE, pas au libelle.
   La marge negative annule le `gap` de 4 px du compteur pour le coller au chiffre, sans
   toucher a l'espace qui le separe du libelle. Il est purement decoratif (aria-hidden) :
   le libelle accessible du compteur reste la phrase complete portee par `aria-label`.
   (La pastille doree « #1 » qui doublait ce compteur a ete supprimee le 2026-07-27 : le
   Top 20 compte deja toutes les saisons classees, n°1 compris.) */
/* Saut de ligne DUR de la vitrine (2026-07-27) : element de largeur pleine et de hauteur
   nulle, qui force les compteurs suivants sur une nouvelle ligne d'un conteneur en
   flex-wrap. Il garantit le decoupage voulu — Major / Grand Slam / MVP / EVP en haut,
   titres / Top 20 / Awards en bas — a toute largeur et quelle que soit la taille des
   nombres, la ou le repli naturel changeait de decoupe au premier titre gagne.
   Hauteur nulle : il n'ajoute aucune hauteur, seul le `row-gap` de `.hud-palm` separe
   les deux lignes. */
.hp-br { flex: 0 0 100%; height: 0; }
.hp-x { font-size: .78rem; font-weight: 700; color: var(--txt-dim); margin-left: -4px; }
.hp-item.zero .hp-x { color: var(--txt-dim); }
/* CARTE DE LA FICHE JOUEUR — meme COMPOSANT que la carte du theme clair (surface
   arrondie, ombree, sans bordure dure) mais posee sur la surface de la fiche, qui est
   encore l'ecran SOMBRE d'origine : une carte blanche y jurerait et reviendrait a
   convertir la fiche a moitie, ce que cette tache ne fait pas. Elle reprend donc le
   rayon du theme (`--ds-radius-card`) et son elevation, en surface `--bg-card`. Si la
   fiche passe un jour au theme clair, la regle jumelle plus bas (`html.theme-clair
   .fiche-card`) lui rend la carte blanche sans rien changer ici ni dans le JS. */
.fiche-card {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--ds-radius-card, var(--radius));
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35), 0 10px 22px rgba(0, 0, 0, .22);
  padding: 15px 15px 6px; margin: 20px 0 8px;
}
html.theme-clair .fiche-card {
  background: var(--ds-card); border: 0;
  box-shadow: var(--ds-shadow);
}
/* Meme recapitulatif dans la fiche joueur, en plus grand : memes valeurs, meme source. */
.fiche-palm { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; margin: 2px 0 9px; }
.fiche-palm .hp-n { font-size: .98rem; }
.fiche-palm .hp-lab { font-size: .88rem; }
.fiche-palm .hp-x { font-size: .92rem; }

/* Accueil : embleme a cote de Continuer */
.save-info { display: flex; align-items: center; justify-content: center; gap: 8px; }
.home-emb { display: inline-flex; }

/* Offres : embleme en tete de carte */
.offer-head { display: flex; align-items: center; gap: 11px; margin-bottom: 4px; }
.offer-head h4 { flex: 1; }
.offer-emb { flex: 0 0 auto; }

/* Tableau resultats : badge de famille + trophee sur les lignes gagnees */
.res-badge { display: inline-flex; vertical-align: middle; margin-right: 6px; }
.res-trophy { display: inline-flex; vertical-align: middle; margin-right: 5px; }
.res-trophy .trophy { filter: drop-shadow(0 1px 1px rgba(0,0,0,.5)); }

/* ---------------------------------------------------------- CARTE DE TITRE
   REAGENCEE le 2026-07-26. Avant : trophee de 120 px (donc 144 px de haut) a gauche,
   texte a droite, 16 px de marge interieure -> la carte faisait ~176 px de haut alors que
   son texte n'en occupait qu'une centaine, et le trophee nageait dans le vide pendant que
   le nom du tournoi se tassait sur 220 px de large. Une saison a trois titres devenait un
   long defile de blocs.
   Ce qui change, et RIEN d'autre (aucun trophee n'est redessine, aucun texte retire) :
     - trophee ramene a 84 px pour un sacre majeur (Major, Grand Slam) et 60 px pour un
       titre ordinaire : c'est la HIERARCHIE qui reste, portee par la taille, la bordure
       doree et l'intitule, plus par la hauteur du bloc ;
     - `line-height: 0` sur la colonne du trophee : un <svg> est en ligne, il tramait un
       creux de descendante de quelques pixels sous le dessin ;
     - marges interieures et interlignes resserres -> le texte recupere ~60 px de largeur,
       donc moins de retours a la ligne, donc une carte plus courte encore ;
     - la colonne du trophee est dimensionnee a la largeur du dessin (flex-basis) et le
       texte prend tout le reste : plus de zone vide reservee a cote du trophee. */
.titlecard {
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(180deg, #1c1a15, var(--bg-2));
  border: 1px solid var(--accent-dim); border-radius: 13px;
  padding: 11px 13px; margin-bottom: 10px; animation: tcfade .35s ease;
}
.titlecard.major { border-color: #f2c14e; box-shadow: 0 0 0 1px rgba(242,193,78,.25), 0 8px 26px rgba(0,0,0,.35); background: linear-gradient(180deg, #241f12, #16130c); padding: 13px 14px; gap: 14px; }
.titlecard .tc-trophy { flex: 0 0 auto; line-height: 0; }
.titlecard .tc-trophy svg { display: block; }
.titlecard .tc-body { min-width: 0; flex: 1 1 auto; }
.tc-h { font-size: .66rem; letter-spacing: 1.4px; text-transform: uppercase; color: var(--accent); font-weight: 700; }
.titlecard.major .tc-h { font-size: .7rem; letter-spacing: 1.8px; }
.tc-name { font-size: 1.02rem; font-weight: 800; margin: 1px 0 2px; line-height: 1.2; overflow-wrap: anywhere; }
.titlecard.major .tc-name { color: var(--accent-2); font-size: 1.12rem; }
.tc-meta { color: var(--txt-dim); font-size: .76rem; line-height: 1.3; }
.tc-team { display: flex; align-items: center; gap: 6px; font-size: .82rem; margin-top: 5px; color: var(--txt); }
.tc-team svg { display: block; }
.tc-cut { color: var(--good); font-size: .8rem; margin-top: 3px; font-weight: 600; }
@keyframes tcfade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .titlecard { animation: none; } }

/* ============================ GRAND SLAM ESL / IEM ============================
   Quatre titres ESL/IEM dans une fenetre glissante de dix. Trois blocs : la CARTE DE
   CONQUETE (le lingot en grand), la PROGRESSION (bandeau discret) et le BANDEAU de fin
   de carriere. Or plus profond que celui du Major, pour que les deux ne se confondent
   pas cote a cote. Disposition EMPILEE par defaut (le lingot au-dessus du texte) :
   c'est ce qui tient a 390 px sans debordement ; la mise en ligne n'apparait qu'au-dela
   de 520 px, ou la largeur le permet reellement. */
/* Marges interieures et interlignes resserres le 2026-07-26, en meme temps que les cartes
   de titre et avec le lingot ramene de 150 a 108 px : la carte de conquete perd ~90 px de
   hauteur sans rien perdre de son contenu ni de son rang (c'est la carte la plus rare du
   jeu, elle reste la plus haute et la seule cerclee d'or profond). */
.gscard {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 9px;
  background: linear-gradient(180deg, #2a2010, #14110a);
  border: 1px solid #c8891a; border-radius: 16px;
  box-shadow: 0 0 0 1px rgba(200,137,26,.28), 0 10px 30px rgba(0,0,0,.45);
  padding: 14px 14px; margin-bottom: 12px; animation: tcfade .35s ease;
}
.gscard .gs-trophy { flex: 0 0 auto; line-height: 0; }
.gscard .gs-trophy svg { max-width: 100%; height: auto; }
.gscard .gs-body { min-width: 0; width: 100%; }
.gs-h { font-size: .74rem; letter-spacing: 2.4px; text-transform: uppercase; color: #ffd97a; font-weight: 800; }
.gs-name { font-size: 1.16rem; font-weight: 800; color: #ffe6a3; margin: 3px 0; overflow-wrap: anywhere; }
.gs-name .gs-num { font-size: .82rem; color: var(--txt-dim); font-weight: 700; }
.gs-sub { color: var(--txt-dim); font-size: .82rem; line-height: 1.4; }
.gs-team { display: flex; align-items: center; justify-content: center; gap: 7px; font-size: .88rem; margin-top: 7px; color: var(--txt); flex-wrap: wrap; }
.gs-scelle { font-size: .82rem; color: var(--txt-dim); margin-top: 3px; overflow-wrap: anywhere; }
.gs-titres { list-style: none; margin: 7px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; }
.gs-titres li {
  background: rgba(200,137,26,.14); border: 1px solid rgba(200,137,26,.4); border-radius: 999px;
  padding: 3px 9px; font-size: .76rem; color: #ffe6a3; overflow-wrap: anywhere;
}
.gs-cut { color: var(--good); font-size: .84rem; margin-top: 9px; font-weight: 600; overflow-wrap: anywhere; }
@media (min-width: 520px) {
  .gscard { flex-direction: row; align-items: center; text-align: left; gap: 18px; }
  .gscard .gs-body { width: auto; }
  .gscard .gs-team, .gscard .gs-titres { justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) { .gscard { animation: none; } }

/* Progression vers le prochain Grand Slam : un bandeau, jamais une jauge. */
.gs-prog {
  display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap;
  background: var(--bg-2); border: 1px solid var(--line); border-left: 3px solid #c8891a;
  border-radius: 12px; padding: 10px 12px; margin: 10px 0;
}
.gs-prog.chaud { border-color: #c8891a; background: linear-gradient(180deg, #221b0f, var(--bg-2)); }
.gs-prog .gsp-ic { flex: 0 0 auto; line-height: 0; }
.gs-prog .gsp-tx { flex: 1 1 190px; min-width: 0; font-size: .86rem; line-height: 1.45; color: var(--txt); overflow-wrap: anywhere; }
.gs-prog .gsp-alerte { color: #ffd97a; font-weight: 600; }
.gs-prog .gsp-liste { flex: 1 1 100%; font-size: .78rem; color: var(--txt-dim); overflow-wrap: anywhere; }

/* Bandeau de fin de carriere + vitrine du palmares. */
.gs-banner {
  display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; text-align: center;
  background: linear-gradient(180deg, #2a2010, var(--bg-2));
  border: 1px solid #c8891a; border-radius: 12px; padding: 10px 14px; margin: 12px 0;
  color: #ffe6a3; font-size: .92rem;
}
.gs-banner strong { color: #ffd97a; }
.gs-palm { margin-top: 4px; }
.tshow-group.grandslam { border-color: #c8891a; background: linear-gradient(180deg, #221b0f, var(--bg-2)); }
.tshow-group.grandslam .tshow-fam { color: #ffd97a; }

/* Historique : embleme devant l'org */
.histo-left { display: flex; align-items: center; gap: 9px; }

/* Vitrine des trophees (fin de carriere) */
.tshow { margin-top: 4px; }
.tshow-group { background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; margin-bottom: 10px; }
.tshow-group.major { border-color: #f2c14e; background: linear-gradient(180deg, #221d11, var(--bg-2)); }
.tshow-fam { font-size: .82rem; font-weight: 700; color: var(--accent-2); margin-bottom: 10px; text-transform: uppercase; letter-spacing: .8px; }
.tshow-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.tshow-item { text-align: center; }
.tshow-tr { min-height: 60px; display: flex; align-items: flex-end; justify-content: center; }
.tshow-lab { font-size: .76rem; color: var(--txt); margin-top: 5px; line-height: 1.25; }

/* Page de controle des emblemes */
.verif-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.verif-cell { background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; padding: 12px; text-align: center; }
.verif-sizes { display: flex; align-items: flex-end; justify-content: center; gap: 10px; margin-bottom: 8px; min-height: 96px; }
.verif-name { font-size: .78rem; color: var(--txt-dim); word-break: break-word; }

/* ============================================================ v6 : Defi + Palmares */
.defi-info { color: var(--accent-2); font-size: .82rem; margin-top: 12px; max-width: 420px; margin-left: auto; margin-right: auto; }

/* Contraintes imposees du defi */
.defi-constraints { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 18px; }
.dchip { display: inline-flex; flex-direction: column; gap: 2px; background: var(--bg-card); border: 1.5px solid var(--line); border-radius: 12px; padding: 8px 12px; font-size: .72rem; color: var(--txt-faint); text-transform: uppercase; letter-spacing: .6px; }
.dchip strong { color: var(--accent-2); font-size: .95rem; text-transform: none; letter-spacing: 0; }
.defi-banner { background: #241a10; border: 1px solid var(--accent-dim); border-radius: var(--radius); padding: 12px 14px; margin: 4px 0 16px; font-size: .9rem; color: var(--accent-2); text-align: center; }

/* Score de legende */
.score-list { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 6px 14px; margin-top: 6px; }
.score-line { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: .9rem; }
.score-line:last-child { border-bottom: none; }
.score-line .sc-pts { color: var(--accent-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.score-total { display: flex; justify-content: space-between; gap: 12px; padding: 12px 0 6px; margin-top: 4px; border-top: 2px solid var(--accent-dim); font-weight: 700; font-size: 1.15rem; }
.score-total span:last-child { color: var(--accent); font-variant-numeric: tabular-nums; }

/* Palmares : statistiques */
.pstat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (min-width: 480px) { .pstat-grid { grid-template-columns: repeat(3, 1fr); } }
.pstat { background: var(--bg-card); border: 1px solid var(--line); border-radius: 12px; padding: 12px; text-align: center; }
.ps-val { font-size: 1.2rem; font-weight: 700; color: var(--accent-2); }
.ps-lab { font-size: .72rem; color: var(--txt-faint); margin-top: 3px; text-transform: uppercase; letter-spacing: .5px; }

/* Palmares : tri + liste des legendes */
.sort-row { font-size: .82rem; color: var(--txt-dim); margin: 4px 0 10px; display: flex; align-items: center; gap: 8px; }
.minitab { background: var(--bg-3); border: 1px solid var(--line); color: var(--txt-dim); border-radius: 9px; padding: 5px 11px; font-size: .8rem; cursor: pointer; }
.minitab.on { background: #241a10; border-color: var(--accent); color: var(--accent-2); }
.leg-row { background: var(--bg-card); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; margin-bottom: 8px; }
.leg-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; cursor: pointer; }
.leg-left { display: flex; align-items: center; gap: 8px; min-width: 0; }
.leg-left svg { flex: 0 0 auto; }
.leg-nom { font-weight: 600; }
.leg-right { white-space: nowrap; }
.leg-right strong { color: var(--accent); font-variant-numeric: tabular-nums; }
.leg-meta { font-size: .78rem; color: var(--txt-faint); margin-top: 5px; }
.leg-detail { margin-top: 10px; }
.leg-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.leg-actions .btn { width: auto; }
.badge-defi { display: inline-block; background: var(--accent-dim); color: var(--accent-2); font-size: .66rem; text-transform: uppercase; letter-spacing: .5px; padding: 2px 6px; border-radius: 6px; vertical-align: middle; }

/* ============================================================ v6.1 : migration + export */
.est { color: var(--txt-faint); font-style: italic; }
.est-note { font-size: .8rem; margin-top: 8px; }
.tshow-anterieur { background: var(--bg-2); border: 1px dashed var(--line); border-radius: 12px; padding: 10px 12px; margin-top: 10px; font-size: .88rem; color: var(--txt-dim); }
#palm-export { margin-top: 10px; }
.export-box { margin-top: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .74rem; }

/* ============================================================ v7 : circuit VRS */
/* Encadre d'objectif : bloc PLEINE LARGEUR sur sa propre ligne (il etait auparavant une
   colonne de la ligne d'equipe et chevauchait le reste sur telephone). Le texte passe a la
   ligne au lieu d'etre coupe : un objectif tronque ne veut plus rien dire. */
.hud-vrs-obj { display: block; width: 100%; margin-top: 4px; font-size: .78rem; line-height: 1.35; color: var(--accent-2); background: #241a10; border: 1px solid var(--accent-dim); border-radius: 8px; padding: 6px 9px; white-space: normal; overflow-wrap: anywhere; }
.vrs-synth { background: var(--bg-2); border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 10px; padding: 9px 12px; margin: 10px 0; font-size: .9rem; color: var(--txt-dim); }
.vrs-synth .vrs-pts { color: var(--accent-2); font-weight: 700; }
.res-table td.res-vrs { color: var(--accent-2); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Mouvement de rang (cause -> effet) : le classement bouge tournoi par tournoi. */
.rg-up { color: #6fcf7f; font-weight: 700; }
.rg-down { color: #e2705f; font-weight: 700; }
.rg-stable { color: var(--txt-dim); }
.vrs-synth.rg-up { border-left-color: #6fcf7f; }
.vrs-synth.rg-down { border-left-color: #e2705f; }
.vrs-synth .vrs-fleche { font-weight: 700; margin-right: 4px; }
.vrs-synth strong { color: var(--txt); }
.coupure-major { font-size: .86rem; }

/* ============================================================ decline : banc + reconversion + role switch */
.reconv-banner { background: #10241a; border: 1px solid var(--good); border-radius: var(--radius); padding: 12px 14px; margin: 4px 0 16px; font-size: .92rem; color: var(--good); text-align: center; }
.act-roleswitch { border-color: var(--accent-dim); }

/* Rang regional : information secondaire (une seule regle en depend : l'acces au
   circuit regional). Le rang mondial reste l'identite de l'equipe.
   2026-07-26 : `.hud-vrs-reg` et `.hud-vrs-note` ne sont plus produits par l'en-tete de
   saison (leur ligne porte desormais le recapitulatif de palmares, `.hud-palm`). Les deux
   regles sont conservees telles quelles pour un retour en arriere immediat ; le rang
   regional et l'ecart au classement s'affichent aujourd'hui dans la fiche joueur. */
.hud-vrs-reg { margin-top: 0; font-size: .74rem; line-height: 1.3; color: var(--txt-dim); opacity: .8; overflow-wrap: anywhere; }
.vrs-synth .vrs-reg { font-size: .84em; opacity: .78; }

/* Note VRS + ecart au classement (HUD) : la note du premier vaut 2000 par
   construction, seul l'ecart avec le voisin laisse voir son erosion. */
.hud-vrs-note { margin-top: 0; font-size: .76rem; line-height: 1.3; color: var(--txt-dim); overflow-wrap: anywhere; }
/* Avertissement de bilan : la marge s'est effondree en une saison. */
.vrs-alerte { margin: 6px 0 0; font-size: .86rem; color: var(--accent-2); border-left: 3px solid var(--accent-dim); padding-left: 9px; }

/* ---- Options de role sur les evenements : visibles du seul role concerne ---- */
.choice-btn.role-opt { border-color: var(--accent-dim); background: linear-gradient(180deg, rgba(184,145,47,.10), transparent); }
.c-role { display: inline-block; font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-2); border: 1px solid var(--accent-dim); border-radius: 999px; padding: 1px 7px; margin-right: 8px; vertical-align: middle; }

/* ---- Moments d'anthologie ---- */
.anthologie { border: 1px solid var(--accent-dim); border-left: 3px solid var(--accent-2); background: linear-gradient(180deg, rgba(246,227,174,.08), transparent); border-radius: 10px; padding: 10px 13px; margin: 10px 0; }
.anthologie.rate { border-left-color: var(--bad); background: linear-gradient(180deg, rgba(226,112,95,.08), transparent); }
.anthologie .ant-h { font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 4px; }
.anthologie.rate .ant-h { color: var(--bad); }
.anthologie .ant-t { font-size: .95rem; line-height: 1.45; }
.moments-list { display: flex; flex-direction: column; gap: 6px; }
.moment-line { display: flex; align-items: baseline; gap: 8px; border: 1px solid var(--line); border-left: 3px solid var(--accent-2); border-radius: 8px; padding: 7px 10px; font-size: .86rem; }
.moment-line.rate { border-left-color: var(--bad); }
.moment-line .mo-ic { color: var(--accent-2); flex: 0 0 auto; }
.moment-line.rate .mo-ic { color: var(--bad); }
.moment-line .mo-txt { flex: 1 1 auto; }
.moment-line .mo-s { flex: 0 0 auto; font-size: .76rem; color: var(--txt-dim); }
/* Enveloppe d'un moment de la liste QUAND il porte un kill feed : la ligne compacte
   d'origine (.moment-line) est inchangee, le feed vient dessous. Sans feed, la ligne
   reste seule dans .moments-list, exactement comme avant. */
.moment-item { display: flex; flex-direction: column; gap: 5px; }

/* ---- Kill feed d'un moment d'anthologie (3 frags ou plus) ----
   Une ligne par frag, sous le texte narratif et jamais a sa place : auteur a gauche,
   icone d'arme au centre, adversaire elimine a droite. Les lignes entrent l'une apres
   l'autre (retard indexe par --kf-i, pose en style inline par main.js) pour rendre la
   tension du clutch. Charte sombre et ambre du jeu, aucune ressource externe.
   RESPONSIVE : chaque ligne est un flex a trois cases dont les deux cases de texte
   peuvent retrecir (min-width: 0) et couper un pseudo trop long (overflow-wrap), donc
   aucun debordement horizontal a 390 px, meme avec un pseudo de 16 caracteres. */
.killfeed { display: flex; flex-direction: column; gap: 4px; margin-top: 9px; }
.kf-cap { font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; color: var(--txt-faint); }
/* ⚠️ LE TRIO EST GROUPE AU CENTRE, ET LES ARMES S'ALIGNENT A LA VERTICALE.
   Grille a colonnes FIXES — 58 px de pseudo, 92 px d'arme, 58 px de pseudo — et
   un ecart IDENTIQUE de 11 px de part et d'autre de l'arme. Deux colonnes de
   pseudo de largeur egale, c'est ce qui fait que sur un multi-frag les armes
   tombent exactement l'une sous l'autre : c'est la raison d'etre de la grille,
   pas un effet de style. Largeur totale 230 px, donc aucun debordement a 390 px.
   Un pseudo trop long est ecrete par l'ellipse plutot que d'elargir sa colonne. */
.kf-line {
  display: grid; grid-template-columns: 58px 92px 58px; column-gap: 11px;
  justify-content: center; align-items: center; min-width: 0;
  background: rgba(0, 0, 0, .42);
  border: 1px solid var(--line); border-left: 2px solid var(--accent-dim);
  border-radius: 6px; padding: 4px 9px;
  font-size: .78rem; line-height: 1.3;
  animation: kf-in .34s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: calc(var(--kf-i, 0) * 300ms);
}
.kf-line .kf-a { min-width: 0; font-weight: 700; color: var(--accent-2);
  text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kf-line .kf-w { display: inline-flex; align-items: center; justify-content: center; color: var(--accent); }
.kf-line .kf-w svg { display: block; width: 92px; height: auto; }
.kf-line .kf-v { min-width: 0; text-align: left; color: var(--txt-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes kf-in { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
/* Animations reduites : toutes les lignes d'emblee, sans retard ni deplacement. */
@media (prefers-reduced-motion: reduce) {
  .kf-line { animation: none; }
}

/* ---- Rotation du pool de maps (bilan de saison) ---- */
.map-rota { margin: 8px 0; font-size: .86rem; color: var(--txt-dim); border-left: 3px solid var(--line); padding-left: 9px; }

/* ============================ ACADEMIES (nature, promotion, denouement) ===== */
.nature-badge { font-size: .68rem; padding: 2px 8px; border-radius: 20px; font-weight: 700; letter-spacing: .3px; }
.nature-badge.acad { background: #10222e; border: 1px solid var(--info); color: var(--info); }
/* Mouvement interne au groupe (academie <-> maison mere) : aucune indemnite. */
.nature-badge.interne { background: #14231a; border: 1px solid var(--good); color: var(--good); }
/* Transfert international / retour au pays : destination affichee. */
.nature-badge.intl { background: #2a1e0f; border: 1px solid var(--accent); color: var(--accent-2); }
.offer-intl { border-color: #5a3a12; }
.offer-acad { border-color: #1f4256; }
.offer-nature { margin: 0 0 6px; display: flex; flex-wrap: wrap; gap: 5px; }
/* Ce que l'on risque en refusant une prolongation (jamais le resultat, seulement le risque). */
.offer-risque, .risque-ligne { font-size: .8rem; color: var(--accent-2); background: #241a10;
  border-left: 3px solid var(--accent-dim); border-radius: 8px; padding: 8px 10px; margin: 8px 0 0; line-height: 1.35; }
.risque-ligne { margin: 4px 0 10px; }
/* Banniere : academie qui met en vente / ne prolonge pas (ou denouement top 30) */
.acad-exit { background: #241a10; border: 1px solid var(--accent-dim); border-left: 3px solid var(--accent); border-radius: 10px; padding: 11px 13px; margin: 4px 0 14px; font-size: .88rem; color: var(--accent-2); }
.acad-warn { background: var(--bg-2); border: 1px solid var(--line); border-left: 3px solid var(--info); border-radius: 10px; padding: 10px 13px; margin: 4px 0 14px; font-size: .86rem; color: var(--txt-dim); }
/* Ecran dedie de promotion vers l'equipe premiere */
.promo-card { background: var(--bg-card); border: 1.5px solid var(--good); border-radius: 14px; padding: 16px; margin: 6px 0 14px; text-align: center; }
.promo-embs { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 10px; }
.promo-arrow { color: var(--good); font-size: 1.6rem; font-weight: 800; }
.promo-parent { font-size: 1.25rem; font-weight: 800; color: var(--txt); margin-bottom: 10px; }
.promo-parent .tier-badge { font-size: .68rem; padding: 2px 8px; border-radius: 20px; background: var(--bg-3); color: var(--accent-2); margin-left: 6px; font-weight: 600; }
.promo-card .narr { text-align: left; }
/* Ecran dedie : bascule vers l'IGL / support (tournant de carriere) */
.roleswitch-card { background: var(--bg-card); border: 1.5px solid var(--accent); border-radius: 14px; padding: 16px; margin: 6px 0 14px; }
.roleswitch-card .narr { font-style: italic; color: var(--txt); }
.rs-deal { margin: 12px 0 6px; }
.rs-list { list-style: none; padding: 0; margin: 6px 0 0; display: flex; flex-direction: column; gap: 7px; }
.rs-list li { font-size: .88rem; color: var(--txt-dim); line-height: 1.4; }
.rs-actions { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; }
.rs-actions .btn { display: flex; flex-direction: column; align-items: flex-start; text-align: left; height: auto; padding: 11px 14px; gap: 3px; }
.rs-desc { font-size: .74rem; font-weight: 500; opacity: .82; }
/* Historique : marqueur de promotion vs transfert */
.histo-via { font-size: .68rem; padding: 1px 7px; border-radius: 20px; margin-left: 7px; font-weight: 700; }
.histo-via.promo { background: #12291b; border: 1px solid var(--good); color: var(--good); }

/* ============================ PROGRESSION (jetons / quetes / avantages) ============================ */
.jetons-head { text-align: center; margin: 4px 0 10px; padding: 14px; background: linear-gradient(180deg, var(--bg-3), var(--bg-2)); border: 1px solid var(--line); border-radius: var(--radius); }
.jetons-head .jh-num { font-size: 2.4rem; font-weight: 800; color: var(--accent-2); letter-spacing: -1px; }
.jetons-head .jh-ic { font-size: 1.6rem; color: var(--accent); }
.jetons-head .jh-lab { font-size: .8rem; color: var(--txt-dim); text-transform: uppercase; letter-spacing: .05em; margin-top: 2px; }
.defi-neutral { font-size: .82rem; color: var(--info); background: #0f1c26; border: 1px solid #244; border-radius: 10px; padding: 8px 12px; margin: 8px 0 4px; text-align: center; }

/* Quetes */
.quest-row { border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; margin: 8px 0; background: var(--bg-card); }
.quest-row.done { border-color: var(--good); background: #101c14; }
.quest-main { display: flex; gap: 10px; align-items: flex-start; }
.quest-ic { font-size: 1.1rem; line-height: 1.3; color: var(--txt-faint); flex: 0 0 auto; }
.quest-row.done .quest-ic { color: var(--good); }
.quest-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quest-txt strong { color: var(--txt); }
.quest-rew { font-size: .74rem; color: var(--accent-2); font-weight: 700; margin-left: 4px; }
.quest-desc { font-size: .82rem; color: var(--txt-dim); }
.quest-prog { font-size: .78rem; color: var(--accent); font-weight: 600; margin-top: 1px; }
.quest-row.done .quest-prog { color: var(--good); }

/* Avantages / catalogue */
.equip-head { font-size: .86rem; margin: 10px 0 6px; padding: 8px 10px; background: var(--bg-2); border-radius: 10px; border: 1px solid var(--line); }
.perk-row { border: 1px solid var(--line); border-radius: 12px; padding: 11px 12px; margin: 8px 0; background: var(--bg-card); }
.perk-row.owned { border-color: var(--accent-dim); }
.perk-row.equipped { border-color: var(--accent); background: #1e1710; box-shadow: 0 0 0 1px var(--accent-dim) inset; }
.perk-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.perk-nom { font-weight: 700; color: var(--txt); }
.perk-cost { color: var(--accent-2); font-weight: 700; font-size: .9rem; white-space: nowrap; }
.perk-state { font-size: .74rem; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .04em; }
.perk-desc { font-size: .84rem; color: var(--txt-dim); margin: 4px 0 8px; }
.perk-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.perk-org { margin-top: 8px; font-size: .82rem; color: var(--txt-dim); }
.perk-org label { display: block; margin-bottom: 4px; }
.perk-org-sel { width: 100%; padding: 8px; background: var(--bg-3); color: var(--txt); border: 1px solid var(--line); border-radius: 8px; font-size: .86rem; }
.perk-org-warn { color: var(--accent); }

/* Marquages divers */
.jetons-gain { text-align: center; font-size: 1.05rem; font-weight: 800; color: var(--accent-2); margin: 10px 0; padding: 8px; background: #1e1710; border: 1px solid var(--accent-dim); border-radius: 10px; }
.avant-note { font-size: .8rem; margin-top: 6px; }
.avant-badge { font-size: .68rem; padding: 1px 7px; border-radius: 20px; background: #1e1710; border: 1px solid var(--accent-dim); color: var(--accent-2); font-weight: 700; }

/* ============================ Drapeaux (emoji ou repli SVG) ============================
   Le drapeau precede toujours le nom du pays (jamais a sa place). Alignement vertical
   soigne a toutes les tailles : l'emoji ne se comporte pas comme une image. */
.flagico { display: inline-block; font-size: 1.05em; line-height: 1; vertical-align: -0.08em; margin-right: 0.05em;
  font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif; }
.flagsvg { display: inline-block; height: 0.82em; width: 1.23em; vertical-align: -0.06em; margin-right: 0.12em;
  border-radius: 2px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16); }
.chip .flagico { font-size: 1.1em; }
.chip .flagsvg { height: 0.95em; width: 1.42em; }

/* ============================ Renommage du joueur ============================ */
.rename-btn { background: transparent; border: 1px solid var(--line); color: var(--txt-dim); border-radius: 6px;
  font-size: .78rem; line-height: 1; padding: 2px 6px; cursor: pointer; margin-left: 6px; vertical-align: middle; }
.rename-btn:hover { color: var(--accent-2); border-color: var(--accent-dim); }
.rename-box { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0; }
.rename-input { flex: 1 1 130px; min-width: 110px; padding: 7px 9px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-3); color: var(--txt); font-size: .95rem; }
.rename-input:focus { outline: none; border-color: var(--accent); }
.rename-err { flex-basis: 100%; color: var(--bad); font-size: .8rem; min-height: 0; }
.rename-err:empty { display: none; }
.rename-orig { font-size: .78rem; margin: 0 0 6px; }
.rename-zone:empty { display: none; }

/* ================================================================================
   JAUGES ET EXPLICATIONS (tache « rendre lisible ce que chaque valeur gouverne »)
   ================================================================================ */

/* En-tete adapte au role : Forme + les 2 statistiques du poste (toujours 3 colonnes,
   la grille existante est donc conservee telle quelle). Couleur distincte pour les
   statistiques, afin de ne pas les confondre avec la jauge de Forme. */
.g-stat .g-fill { background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
.g-stat2 .g-fill { background: linear-gradient(90deg, #b565e0, #d79bf0); }

/* Ligne « valeur + barre + phrase qui dit ce qu'elle gouverne » (fiche joueur et
   ecran « Comment ca marche »). */
.val-row { padding: 10px 0; border-bottom: 1px solid var(--line); }
.val-row:last-child { border-bottom: none; }
.val-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.val-name { font-size: .92rem; font-weight: 600; }
.val-num { font-size: 1.05rem; font-weight: 700; color: var(--accent); }
.val-badge {
  display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 20px;
  background: #241a10; border: 1px solid var(--accent-dim); color: var(--accent-2);
  font-size: .66rem; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  vertical-align: middle;
}
.val-desc { color: var(--txt-dim); font-size: .84rem; line-height: 1.45; margin: 7px 0 0; }

/* ---------------------------------------------- Ecran « Comment ca marche » */
.howto-note { color: var(--txt-dim); font-size: .88rem; line-height: 1.5; margin: 8px 0 12px; }
.howto-note strong { color: var(--txt); }
.howto-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 8px 0 14px; }
.howto-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.howto-table th {
  text-align: left; color: var(--txt-faint); font-weight: 600; font-size: .68rem;
  text-transform: uppercase; letter-spacing: .4px; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.howto-table td { padding: 7px 8px; border-bottom: 1px solid var(--line); }
.howto-table tbody tr:last-child td { border-bottom: none; }
.howto-table td:not(:first-child) { text-align: right; color: var(--txt-dim); white-space: nowrap; }
.howto-table td.poids-nul { color: var(--txt-faint); opacity: .55; }

/* ------------------------------------- Difficulte annoncee par nationalite */
.nat-legende { font-size: .78rem; color: var(--txt-faint); margin: 0 0 8px; }
.nat-leg-item { white-space: nowrap; }
.nat-info { font-size: .84rem; color: var(--txt-dim); line-height: 1.45; margin: 10px 0 0; }
.nat-info strong { color: var(--txt); }
.nat-info .dim strong { color: var(--txt-dim); }
/* Indicateur a trois points : 1 allume = chemin court, 3 = chemin long. */
.nat-diff { display: inline-flex; gap: 2px; vertical-align: middle; }
.nat-diff i { width: 5px; height: 5px; border-radius: 50%; display: inline-block; }
/* Les points eteints doivent rester VISIBLES : sans eux, « 1 point allume » et
   « 3 points allumes » ne se lisent pas comme une echelle mais comme deux symboles
   sans rapport. Contour clair plutot qu'un aplat sombre noye dans la puce. */
.nat-diff i.off { background: transparent; box-shadow: inset 0 0 0 1px var(--txt-faint); opacity: .6; }
.nat-diff-court i.on { background: var(--good, #5fce8b); }
.nat-diff-moyen i.on { background: var(--accent); }
.nat-diff-long i.on { background: #e0863f; }
.nat-groupe { margin-bottom: 6px; }
.nat-groupe-t { font-size: .86rem; color: var(--txt-dim); line-height: 1.45; margin-bottom: 2px; }
.nat-groupe-t strong { color: var(--txt); }

/* Sous 600 px (telephone) : le tableau des poids de rating compte 6 colonnes et devait
   defiler horizontalement dans son conteneur. On le rend lisible sans defilement —
   police et marges resserrees, intitules de colonne raccourcis par un attribut data-court
   (le libelle complet reste dans l'en-tete au-dela de 600 px). */
@media (max-width: 599.98px) {
  .howto-table { font-size: .74rem; }
  .howto-table th, .howto-table td { padding: 6px 3px; }
  .howto-table th { font-size: .58rem; letter-spacing: 0; }
  .howto-table th[data-court]::after { content: attr(data-court); }
  .howto-table th[data-court] .th-long { display: none; }
  .howto-table td:first-child, .howto-table th:first-child { padding-left: 0; }
}
@media (min-width: 600px) {
  .howto-table th[data-court]::after { content: none; }
}

/* Tableau des poids de rating : les deux valeurs mises en evidence sont exactement
   celles que l'en-tete de saison affiche (les deux plus forts poids du poste). */
.howto-table td.poids-tete { color: var(--accent); font-weight: 700; }
.poids-tete-txt { color: var(--accent); }

/* ================================================================ STATISTIQUES DETAILLEES
   Bandeau de valeurs (% Swing, KAST, ADR, KPR, DPR, duels d'ouverture, maps), reutilise
   au bilan de saison, dans la fiche joueur, a l'ecran de fin et sous une ligne de tournoi
   depliee. Les valeurs sont DERIVEES du rating : la couleur ne fait que situer chaque
   chiffre par rapport a la moyenne du poste. */
.stats-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 4px; }
.stc {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 9px;
  padding: 5px 9px; min-width: 0;
}
.stc-l { color: var(--txt-faint); font-size: .6rem; text-transform: uppercase; letter-spacing: .4px; font-weight: 700; white-space: nowrap; }
.stc-v { font-size: .86rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.stc.st-hi .stc-v { color: var(--good); }
.stc.st-lo .stc-v { color: var(--bad); }
.stc.st-mid .stc-v { color: var(--txt); }
.stc-maps .stc-v { color: var(--accent-2); }
.chips-saison { justify-content: center; }
.chips-carriere { margin-top: 6px; }
.stats-lead { color: var(--txt-dim); font-size: .8rem; margin: 2px 0 0; }
.stats-note { color: var(--txt-faint); font-size: .74rem; margin: 4px 0 0; line-height: 1.35; }
.stats-legend { color: var(--txt-faint); font-size: .68rem; margin: 4px 0 0; text-transform: uppercase; letter-spacing: .3px; }

/* Bouton de depliage d'une ligne de tournoi : discret, ne change rien tant qu'on n'y touche pas. */
.res-plus {
  margin-left: 6px; background: transparent; border: 1px solid var(--line); color: var(--txt-faint);
  border-radius: 6px; width: 22px; height: 22px; line-height: 1; font-size: .7rem; font-weight: 700;
  cursor: pointer; padding: 0; vertical-align: middle;
}
.res-plus:hover, .res-plus:focus-visible { color: var(--accent); border-color: var(--accent); }
.res-detail td { background: var(--bg-2); padding: 4px 8px 10px; }
/* La regle `.res-table tr { display:block }` du mode telephone l'emporterait sur
   l'attribut `hidden` : on retablit explicitement le repliage aux deux largeurs. */
.res-table tr.res-detail[hidden] { display: none !important; }

/* Evolution des statistiques, saison par saison (fiche joueur). */
.stats-evo { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.evo-line {
  display: grid; grid-template-columns: 2.2rem 2.6rem 1fr 1fr 1fr 3.4rem;
  gap: 4px; align-items: baseline; padding: 5px 6px; border-bottom: 1px solid var(--line);
  font-size: .78rem; font-variant-numeric: tabular-nums;
}
.evo-line:last-child { border-bottom: none; }
.evo-s { color: var(--txt-faint); font-weight: 700; font-size: .72rem; }
.evo-r { color: var(--accent-2); font-weight: 700; }
.evo-v { color: var(--txt-dim); }
.evo-m { color: var(--txt-faint); font-size: .7rem; text-align: right; white-space: nowrap; }

/* Definitions de l'ecran « Comment ca marche ». */
.howto-defs { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 4px; }
.howto-def { background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; }
.hd-n { display: block; color: var(--accent); font-weight: 700; font-size: .82rem; margin-bottom: 2px; }
.hd-t { display: block; color: var(--txt-dim); font-size: .8rem; line-height: 1.45; }

/* Telephone : les valeurs restent lisibles et ne debordent jamais. */
@media (max-width: 599.98px) {
  .stats-chips { gap: 5px; }
  .stc { padding: 4px 7px; }
  .stc-l { font-size: .55rem; letter-spacing: .3px; }
  .stc-v { font-size: .8rem; }
  .res-detail td { display: block; width: 100%; padding: 2px 0 8px; background: transparent; }
  .evo-line { grid-template-columns: 1.9rem 2.4rem 1fr 1fr 1fr; font-size: .74rem; }
  .evo-m { grid-column: 1 / -1; text-align: left; padding-left: 1.9rem; }
}

/* ============================================ VENTILATION DES REVENUS
   Bloc reutilisable (bilan de saison, fiche joueur, ecran de fin). Chaque source occupe
   DEUX lignes : libelle + montant d'abord, barre ensuite. La barre etant seule sur sa
   ligne, rien ne peut deborder a 390 px, quel que soit le montant ou la longueur du
   libelle ; seul le couple libelle/montant partage une ligne, et il reste court. */
.revenus { margin: 6px 0 2px; }
.rev-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  font-size: .82rem; color: var(--txt-dim); margin-bottom: 6px;
}
.rev-total strong { color: var(--accent-2); font-size: 1.02rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rev-lines { display: flex; flex-direction: column; gap: 7px; }
.rev-line { min-width: 0; }
.rev-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; min-width: 0; }
.rev-lab { color: var(--txt); font-size: .8rem; min-width: 0; overflow-wrap: anywhere; }
.rev-val { color: var(--txt-dim); font-size: .8rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rev-val em { color: var(--txt-faint); font-style: normal; font-size: .72rem; margin-left: 3px; }
.rev-bar { height: 5px; background: var(--bg-3); border-radius: 3px; overflow: hidden; margin-top: 3px; }
.rev-bar i { display: block; height: 100%; background: var(--accent-dim); border-radius: 3px; }
/* Une couleur par source : on repere d'un coup d'oeil d'ou vient l'argent. */
.rev-salaire  .rev-bar i { background: #6b6b76; }
.rev-prize    .rev-bar i { background: var(--info); }
.rev-stickers .rev-bar i { background: var(--accent); }
.rev-sponsors .rev-bar i { background: var(--good); }
.rev-primes   .rev-bar i { background: var(--accent-2); }
.rev-evenements .rev-bar i { background: #7a5ad0; }
.rev-anterieur .rev-bar i { background: var(--line); }
/* Depense nette (seule la categorie « Divers » peut l'etre : un evenement peut couter). */
.rev-neg .rev-val { color: var(--bad); }
.rev-neg .rev-bar i { background: var(--bad); }
.rev-cumul { margin-top: 8px; font-size: .8rem; color: var(--txt-dim); display: flex; justify-content: space-between; gap: 8px; }
.rev-cumul strong { color: var(--txt); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rev-vide { font-size: .8rem; color: var(--txt-faint); }
.rev-fin { max-width: 460px; margin-left: auto; margin-right: auto; }

@media (max-width: 599.98px) {
  .rev-lab, .rev-val { font-size: .76rem; }
  .rev-total strong { font-size: .96rem; }
  .rev-lines { gap: 6px; }
}

/* ============================================ VENTILATION DES DEPENSES
   Meme structure que les revenus (barre sur sa propre ligne -> aucun debordement a
   390 px), en accent « depense ». Le pied porte les deux chiffres qui comptent : revenu
   NET de la saison et patrimoine NET cumule. */
.depenses { margin: 6px 0 2px; }
.dep-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  font-size: .82rem; color: var(--txt-dim); margin-bottom: 6px;
}
.dep-total strong { color: var(--bad); font-size: 1.02rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dep-line .rev-val { color: var(--bad); }
.dep-line .rev-bar i { background: var(--bad); }
.dep-impots     .rev-bar i { background: #b6553f; }
.dep-trainDeVie .rev-bar i { background: #c08a3e; }
.dep-viePerso   .rev-bar i { background: #7a5ad0; }
.dep-imprevus   .rev-bar i { background: #7d7d88; }
.dep-evenements .rev-bar i { background: #9b5f8a; }
.dep-anterieur  .rev-bar i { background: var(--line); }
.dep-net strong { color: var(--good); }
.dep-fin, .dep-carriere { max-width: 460px; margin-left: auto; margin-right: auto; }
.fisc-note, .imprevu-note { font-size: .78rem; margin-top: 6px; overflow-wrap: anywhere; }

/* Patrimoine net final, ecran de fin : le pendant du total brut, jamais a sa place. */
.patrimoine-fin { text-align: center; margin: 10px auto 4px; max-width: 460px; }
.pf-val { font-size: 1.5rem; font-weight: 700; color: var(--good); font-variant-numeric: tabular-nums; }
.pf-lab { font-size: .76rem; color: var(--txt-dim); margin-top: 2px; }

/* Ecran « vie hors du serveur » : jalon de vie ou proposition de residence fiscale.
   Les meta (cout, gain fiscal, contrepartie) s'empilent et passent a la ligne : rien ne
   sort de l'ecran a 390 px, quelle que soit la longueur des montants. */
.vie-note { font-size: .78rem; margin: 2px 0 10px; overflow-wrap: anywhere; }
.vie-choice { display: block; text-align: left; }
.vie-choice .c-sub { display: block; font-size: .78rem; color: var(--txt-dim); margin-top: 3px; overflow-wrap: anywhere; }
.vc-meta { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 6px; font-size: .74rem; }
.vc-cout { color: var(--bad); font-variant-numeric: tabular-nums; }
.vc-gain { color: var(--good); font-variant-numeric: tabular-nums; }
.vc-contre { color: var(--txt-faint); }
.vc-libre { color: var(--txt-faint); }
.vie-cout-note { font-size: .82rem; color: var(--txt-dim); margin-top: 6px; }
.vie-cout-note strong { color: var(--bad); font-variant-numeric: tabular-nums; }
/* Categories d'imposition (« Comment ca marche ») : blocs empiles, jamais un tableau —
   la liste des pays est longue par nature et ferait deborder trois colonnes a 390 px. */
.fisc-cats { display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.fisc-cat { background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; min-width: 0; }
.fc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.fc-nom { font-size: .82rem; color: var(--txt); text-transform: capitalize; }
.fc-taux { font-size: .95rem; font-weight: 700; color: var(--bad); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fc-desc { font-size: .74rem; color: var(--txt-dim); margin-top: 2px; overflow-wrap: anywhere; }
.fc-pays { font-size: .74rem; color: var(--txt-faint); margin-top: 4px; overflow-wrap: anywhere; }

@media (max-width: 599.98px) {
  .dep-total strong { font-size: .96rem; }
  .pf-val { font-size: 1.3rem; }
  .vc-meta { font-size: .72rem; }
}

/* ============================================================ Participation aux tournois
   Ecran « calendrier de la saison », marqueurs de prestige, tournois sautes et etat du
   programme de fidelite des organisateurs. Tout est empile en colonne : a 390 px, aucune
   ligne ne peut deborder (les noms de tournoi et d'organisateur sont longs par nature). */
.cal-lead { font-size: .84rem; color: var(--txt-dim); margin: 0 0 10px; overflow-wrap: anywhere; }
.cal-compteur { font-size: .8rem; color: var(--txt-dim); background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 10px; margin-bottom: 10px; overflow-wrap: anywhere; }
.cal-compteur #cal-n { color: var(--accent-2); font-weight: 700; font-variant-numeric: tabular-nums; }
.cal-liste { display: flex; flex-direction: column; gap: 8px; }
.caltour { background: var(--bg-card); border: 1px solid var(--line); border-radius: 10px; padding: 9px 10px; min-width: 0; }
.caltour.oblig { border-color: var(--accent-dim); }
.caltour.sautee { opacity: .62; border-style: dashed; }
.ct-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 8px; }
.ct-titre { min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 7px; }
.ct-mois { font-size: .68rem; text-transform: uppercase; letter-spacing: .5px; color: var(--txt-faint); }
.ct-nom { font-size: .92rem; font-weight: 600; color: var(--txt); overflow-wrap: anywhere; }
.caltour.sautee .ct-nom { text-decoration: line-through; text-decoration-color: var(--txt-faint); }
.pchip { font-size: .66rem; text-transform: uppercase; letter-spacing: .4px; font-weight: 700;
  padding: 2px 7px; border-radius: 999px; white-space: nowrap; border: 1px solid transparent; }
.pchip-incontournable { color: #ffdca8; background: rgba(255, 138, 30, .16); border-color: var(--accent-dim); }
.pchip-optionnel { color: #a8d5f5; background: rgba(74, 163, 224, .14); border-color: rgba(74, 163, 224, .3); }
.pchip-secondaire { color: var(--txt-dim); background: var(--bg-3); border-color: var(--line); }
.pchip-bas { color: var(--txt-faint); background: var(--bg-3); border-color: var(--line); }
.ct-ligne { font-size: .74rem; margin-top: 5px; overflow-wrap: anywhere; }
.ct-gain { color: var(--good); }
.ct-gain strong { color: var(--txt); font-variant-numeric: tabular-nums; }
.ct-cout { color: var(--txt-faint); }
.ct-action { margin-top: 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.ct-lock { font-size: .74rem; color: var(--accent-2); overflow-wrap: anywhere; }
.ct-etat { font-size: .72rem; color: var(--txt-faint); overflow-wrap: anywhere; }

/* Programme de fidelite : une ligne par organisateur, jamais un tableau (les noms
   d'organisateur sont longs et le seuil doit rester lisible a 390 px). */
.fid-bloc { margin-top: 12px; }
.fid-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.fid-list li { font-size: .76rem; background: var(--bg-2); border: 1px solid var(--line); border-left-width: 3px;
  border-radius: 7px; padding: 6px 9px; color: var(--txt-dim); overflow-wrap: anywhere; }
.fid-list li strong { color: var(--txt); font-variant-numeric: tabular-nums; }
.fid-ok { border-left-color: var(--line); }
.fid-warn { border-left-color: var(--accent); }
.fid-ko { border-left-color: var(--bad); }
.fid-cons { display: block; margin-top: 2px; color: var(--bad); }

/* Bilan de saison : joues / sautes / invitations, cote a cote puis empiles si besoin. */
.bilan-cal { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 4px; }
.bc-l { flex: 1 1 90px; min-width: 0; background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 9px; display: flex; flex-direction: column; gap: 1px; }
.bc-v { font-size: 1.15rem; font-weight: 700; color: var(--txt); font-variant-numeric: tabular-nums; }
.bc-saut .bc-v { color: var(--accent-2); }
.bc-k { font-size: .68rem; color: var(--txt-faint); text-transform: uppercase; letter-spacing: .3px; overflow-wrap: anywhere; }
.bc-liste { list-style: none; margin: 4px 0 0; padding: 0; font-size: .78rem; color: var(--txt-dim); }
.bc-liste li { padding: 3px 0; overflow-wrap: anywhere; }

/* Tableau de resultats : ligne d'un tournoi volontairement non dispute. */
.res-table tr.res-saute td { opacity: .6; }
.res-nonjoue { color: var(--txt-faint); font-style: italic; }

/* ============================================================================
   CHARGE DE TRAVAIL, JOURS DE COMPETITION ET REPOS  (2026-07-26)
   AUCUNE JAUGE ICI : pas de barre, pas de remplissage, pas de pourcentage. La
   fatigue s'exprime par la Forme (jauge existante) ; ce bloc ne style que des
   COMPTEURS de jours et des mentions qualitatives. Tout est en unites relatives
   et se replie a 390 px sans debordement.
   ========================================================================== */
.chg-cpt { display: flex; flex-wrap: wrap; gap: .5rem; margin: .4rem 0 .3rem; }
.chg-l { flex: 1 1 8rem; min-width: 0; background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(246, 227, 174, .14); border-radius: .5rem; padding: .5rem .6rem; }
.chg-v { display: block; font-size: 1.35rem; font-weight: 700; color: #F6E3AE; line-height: 1.1; }
.chg-k { display: block; font-size: .74rem; opacity: .68; margin-top: .1rem; overflow-wrap: anywhere; }
.chg-mention { margin: .1rem 0 .35rem; font-size: .84rem; font-weight: 600; letter-spacing: .02em; }
.chg-mention.chg-lourd { color: #E8A87C; }
.chg-mention.chg-neutre { color: #C8C2B4; }
.chg-mention.chg-leger { color: #9FD39F; }
.chg-cpt.chg-lourd { border-left: 2px solid rgba(232, 168, 124, .5); padding-left: .35rem; }
.chg-cpt.chg-leger { border-left: 2px solid rgba(159, 211, 159, .45); padding-left: .35rem; }
.chg-cause { margin: .15rem 0 .5rem; font-size: .82rem; line-height: 1.45; opacity: .9;
  overflow-wrap: anywhere; }
.chg-cause.chg-bon { color: #9FD39F; }
.fiche-note { margin: .2rem 0 .5rem; font-size: .78rem; line-height: 1.45; overflow-wrap: anywhere; }

/* Compteur de jours de l'ecran « calendrier de la saison ». */
.cal-jours { margin: .1rem 0 .5rem; padding: .45rem .6rem; border-radius: .5rem;
  background: rgba(255, 255, 255, .04); border: 1px solid rgba(246, 227, 174, .14);
  font-size: .82rem; line-height: 1.5; overflow-wrap: anywhere; }
.cal-jours.chg-lourd { border-color: rgba(232, 168, 124, .35); }
.cal-jours.chg-leger { border-color: rgba(159, 211, 159, .32); }
.cj-gain { display: block; margin-top: .15rem; font-size: .78rem; color: #9FD39F; }

/* Ligne « benefice de recuperation » d'une carte de tournoi sautable. */
.ct-repos { color: #9FD39F; opacity: .95; }

/* Detail du calcul des jours, sous le compteur du bilan. */
.chg-detail { margin: 0 0 .4rem; font-size: .76rem; line-height: 1.45; overflow-wrap: anywhere; }

/* Coupure estivale : une ligne, deux tons, aucune barre. */
.cal-coupure { margin: 0 0 .5rem; padding: .4rem .6rem; border-radius: .5rem; font-size: .8rem;
  line-height: 1.45; overflow-wrap: anywhere; border: 1px solid rgba(246, 227, 174, .14);
  background: rgba(255, 255, 255, .03); }
.cal-coupure.ok { border-color: rgba(159, 211, 159, .35); color: #9FD39F; }
.cal-coupure.ko { border-color: rgba(232, 168, 124, .3); color: #E8A87C; }

/* Recapitulatif « ce que ton repos te rapporte » (ecran calendrier). */
.cal-recap { margin: 0 0 .6rem; padding: .5rem .65rem; border-radius: .5rem;
  background: rgba(159, 211, 159, .07); border: 1px solid rgba(159, 211, 159, .28); }
.cal-recap .cr-t { margin: 0 0 .3rem; font-size: .8rem; font-weight: 700; color: #9FD39F;
  letter-spacing: .02em; }
.cal-recap .cr-l { margin: 0; padding-left: 1.1rem; font-size: .8rem; line-height: 1.5;
  overflow-wrap: anywhere; }
.cal-recap .cr-l li { margin: .1rem 0; }
.cal-recap .cr-n { margin: .3rem 0 0; font-size: .75rem; opacity: .7; overflow-wrap: anywhere; }

/* ============================ RECOMPENSES ANNUELLES (facon HLTV Awards)
   Presentation VERTICALE : une carte par categorie, dont le contenu s'empile
   (intitule, laureat, note). Rien n'est mis sur une meme ligne flex qui pourrait
   se tasser a 390 px — c'est la lecon de l'en-tete de saison. Le nom du laureat
   et son organisation peuvent revenir a la ligne sans jamais deborder. */
.rec-banner { display: flex; gap: 10px; align-items: flex-start; background: #241a10;
  border: 1px solid var(--accent-dim); border-radius: 12px; padding: 10px 12px; margin: 10px 0; }
.rec-banner .rec-b-ic { font-size: 1.1rem; line-height: 1.3; flex: 0 0 auto; }
.rec-banner .rec-b-tx { color: var(--accent-2); font-size: .88rem; line-height: 1.45; min-width: 0; }
.rec-banner .rec-b-tx strong { color: var(--accent); }

.rec-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 12px; }
.rec-row { background: var(--bg-2); border: 1px solid var(--line); border-left-width: 3px;
  border-radius: 10px; padding: 8px 11px; }
.rec-row.moi { border-color: var(--accent-dim); border-left-color: var(--accent); background: #201810; }
.rec-row.vide { opacity: .62; }
.rec-cat { font-size: .74rem; text-transform: uppercase; letter-spacing: .7px; color: var(--txt-dim); }
.rec-row.moi .rec-cat { color: var(--accent-2); }
.rec-poste { display: inline-block; margin-left: 5px; padding: 1px 6px; border-radius: 8px;
  background: var(--bg-3); border: 1px solid var(--line); font-size: .66rem; letter-spacing: .4px; color: var(--txt-faint); }
.rec-win { margin-top: 2px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.rec-nom { font-weight: 700; font-size: .98rem; overflow-wrap: anywhere; }
.rec-row.moi .rec-nom { color: var(--accent); }
.rec-org { color: var(--txt-dim); font-size: .8rem; overflow-wrap: anywhere; }
.rec-non { color: var(--txt-faint); font-style: italic; font-size: .88rem; }
.rec-note { color: var(--txt-faint); font-size: .74rem; margin-top: 3px; line-height: 1.4; }
.rec-moment { color: var(--txt-dim); font-size: .79rem; margin-top: 4px; line-height: 1.45; overflow-wrap: anywhere; }
.rec-moment.small { font-size: .74rem; margin: 0 0 6px 2px; }

/* Palmares de carriere (fiche joueur, ecran de fin) */
.rec-pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.rec-pill { padding: 5px 12px; border-radius: 20px; font-size: .82rem; border: 1px solid var(--line); background: var(--bg-3); color: var(--txt-dim); }
.rec-pill.or { border-color: var(--accent-dim); color: var(--accent-2); background: #241a10; }
.rec-pill strong { color: var(--txt); }
.rec-pill.or strong { color: var(--accent); }
.rec-palm { margin: 4px 0 8px; }

/* Colonne « sur quoi elle se decide » de l'ecran « Comment ca marche » : phrase
   longue, elle doit pouvoir respirer sans etirer le tableau hors de l'ecran. */
.howto-table td.howto-regle { white-space: normal !important; text-align: left !important;
  min-width: 200px; line-height: 1.45; }

/* =============================================================================
   THEME « CLAIR DOUX » — FONDATIONS + ECRAN JOUEUR PRINCIPAL
   Phase 1 de la refonte visuelle (2026-07-27).

   CE QUE CE BLOC CONTIENT, ET RIEN D'AUTRE :
     1. les JETONS de la palette (variables `--ds-*`), definis UNE FOIS ;
     2. les COMPOSANTS reutilisables (`.ds-card`, `.ds-tile`, `.ds-eyebrow`,
        `.ds-gauge`, `.ds-btn`, `.ds-pill`), tous derives de ces jetons ;
     3. l'APPLICATION du theme au SEUL ecran joueur principal (ecran de saison :
        en-tete + corps narratif / bilan), derriere le selecteur `html.theme-clair`.

   PORTEE — la classe `theme-clair` est posee sur <html> par UI.show() et
   UNIQUEMENT pour `screen-season` (cf. ECRANS_CLAIRS dans js/ui.js). Tous les
   autres ecrans (accueil, creation, fiche, palmares, progression, defi, fin de
   carriere, comment ca marche) gardent le theme sombre d'origine tant qu'ils
   n'ont pas ete repris. Retirer la classe rend l'ecran a son apparence d'avant.

   METHODE — le jeu etait deja entierement ecrit en variables (`--bg`, `--txt`,
   `--accent`…). Le theme clair se contente donc de les REMAPPER sur les jetons
   `--ds-*` : tout l'ecran de saison bascule d'un coup, sans toucher a une seule
   regle existante. Seules les rares couleurs ecrites en dur (fond de l'en-tete,
   encadres ambres) sont reprises nommement, plus bas.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   JETONS DE ROLE — le socle des themes (2026-07-31)

   POURQUOI DES ROLES ET NON DES COULEURS. Un jeton se nomme par ce qu'il FAIT,
   jamais par la teinte qu'il porte aujourd'hui : `--ds-accent` reste l'accent
   dans un theme bleu, la ou `--ds-gold` (son ancien nom, renomme ce jour) aurait
   menti des le premier theme non dore. Meme raison pour --ds-info / --ds-good /
   --ds-bad, qui remplacent --ds-blue / --ds-green / --ds-red.

   CE QUI N'EST PAS ICI, ET NE DOIT PAS Y VENIR :
     - les QUATRE METAUX (diamant, or, argent, bronze) des ecussons, des cartes de
       deblocage et des paliers de pseudo — un metal ne change pas de couleur avec
       le theme, sinon un badge d'or cesse d'etre en or ;
     - les couleurs de TIER (amateur gris, T3 vert, T2 bleu, T1 violet, TS dore) —
       elles encodent un niveau, pas une ambiance ;
     - les BLASONS d'organisations (js/emblems.js) et les DRAPEAUX (js/flags.js) ;
     - les surfaces de trophees `--tr-*` et les icones de vitrine `--ic-*`, qui ont
       deja leur propre jeu de jetons plus bas.
   Un theme ne redefinit que les jetons de ce bloc.
   -------------------------------------------------------------------------- */
:root {
  /* ---- FOND ---- */
  --ds-bg-1: #DCE5F3;                 /* haut du fond bleu-ardoise */
  --ds-bg-2: #CBD7EC;                 /* bas du fond */
  --ds-bg: linear-gradient(150deg, var(--ds-bg-1), var(--ds-bg-2));
  /* Texture diagonale tres discrete, posee PAR-DESSUS le fond (voir body::before).
     Le trait est sorti en jeton : sur un fond clair il eclaircit, sur un fond
     sombre un theme voudra l'assombrir — c'est la seule couleur de la texture. */
  --ds-texture-trait: rgba(255,255,255,.05);
  --ds-texture: repeating-linear-gradient(135deg,
      var(--ds-texture-trait) 0, var(--ds-texture-trait) 2px, transparent 2px, transparent 20px);
  /* ---- SURFACES ---- */
  --ds-card: #FFFFFF;                 /* carte flottante */
  /* DEUX JETONS LA OU IL N'Y EN AVAIT QU'UN   (scindement du 2026-08-01, etape 3)
     `--ds-on-solid` portait DEUX roles incompatibles, et aucune valeur unique ne
     pouvait servir les deux :
       - ENCRE posee sur un aplat de couleur (chiffre d'un badge, glyphe d'une
         pastille) : elle doit contraster avec l'APLAT, donc etre claire sur un
         aplat sombre et sombre sur un aplat clair ;
       - CONTOUR trace autour de ce badge, qui le detache de LA PAGE : il doit
         contraster avec le fond de la page, donc suivre la carte.
     Sur un theme clair les deux valent le meme blanc et rien ne se voit ; sur un
     theme sombre elles divergent completement. Le scindement est ce qui coute le
     plus cher a repousser : chaque theme ajoute en multiplierait le prix. */
  --ds-on-solid: #FFFFFF;             /* ENCRE posee SUR un aplat de couleur */
  --ds-outline: #FFFFFF;              /* CONTOUR d'un badge, trace sur la page */
  --ds-field-bg: #F3F6FB;             /* fond d'un champ / d'une case neutre */
  --ds-track: #E7ECF4;                /* piste de jauge, fond neutre */
  /* ---- TEXTE ----
     Les trois niveaux ont ete ASSOMBRIS le 2026-08-01 (etape 3) pour que le texte
     attenue et le texte discret repassent au-dessus de 4,5:1 sur la carte blanche
     ET sur le fond de champ : ils etaient a 4,32 et 3,01. La hierarchie des trois
     encres est conservee — c'est elle qui fait lire l'ecran. */
  --ds-text: #242A3A;                 /* texte principal      (14,3:1 sur carte) */
  --ds-text-dim: #646B7A;             /* texte attenue        (5,35:1 sur carte) */
  --ds-text-faint: #6D778B;           /* texte le plus discret (4,50:1 sur carte) */
  /* ---- ACCENT ---- */
  --ds-accent: #E39A1F;                 /* accent : icones, etoiles */
  --ds-accent-light: #E7A94A;           /* accent CLAIR, depart du degrade de remplissage */
  --ds-accent-dim: #F0DCB2;             /* accent EFFACE : lisere au survol, contour discret */
  /* TROIS NIVEAUX D'ENCRE DOREE, ET PLUS SEPT   (fusion du 2026-08-01)
     Le socle portait SEPT dores sombres quasi identiques qui rendaient le meme
     service — #B06E00 #A96E00 #96610A #8A5E08 #7A5206 #7A4E00 #6B4A08 —, quatre en
     jetons et trois ecrits en dur. Chaque theme aurait eu a en redefinir sept.
     Ils sont ramenes a TROIS niveaux, departages par le CONTRASTE et non par
     l'habitude : a chaque fusion la valeur retenue est la PLUS FONCEE des deux,
     celle qui ne degrade jamais la lisibilite (#B06E00 -> #A96E00, et
     #96610A -> #8A5E08 qui fait au passage repasser `.fcm-rat.top` au-dessus de
     4,5:1). NON FUSIONNES, ET C'EST VOULU : #7A5206 et #7A4E00 dans leurs emplois
     METAL (or des ecussons, carte de palier « or »), et #96610A dans `.otier-ts`
     (couleur de TIER). Un metal, un tier encodent une valeur d'accomplissement :
     ils ne suivent aucun theme. */
  --ds-accent-deep: #A06700;            /* encre d'accent : valeurs, chiffres, libelles (4,74:1 sur carte) */
  --ds-accent-ink: #875C08;             /* encre RENFORCEE, sur les fonds dores pales (5,23 / 4,50) */
  --ds-accent-ink-fort: #6B4A08;        /* encre FORTE (7:1), reservee aux avertissements */
  /* APLAT DORE PLEIN — le carre du palier FACEIT. Ce n'est pas une surface pale :
     c'est de l'or SATURE, qui porte un glyphe. Son encre est `--ds-btn-txt`, jamais
     `--ds-on-solid` : du blanc sur cet or ne fait que 2,4:1. */
  --ds-accent-solid-1: #F3B63C;         /* depart du degrade */
  --ds-accent-solid-2: #D18A0C;         /* arrivee */
  /* LAVIS DORE en trois crans, du plus clair au plus soutenu. Ce sont les fonds des
     grands encadres dores (verrou du Defi, avertissement de sauvegarde, vitrine des
     distinctions), auparavant six valeurs ecrites en dur dans cinq regles. */
  --ds-accent-wash-1: #FFFCF4;
  --ds-accent-wash-2: #FDF4DF;
  --ds-accent-wash-3: #F7E7BF;
  /* DEUX SURFACES DOREES PALES, ET PLUS TROIS. #FBEACB et #FCEFCF etaient ecrits en
     dur et faisaient le meme service que ce jeton : ils y sont fondus. Il en reste
     DEUX et non une, parce qu'un aplat et une FIN de degrade ne peuvent pas etre le
     meme nombre. Les emplois METAL de #FCEFCF (carte de palier « or », titre Grand
     Slam) gardent leur valeur en dur, pour la meme raison que ci-dessus. */
  --ds-accent-soft-bg: #FBF1D6;         /* fond de la tuile surlignee / pastille */
  --ds-accent-soft-bg-2: #F6DFAA;       /* fin du degrade dore */
  /* ---- ETATS ----
     Chaque etat porte QUATRE emplois, et chacun a son jeton depuis le 2026-08-01
     (etape 3) : la couleur vive (encre sur la carte ET aplat sous une encre
     claire), l'ENCRE sur son propre fond pale, le FOND pale, et le FILET de ce
     fond. Sans cette famille, une regle sur deux ecrivait sa nuance en dur et
     restait claire sous un theme sombre. `--ds-good` et `--ds-bad` ont ete
     legerement assombris (3,43 et 4,38) pour tenir 4,5:1 dans les deux sens. */
  --ds-info: #2F6FB0;                 /* EVP, liens, information       (5,22:1) */
  --ds-good: #1A8755;                 /* reussite, valeurs positives   (4,53:1) */
  --ds-bad: #D0473B;                  /* echec, valeurs negatives      (4,52:1) */
  --ds-info-ink: #235784;             /* encre d'information sur son fond pale */
  --ds-info-soft-bg: #E7F0F9;
  --ds-info-soft-line: #CFE0F0;
  --ds-info-light: #6FA8DC;           /* arrivee du degrade de la jauge d'information */
  --ds-good-ink: #14704A;             /* encre positive sur son fond pale */
  --ds-good-soft-bg: #E6F5EE;
  --ds-good-soft-line: #C6E7D8;
  /* ⚠️ AJOUTE LE 2026-08-13, ET IL COMBLE UNE ASYMETRIE : la famille `info` avait
     son `-light` — le depart clair d'un degrade — la famille `good` n'en avait
     pas. Deux des six ecus de l'accueil sortaient donc en BLEU faute d'un vert
     capable de porter un degrade. Valeur reprise telle quelle de la palette
     fournie avec la commande de l'accueil. */
  --ds-good-light: #63CFA0;           /* depart clair du degrade positif */
  /* ⚠️ LA FAMILLE VIOLETTE EST NEUVE, ET ELLE EXISTE POUR UNE SEULE RAISON :
     « Carriere Coach » devait se distinguer de « Progression », et les deux
     tiraient `--ds-info`. Elle suit la forme des trois autres familles d'etat —
     le vif, son depart clair, son encre — et elle est INSCRITE DANS LA LISTE des
     jetons de `js/themes.js`, donc un theme peut la redefinir comme les autres.
     ⚠️ ELLE N'EST PAS UN ETAT : rien n'est « violet » au sens de reussite ou
     d'echec. C'est une couleur d'IDENTITE de mode, et c'est pour cela qu'elle ne
     porte ni fond pale ni filet — personne n'a de message a peindre avec.
     Les trois valeurs viennent de la palette fournie avec la commande. */
  --ds-viol: #5C3AA8;                 /* identite du mode Carriere Coach */
  --ds-viol-light: #A184DE;           /* depart clair de son degrade */
  --ds-viol-ink: #2E1C58;             /* son encre, pour la gravure */
  --ds-bad-ink: #A83A2F;              /* encre negative sur son fond pale */
  --ds-bad-soft-bg: #FBE9E6;
  /* AVERTISSEMENT : ni une erreur (rouge) ni une reussite. Une seule encre, pour
     les mentions « lourd » et la coupure estivale manquee. */
  --ds-warn-ink: #B4551F;
  /* ALERTE : la pastille rouge de notification. Distincte de `--ds-bad`, qui est
     une VALEUR negative ; celle-ci est un rappel a l'oeil. Assombrie de #E0402F
     pour porter du texte clair a 4,5:1. */
  --ds-alerte: #DE3625;
  /* JAUGE SECONDAIRE : la seule couleur du jeu qui ne soit ni l'accent ni un etat.
     Elle sert a distinguer une statistique derivee d'une jauge de jeu. */
  --ds-fill-alt-1: #7A57C7;
  --ds-fill-alt-2: #A98BE0;
  /* ---- FILETS ---- */
  --ds-line: #E4EAF4;                 /* filet de separation et lisere de champ */
  --ds-line-hover: #D6DDE9;           /* le meme, survole : un cran plus marque */
  /* ---- BOUTON PRINCIPAL (degrade d'accent, texte sombre lisible) ---- */
  --ds-btn-1: #F3B94A;                /* haut du degrade */
  --ds-btn-2: var(--ds-accent);       /* bas du degrade */
  --ds-btn-txt: #3A2600;              /* son texte */
  --ds-btn-shadow: 0 2px 6px rgba(227,154,31,.28);
  /* ---- REMPLISSAGE DES JAUGES ET DES BARRES ---- */
  --ds-fill-1: var(--ds-accent);      /* depart du degrade de remplissage */
  --ds-fill-2: #F5BE5C;               /* son arrivee */
  /* Bouton SECONDAIRE gris-bleu (2026-07-27) : meme axe bleute que le fond et la
     piste, un cran plus soutenu pour se detacher d'une carte blanche. L'accent reste
     reserve aux actions principales, ce bouton-ci ne doit jamais en porter. */
  --ds-btn-soft-bg: #EDF1F7;          /* fond du bouton secondaire */
  --ds-btn-soft-bg-h: #E3E9F3;        /* le meme, survole */
  --ds-btn-soft-line: #D8DFEA;        /* son contour, plus marque que --ds-line */
  --ds-btn-soft-txt: #3D4451;         /* son texte, foncé mais moins que --ds-text */
  /* ---- Ecran compact du calendrier (2026-07-31) ----
     Les memes roles que sur le theme sombre, en surfaces pleines : sur une carte
     blanche, un voile translucide vert ou rouge vire au gris sale. */
  --c2-ok-bg: #E9F6EF;                /* encadre d'etat FAVORABLE */
  --c2-ok-line: #C2E5D3;
  --c2-ko-bg: #FCEDEB;                /* encadre d'etat DEFAVORABLE */
  --c2-ko-line: #F3CDC7;
  --c2-ac-bg: var(--ds-accent-soft-bg); /* pastille d'etat A LA LIMITE (quota atteint) */
  --c2-rail: #C7D0DE;                 /* rail d'interrupteur / point de refus disponible */
  --c2-knob: var(--ds-outline);      /* pastille mobile de l'interrupteur */
  /* ---- Formes ---- */
  --ds-radius-card: 22px;
  --ds-radius-tile: 15px;
  --ds-radius-btn: 14px;
  --ds-radius-pill: 999px;
  /* ---- Ombres (jamais de bordure sur une carte) ---- */
  --ds-shadow: 0 1px 3px rgba(30,45,80,.07), 0 12px 26px rgba(30,45,80,.11);
  --ds-shadow-tile: 0 1px 2px rgba(30,45,80,.06), 0 4px 10px rgba(30,45,80,.07);
  /* ---- Typographie arrondie (aucune police externe : que du systeme) ---- */
  --ds-font: ui-rounded, "SF Pro Rounded", "Nunito", system-ui, -apple-system, sans-serif;

  /* ---- Couleurs des icones de la vitrine a trophees ----
     Lues par js/emblems.js sous la forme `var(--ic-xxx, <ancienne valeur>)`.
     Les valeurs ci-dessous sont EXACTEMENT celles d'avant : le theme sombre et la
     page de controle des emblemes sont donc inchanges au pixel. */
  --ic-major: #f2c14e;
  --ic-gs: #c8891a;
  --ic-titre: #d8dde6;
  --ic-mvp: #ffb02e;
  --ic-evp: #a8c4e8;
  --ic-top20: #f2c14e;
  --ic-moment: #ff7a59;
  --ic-award: #f2c14e;

  /* ---- Socles, plaques et fonds neutres des trophees (lot 0, 2026-07-27) ----
     Lus par js/emblems.js sous la forme `var(--tr-xxx, <ancienne valeur>)`, comme les
     `--ic-*` ci-dessus. Ce ne sont PAS les couleurs propres d'un trophee (l'or du
     Major, l'argent d'une coupe, le bleu de l'EVP restent ou ils sont) : ce sont les
     SURFACES qui posent le dessin — socle, plaque, bloc de tige, fond d'ecusson,
     disque du globe, ombre portee, point creuse du marqueur d'organisateur.
     Les valeurs ci-dessous sont EXACTEMENT celles d'avant : le theme sombre, la fiche
     joueur, l'ecran de fin, le palmares et verif-emblemes.html sont donc inchanges au
     pixel. Seul `html.theme-clair` les redefinit, plus bas. */
  --tr-socle: #242430;
  --tr-plaque: #33333f;
  --tr-plaque-2: #3a3a46;
  --tr-badge-fond: #2f3a4a;
  --tr-badge-queue: #5b6b82;
  --tr-globe: #26406e;
  --tr-ombre: #000000;
  --tr-point: #0d0d0f;
}

/* ---------------------------------------------------------------------------
   COMPOSANTS REUTILISABLES
   Definis a partir des seuls jetons ci-dessus, et donc reutilisables tels quels
   par les ecrans qui seront repris ensuite. Ils ne s'appliquent qu'a l'interieur
   du theme clair : poses sur un ecran sombre ils resteraient inertes.
   --------------------------------------------------------------------------- */

/* Carte flottante : blanc, coins tres arrondis, ombre douce, AUCUNE bordure. */
html.theme-clair .ds-card {
  background: var(--ds-card);
  border: 0;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow);
  padding: 16px 18px;
}

/* Tuile-stat : petite carte blanche, ombre plus legere. */
html.theme-clair .ds-tile {
  background: var(--ds-card);
  border: 0;
  border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile);
  padding: 10px 12px;
}
/* Variante surlignee, pour la statistique vedette d'un ecran. */
html.theme-clair .ds-tile.gold {
  background: var(--ds-accent-soft-bg);
  color: var(--ds-accent-deep);
  box-shadow: none;
}

/* Bandeau de titre (« eyebrow ») : petites capitales espacees, grises, avec la
   place d'une petite icone ou d'un emoji en tete. */
html.theme-clair .ds-eyebrow {
  display: flex; align-items: center; gap: 6px;
  font-size: .72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 1.3px;
  color: var(--ds-text-dim);
}

/* Jauge : piste claire, remplissage arrondi a degrade. */
html.theme-clair .ds-gauge { height: 8px; background: var(--ds-track); border-radius: var(--ds-radius-pill); overflow: hidden; }
html.theme-clair .ds-gauge > * { height: 100%; border-radius: var(--ds-radius-pill);
  background: linear-gradient(90deg, var(--ds-fill-1), var(--ds-fill-2)); }

/* Bouton principal : arrondi, degrade dore, texte fonce lisible. */
html.theme-clair .ds-btn {
  border: 0; border-radius: var(--ds-radius-btn);
  background: linear-gradient(180deg, var(--ds-btn-1), var(--ds-btn-2));
  color: var(--ds-btn-txt); font-weight: 700;
  box-shadow: var(--ds-btn-shadow);
}

/* Pastille d'etiquette (rang, tier…) : fond dore clair, texte dore fonce. */
html.theme-clair .ds-pill {
  display: inline-flex; align-items: center;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border: 0; border-radius: var(--ds-radius-pill);
  padding: 2px 10px; font-size: .72rem; font-weight: 700;
}

/* ---------------------------------------------------------------------------
   APPLICATION AU SEUL ECRAN JOUEUR PRINCIPAL
   1) REMAPPAGE des variables historiques sur les jetons du theme. C'est ce qui
      fait basculer d'un coup l'en-tete et tout le corps de saison, puisque le
      jeu n'ecrit presque jamais une couleur en dur.
   --------------------------------------------------------------------------- */
html.theme-clair {
  --bg: var(--ds-bg-1);
  --bg-2: var(--ds-card);
  --bg-3: var(--ds-track);
  --bg-card: var(--ds-card);
  --line: var(--ds-line);
  --txt: var(--ds-text);
  --txt-dim: var(--ds-text-dim);
  --txt-faint: var(--ds-text-faint);
  --accent: var(--ds-accent);
  /* `--accent-2` servait de variante PLUS CLAIRE de l'accent sur fond sombre ; sur
     fond blanc la variante lisible est la plus FONCEE : c'est le dore profond. */
  --accent-2: var(--ds-accent-deep);
  --accent-dim: var(--ds-accent-dim);
  --good: var(--ds-good);
  --bad: var(--ds-bad);
  --info: var(--ds-info);
  --radius: var(--ds-radius-card);

  /* Icones de la vitrine : tout passe au dore du theme, SAUF l'EVP qui garde son
     bleu (seule exception voulue, pour rester distinct du MVP). Aucun DESSIN n'est
     modifie — seule la couleur suit le theme. */
  --ic-major: var(--ds-accent);
  --ic-gs: var(--ds-accent);
  --ic-titre: var(--ds-accent);
  --ic-mvp: var(--ds-accent);
  --ic-top20: var(--ds-accent);
  --ic-award: var(--ds-accent);
  /* --ic-evp et --ic-moment : volontairement non redefinis. */

  /* SOCLES ET PLAQUES DES TROPHEES (lot 0 de la refonte visuelle, 2026-07-27).
     Ces surfaces etaient calculees pour un fond presque noir : posees sur la carte
     blanche, elles perforaient le dessin en pastilles gris fonce (visible dans le
     tableau des resultats et sur les cartes de titre). Elles passent ici sur une
     ARDOISE CLAIRE de la meme famille bleutee que le reste de la palette — entre
     `--ds-text-faint` (#8D95A5) et `--ds-track` (#E7ECF4) —, du plus fonce (le socle,
     qui doit garder l'assise) au plus clair (les plaques). Aucune teinte nouvelle :
     meme axe bleu-ardoise, meme sobriete.
     L'OR, l'ARGENT et les couleurs de famille ne sont PAS touches : un trophee garde
     exactement sa couleur propre, seule la surface qui le porte s'eclaircit. */
  --tr-socle: #A7B2C4;        /* socle des coupes : ardoise moyenne, garde l'assise */
  --tr-plaque: #BCC5D4;       /* plaque de base, un cran plus clair que le socle */
  --tr-plaque-2: #CCD3E0;     /* bloc de tige / corps de l'ecran du trophee Amateur */
  /* Ecusson EVP : ardoise BLEUTEE plutot que grise — assez soutenue pour que les deux
     chevrons et le contour, traces dans le bleu clair `--ic-evp` (#a8c4e8, volontairement
     non remappe), restent lisibles. Un fond quasi blanc les ferait disparaitre. */
  --tr-badge-fond: #6F849F;
  --tr-badge-queue: #9FB0C6;
  --tr-globe: #BFD2EE;        /* disque EWC : bleu pale, les meridiens restent vifs */
  --tr-ombre: #8D95A5;        /* ombre portee du lingot : gris doux, jamais du noir */
  --tr-point: #FFFFFF;        /* point creuse du marqueur : clair, il ne fait plus tache */

  background: var(--ds-bg-2);          /* debord de defilement (rebond iOS) */
}

/* Ombres portees des emblemes et trophees : les deux filtres d'origine sont des noirs
   a 45-50 %, calcules pour detacher un dessin d'un fond presque noir. Sur une carte
   blanche ils deposent un halo sale autour de chaque blason. Meme role, meme discretion,
   transposes sur le bleu-ardoise des ombres du theme (`--ds-shadow`). */
html.theme-clair .emb { filter: drop-shadow(0 1px 2px rgba(30, 45, 80, .22)); }
html.theme-clair .res-trophy .trophy { filter: drop-shadow(0 1px 1px rgba(30, 45, 80, .25)); }

/* Fond : degrade doux + fine texture diagonale par-dessus. La texture est posee en
   pseudo-element fixe pour ne jamais defiler ni intercepter un clic. */
html.theme-clair body {
  background: var(--ds-bg) fixed;
  color: var(--ds-text);
  font-family: var(--ds-font);
}
html.theme-clair body::before {
  content: ""; position: fixed; inset: 0; z-index: 0;
  background: var(--ds-texture); pointer-events: none;
}
html.theme-clair #app { position: relative; z-index: 1; }

/* =============================================================================
   EN-TETE — QUATRE BLOCS QUI FLOTTENT SEPAREMENT SUR LE FOND (2026-07-27)
   -----------------------------------------------------------------------------
   L'en-tete etait une GRANDE CARTE BLANCHE unique qui enfermait tout (« grande
   bulle »). Elle est supprimee : `.hud` n'est plus qu'un empilement TRANSPARENT,
   sans fond, sans ombre, sans bordure, et les quatre blocs qu'il contient portent
   chacun leur propre forme, posee sur le fond bleu doux :
     1. `.hud-pill`   pastille d'identite (capsule) : drapeau, pseudo, age/saison,
                      tier, organisation et RANG VRS MONDIAL ;
     2. `.hud-tiles`  rangee de tuiles-stats distinctes (Niveau vedette « ⚡ N »,
                      Note, Fortune, et l'ACCES A LA FICHE en presse-papiers) ;
     3. `.hud-vrs`    l'encadre d'objectif regional, pastille posee sur le fond
                      (il portait aussi la carte « Palmares », deplacee dans la
                      FICHE JOUEUR le 2026-07-27 pour aerer l'ecran principal) ;
     4. `.hud-gauges` les jauges, DIRECTEMENT sur le fond — aucune carte.
   `position: static` : l'en-tete n'est plus colle en haut. Une feuille collante
   n'avait de sens que tant qu'elle etait opaque et d'un seul tenant ; des blocs
   transparents laisseraient defiler le texte de la saison DESSOUS. Ils defilent
   donc avec la page, comme sur la maquette de reference.
   Rien de tout cela ne touche au CONTENU : memes valeurs, memes libelles, memes
   icones, memes couleurs, meme ordre. Seuls les conteneurs changent. */
html.theme-clair .hud {
  position: static;
  background: none; box-shadow: none; border: 0; border-radius: 0;
  backdrop-filter: none;
  /* RESPIRATION (2026-07-27) : 16 px suffisaient tant qu'une carte pleine — le palmares
     — fermait l'en-tete par le bas. Sans elle, les jauges finissent l'en-tete a nu sur
     le fond et se collaient visuellement au bandeau de la section de saison qui suit.
     30 px separent donc franchement l'en-tete du contenu, comme sur la maquette. */
  padding: 0; margin: 0 0 30px;
}

/* --- 1. Pastille d'identite : drapeau + pseudo + age/saison + tier + organisation --- */
html.theme-clair .hud-top { display: flex; align-items: flex-start; gap: 8px; }
html.theme-clair .hud-pill {
  background: var(--ds-card); border-radius: var(--ds-radius-pill);
  box-shadow: var(--ds-shadow-tile); padding: 10px 15px;
}
html.theme-clair .hud-pill .hud-name { font-size: 1rem; font-weight: 800; color: var(--ds-text); }
html.theme-clair .hud-pill .hud-age { font-size: .78rem; font-weight: 600; color: var(--ds-text-dim); }
/* Separateur « · » devant l'age et devant le blason (2026-07-28) : la pastille se lit
   « Dio · 29 ans · [blason] Team Vitality · VRS #12 ». Il est dessine en `::before`,
   comme celui du rang VRS — c'est une ponctuation, elle n'a pas a etre lue par un
   lecteur d'ecran ni copiee avec la valeur. */
html.theme-clair .hud-pill .hud-age::before,
html.theme-clair .hud-pill .hud-emb::before {
  content: "·"; margin: 0 6px 0 2px; color: var(--ds-text-dim); opacity: .55; font-weight: 400;
}
/* `display: contents` : le conteneur d'identite d'organisation ne forme PLUS de boite,
   ses trois enfants (blason, nom, rang VRS) deviennent des elements directs de la
   pastille. C'est le point cle de la mise en page a une ligne — avec un flex IMBRIQUE,
   le bloc entier retrecissait d'un bloc et finissait par pousser le rang VRS hors de la
   capsule. A plat, la repartition du manque de place se decide element par element :
     · blason et rang VRS  -> `flex: 0 0 auto`, jamais reduits, toujours visibles ;
     · nom d'equipe        -> retrecit EN PREMIER (`flex-shrink` tres eleve) puis se
                              tronque en « … » ;
     · pseudo              -> n'est abrege qu'une fois le nom d'equipe replie a zero.
   Le rapport de `flex-shrink` entre les deux (10000 contre 1) n'est pas decoratif :
   le manque de place se repartit au PRORATA, donc un rapport modeste laissait encore
   une fraction de pixel au pseudo — et une demi-pixel suffit a declencher son « … »,
   qui mange alors deux caracteres entiers (« nova7 » lu « nov… », constate sur la
   planche de captures). A 10000 contre 1, la part du pseudo est inferieure au
   centieme de pixel tant que le nom d'equipe a la moindre marge.
   Le conteneur reste dans le document (classe et identifiant inchanges) : le theme
   sombre, la fiche et les controles automatises le retrouvent tel quel. */
html.theme-clair .hud-team { display: contents; }
html.theme-clair .hud-pill .hud-emb { flex: 0 0 auto; display: inline-flex; align-items: center; }
html.theme-clair .hud-tier {
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  font-size: .62rem; font-weight: 800; padding: 3px 8px;
  border-radius: var(--ds-radius-pill);
}
/* NOM D'EQUIPE : seul element de la pastille qui se tronque proprement en « … »
   (2026-07-28). Il porte le nom complet en infobulle, rien n'est donc perdu. */
html.theme-clair .hud-team-nom {
  font-size: .84rem; font-weight: 800; color: var(--ds-accent-deep);
  flex: 0 10000 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* RANG VRS MONDIAL, a la suite du nom de l'organisation (2026-07-27) — il occupait la
   quatrieme tuile-stat, remplacee par l'acces a la fiche. Separateur « · » dessine en
   `::before` : c'est une ponctuation, elle n'a pas a etre lue ni copiee avec le rang.
   Insecable, il ne se coupe donc jamais entre le mot et le nombre ; s'il manque de
   place, c'est le bloc d'identite entier qui passe a la ligne suivante de la capsule. */
html.theme-clair .hud-pill .hud-vrs-rang {
  flex: 0 0 auto;                    /* toujours visible : il ne cede jamais sa place */
  font-size: .78rem; font-weight: 700; color: var(--ds-text-dim);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
html.theme-clair .hud-pill .hud-vrs-rang::before { content: "·"; margin: 0 5px 0 3px; color: var(--ds-text-dim); opacity: .55; }
/* Le mot « VRS » reste attenue, le NUMERO passe en dore fonce : deux niveaux de lecture
   pour un meme bloc, comme le rang l'etait deja face a ses points. */
html.theme-clair .hud-pill .hud-vrs-n { color: var(--ds-accent-deep); font-weight: 800; }
html.theme-clair .hud-team-sub { font-size: .76rem; color: var(--ds-text-dim); }

/* --- 2. Rangee de tuiles-stats : petites cartes arrondies DISTINCTES ---
   `display/flex-wrap/align-items` sont REPETES ici a dessein : l'element porte aussi la
   classe historique `.hud-meta` (que lisent la fiche et les controles), dont la regle,
   plus bas dans le fichier, imposerait `flex-wrap: wrap` et `align-items: center` — les
   tuiles se replieraient et n'auraient plus la meme hauteur. */
html.theme-clair .hud-tiles {
  display: flex; flex-wrap: nowrap; align-items: stretch;
  gap: 8px; margin: 12px 0 0;
}
/* TUILES COMPACTES (2026-07-27) : les libelles de tuile (« NIVEAU », « NOTE »,
   « FORTUNE ») ont ete retires, les tuiles n'ont donc plus qu'UNE SEULE ligne a porter.
   Le contenu est CENTRE sur les deux axes et le rembourrage vertical est ramene de
   11/9 px a 10 px, avec une hauteur plancher commune (`min-height`) : les quatre tuiles
   gardent exactement la meme silhouette, quelle que soit la hauteur de ce qu'elles
   montrent (un nombre, des etoiles, une icone). */
html.theme-clair .hud-tile {
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); padding: 10px 5px;
  justify-content: center; min-height: 44px;
}
/* Tuile VEDETTE : la note de niveau, seule tuile doree de la rangee. */
html.theme-clair .hud-tile.gold { background: var(--ds-accent-soft-bg); box-shadow: none; }
html.theme-clair .hud-tile .ht-v { font-size: .95rem; color: var(--ds-text); }
html.theme-clair .hud-tile .ht-sub { color: var(--ds-text-dim); }
html.theme-clair .hud-tile .ht-k { font-size: .58rem; font-weight: 800; color: var(--ds-text-dim); }
html.theme-clair .hud-tile.gold .ht-k { color: var(--ds-accent-ink); }
/* Niveau : l'eclair et le nombre se lisent SUR UNE LIGNE, « ⚡ 100 ». La tuile reste une
   colonne (comme ses voisines) ; c'est son contenu qui s'aligne en ligne. */
html.theme-clair .hud-tile-niv { flex-direction: row; align-items: center; gap: 5px; }
html.theme-clair .hud-tile-niv .ht-ico { font-size: .92rem; line-height: 1; }
html.theme-clair .hud-tile .niveau { gap: 1px; color: inherit; }
html.theme-clair .hud-tile .niv-note { font-size: 1.05rem; color: var(--ds-accent-deep); }
html.theme-clair .hud-tile-note .stars { letter-spacing: .5px; }
html.theme-clair .hud-tile-note .stars .star { font-size: .74rem; }
/* Fortune : meme bloc `.hud-gains` (et son infobulle), le montant seul dans la tuile. */
html.theme-clair .hud-tile .hud-gains { display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: inherit; }
html.theme-clair .hud-tile .hg-val { font-size: .95rem; color: var(--ds-good); }
/* ACCES A LA FICHE : la tuile est un vrai <button>, remis a plat (aucune bordure, aucun
   fond de bouton) pour porter la meme carte que ses trois voisines. Elle ne contient
   qu'une icone, en or du theme via `currentColor`, sans aucun texte. */
html.theme-clair .hud-tile-fiche {
  border: 0; font: inherit; cursor: pointer; -webkit-appearance: none; appearance: none;
  color: var(--ds-accent-deep); align-items: center;
  transition: box-shadow .15s ease, transform .15s ease;
}
html.theme-clair .hud-tile-fiche .ico-fiche { display: block; }
html.theme-clair .hud-tile-fiche:hover { box-shadow: var(--ds-shadow); }
html.theme-clair .hud-tile-fiche:active { transform: scale(.96); }
html.theme-clair .hud-tile-fiche:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  html.theme-clair .hud-tile-fiche { transition: none; }
  html.theme-clair .hud-tile-fiche:active { transform: none; }
}

/* --- 3. Encadre d'objectif regional, pastille posee sur le fond ---
   Ce bloc portait aussi la CARTE « PALMARES ». Le palmares a ete deplace dans la FICHE
   JOUEUR le 2026-07-27 (cf. `.fiche-card` plus haut) : l'ecran principal se limite
   desormais a l'identite, aux tuiles-stats et aux jauges, et respire d'autant. Il ne
   reste donc ici que l'objectif — quand il y en a un, sinon le conteneur se masque. */
html.theme-clair .hud-vrs { display: block; margin: 13px 0 0; }

/* --- 4. Jauges : sur le fond, hors de toute carte --- */
html.theme-clair .hud-gauges { margin: 15px 0 0; padding: 0 3px; gap: 11px; }

/* Drapeau du joueur, juste avant le pseudo. */
.hud-flag { margin-right: 6px; }
.hud-flag .flagico { font-size: 1.05rem; line-height: 1; }
.hud-flag .flagsvg { width: 20px; height: 14px; vertical-align: -2px; border-radius: 2px; }
html.theme-clair .hud-name { color: var(--ds-text); }
/* Note de niveau : chiffres a l'accent, en dore FONCE pour rester parfaitement
   lisibles sur blanc (`--accent-2` est deja remappe, ceci ne fait que le rendre
   explicite pour les valeurs qui portent le sens). Dans la tuile VEDETTE doree,
   la regle plus specifique du bloc « tuiles-stats » prend le relais. */
html.theme-clair .niv-note { color: var(--ds-accent-deep); }
html.theme-clair .hg-val { color: var(--ds-good); }
/* Encadre d'objectif : la pastille doree claire du theme, posee SUR LE FOND,
   detachee de la carte du palmares qui la precede. */
html.theme-clair .hud-vrs-obj {
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border: 0; border-radius: var(--ds-radius-btn);
  margin-top: 10px; padding: 9px 14px;
}
/* Vitrine a trophees — MISE EN PAGE.
   Le decoupage voulu est fixe : ligne 1 = Major / Grand Slam / MVP / EVP, ligne 2 =
   titres / Top 20 / Awards (le saut dur `.hp-br` s'en charge). Encore faut-il que le
   premier groupe TIENNE sur une ligne a 390 px : avec l'ecartement d'origine (14 px)
   et une carriere bien remplie il mesurait 365 px pour 358 disponibles, et l'EVP
   tombait SEUL sur une ligne intermediaire — exactement le compteur orphelin qu'on ne
   veut pas. L'ecartement et le libelle sont donc resserres ici, ce qui ramene le
   groupe le plus large a ~346 px et laisse de la marge pour une police plus large.
   Mesure faite sur la carriere la plus chargee du jeu d'etats de reference
   (7 Majors, 19 MVP, 96 EVP, 25 titres, 17 Top 20, 9 Awards).
   La FICHE JOUEUR, qui utilise la meme vitrine sur un ecran encore sombre, n'est pas
   concernee : elle garde son ecartement et sa taille d'origine. */
html.theme-clair .hud-palm { gap: 5px 8px; }
html.theme-clair .hud-palm .hp-lab { font-size: .72rem; }
/* Les compteurs a zero restent COLORES (le theme les veut lisibles en permanence) ;
   seul le texte reste discret. */
html.theme-clair .hp-item.zero { opacity: 1; }
html.theme-clair .hp-item.zero .hp-n,
html.theme-clair .hp-item.zero .hp-lab,
html.theme-clair .hp-item.zero .hp-x { color: var(--ds-text-faint); }
html.theme-clair .hp-n { color: var(--ds-text); }
html.theme-clair .hp-lab { color: var(--ds-text-dim); }
/* Etoiles de niveau : piste claire pour les vides, dore pour les pleines. */
html.theme-clair .stars .star { color: var(--ds-track); }
html.theme-clair .stars .star.on { color: var(--ds-accent); }

/* --- Jauges de l'en-tete : composant `.ds-gauge` applique aux jauges en place --- */
html.theme-clair .gauge .g-track { height: 8px; background: var(--ds-track); border-radius: var(--ds-radius-pill); }
html.theme-clair .gauge .g-fill { border-radius: var(--ds-radius-pill); }
html.theme-clair .g-form .g-fill { background: linear-gradient(90deg, var(--ds-info), var(--ds-info-light)); }
html.theme-clair .g-stat .g-fill { background: linear-gradient(90deg, var(--ds-fill-1), var(--ds-fill-2)); }
html.theme-clair .gauge .g-label { color: var(--ds-text-dim); }

/* --- Corps de saison : chaque bloc devient une carte flottante --- */
html.theme-clair .narr,
html.theme-clair .offer,
html.theme-clair .choice-btn {
  background: var(--ds-card);
  border: 0;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow);
}
html.theme-clair .narr { border-left: 0; padding: 16px 18px; }
html.theme-clair .choice-btn { padding: 15px 18px; }
html.theme-clair .choice-btn:hover { box-shadow: 0 1px 3px rgba(30,45,80,.09), 0 14px 30px rgba(30,45,80,.15); }
/* La couleur de ton d'un bloc narratif passe du filet lateral a une pastille de
   couleur en tete de carte : meme information, sans bordure. */
html.theme-clair .narr::before {
  content: ""; display: block; width: 34px; height: 4px; border-radius: var(--ds-radius-pill);
  background: var(--ds-accent); margin-bottom: 10px;
}
html.theme-clair .narr.soft::before { background: var(--ds-info); }
html.theme-clair .narr.good::before { background: var(--ds-good); }
html.theme-clair .narr.bad::before { background: var(--ds-bad); }

/* Tuiles-stat du bilan. */
html.theme-clair .stat-box {
  background: var(--ds-card); border: 0;
  border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair .stat-bar { background: var(--ds-track); border-radius: var(--ds-radius-pill); height: 6px; }
html.theme-clair .stat-bar > div { background: linear-gradient(90deg, var(--ds-fill-1), var(--ds-fill-2)); border-radius: var(--ds-radius-pill); }
/* Statistique vedette : la tuile surlignee doree. */
html.theme-clair .big-metric {
  background: var(--ds-accent-soft-bg); border: 0;
  border-radius: var(--ds-radius-tile); box-shadow: none;
}
html.theme-clair .big-metric .m-val { color: var(--ds-accent-deep); }
html.theme-clair .big-metric .m-lab { color: var(--ds-accent-deep); opacity: .8; }

/* Bandeaux de titre du corps de saison. */
html.theme-clair .phase-tag,
html.theme-clair .section-label { color: var(--ds-text-dim); font-weight: 800; }

/* Boutons du corps de saison : le composant bouton principal. */
html.theme-clair .btn { border-radius: var(--ds-radius-btn); }
html.theme-clair .btn-primary {
  background: linear-gradient(180deg, var(--ds-btn-1), var(--ds-btn-2));
  color: var(--ds-btn-txt); border-color: transparent;
  box-shadow: var(--ds-btn-shadow);
}
html.theme-clair .btn-ghost { background: rgba(255,255,255,.72); color: var(--ds-text-dim); border-color: transparent; }
html.theme-clair .btn-ghost:hover { color: var(--ds-text); border-color: transparent; }

/* Pastilles et etiquettes du corps de saison. */
html.theme-clair .offer .tier-badge,
html.theme-clair .award,
html.theme-clair .mvp-pill.mvp,
html.theme-clair .rec-pill.or {
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border: 0; border-radius: var(--ds-radius-pill);
}
html.theme-clair .mvp-pill,
html.theme-clair .rec-pill {
  background: var(--ds-track); color: var(--ds-text-dim);
  border: 0; border-radius: var(--ds-radius-pill);
}
/* Pastille de CARRIERE : elle doit rester distincte d'un resultat de la saison.
   Elle garde son fond froid et ses angles moins ronds, transposes sur fond clair. */
html.theme-clair .award.carriere {
  background: rgba(36, 42, 58, .05); color: var(--ds-text-dim);
  border-radius: 9px; border: 0;
}
html.theme-clair .fx { background: var(--ds-track); }

/* Filets de separation et listes. */
html.theme-clair .trow,
html.theme-clair .list-line { border-bottom-color: var(--ds-line); }

/* ---------------------------------------------------------------------------
   COULEURS ECRITES EN DUR — TRANSPOSITION SUR FOND CLAIR
   Le remappage des variables plus haut suffit pour l'immense majorite du jeu.
   Restent les quelques blocs qui portaient une couleur ECRITE EN DUR, calculee
   pour un fond sombre : ambres tres pales, verts pastel, fonds presque noirs.
   Poses tels quels sur du blanc ils devenaient illisibles (« 130 jours » en creme
   sur blanc) ou invisibles (fond #241a10 devenu un rectangle noir).
   Chacun est ici transpose sur le JETON de meme role dans la palette claire : la
   teinte et le sens sont conserves (ambre = signal chaud, vert = benefice, bleu =
   information), seule la valeur change. Rien n'est ajoute ni retire a l'affichage.
   Comme tout ce bloc, ces regles ne valent que sous `html.theme-clair`, donc sur le
   seul ecran joueur principal : les memes classes restent intactes ailleurs.
   --------------------------------------------------------------------------- */

/* --- Fonds ambres (signal chaud) --- */
html.theme-clair .titlecard,
html.theme-clair .titlecard.major,
html.theme-clair .gscard,
html.theme-clair .gs-prog.chaud,
html.theme-clair .gs-banner,
html.theme-clair .rec-banner,
html.theme-clair .rec-row.moi,
html.theme-clair .offer-risque,
html.theme-clair .risque-ligne,
html.theme-clair .acad-exit,
html.theme-clair .val-badge,
html.theme-clair .avant-badge,
html.theme-clair .jetons-gain,
html.theme-clair .nature-badge.intl,
html.theme-clair .minitab.on,
html.theme-clair .tab.on {
  background: var(--ds-accent-soft-bg);
  color: var(--ds-accent-deep);
  border-color: var(--ds-accent-dim);
}
/* Les deux cartes les plus rares gardent leur rang : ombre de carte flottante et
   cerclage dore franc pour le sacre majeur et la conquete du Grand Slam. */
html.theme-clair .titlecard { border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile); }
html.theme-clair .titlecard.major,
html.theme-clair .gscard { border-color: var(--ds-accent); border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile); }

/* --- Fonds verts (benefice) et bleus (information) --- */
html.theme-clair .reconv-banner,
html.theme-clair .nature-badge.interne,
html.theme-clair .histo-via.promo,
html.theme-clair .quest-row.done { background: var(--ds-good-soft-bg); color: var(--ds-good-ink); border-color: var(--ds-good-soft-line); }
html.theme-clair .nature-badge.acad,
html.theme-clair .defi-neutral { background: var(--ds-info-soft-bg); color: var(--ds-info-ink); border-color: var(--ds-info-soft-line); }
html.theme-clair .perk-row.equipped { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent-dim); }

/* --- Textes ambres tres pales --- */
html.theme-clair .gs-h,
html.theme-clair .gs-name,
html.theme-clair .gs-titres li,
html.theme-clair .gs-prog .gsp-alerte,
html.theme-clair .gs-banner,
html.theme-clair .gs-banner strong,
html.theme-clair .tshow-group.grandslam .tshow-fam,
html.theme-clair .pchip-incontournable,
html.theme-clair .chg-v { color: var(--ds-accent-deep); }

/* --- Textes verts pastel (benefice, gain de repos) --- */
html.theme-clair .rg-up,
html.theme-clair .chg-mention.chg-leger,
html.theme-clair .chg-cause.chg-bon,
html.theme-clair .cj-gain,
html.theme-clair .ct-repos,
html.theme-clair .cal-coupure.ok,
html.theme-clair .cal-recap .cr-t { color: var(--ds-good); }

/* --- Textes d'alerte et neutres --- */
html.theme-clair .chg-mention.chg-lourd,
html.theme-clair .cal-coupure.ko { color: var(--ds-warn-ink); }
html.theme-clair .chg-mention.chg-neutre { color: var(--ds-text-dim); }
html.theme-clair .pchip-optionnel { color: var(--ds-info); }

/* --- Compteurs de charge : de vraies tuiles-stat --- */
html.theme-clair .chg-l {
  background: var(--ds-card); border: 0;
  border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair .chg-k { color: var(--ds-text-dim); opacity: 1; }
html.theme-clair .cal-coupure { border-color: var(--ds-line); background: var(--ds-card); }

/* --- Derniers ajustements de l'ecran joueur en theme clair --- */
/* Le tableau des resultats de la saison flottait a nu sur le fond bleu : il devient
   lui aussi une carte blanche, comme les blocs qui l'entourent. */
html.theme-clair .table-scroll {
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 6px 10px; margin: 10px 0;
}
/* Les deux statistiques de poste de l'en-tete gardent DEUX teintes distinctes, comme
   sur le theme sombre (l'une ambre, l'autre violette) : c'est ce qui permet de les
   suivre d'un coup d'oeil quand elles bougent. Seules les valeurs sont transposees
   pour rester lisibles sur blanc. */
html.theme-clair .g-stat2 .g-fill { background: linear-gradient(90deg, var(--ds-fill-alt-1), var(--ds-fill-alt-2)); }
/* Bloc « moment d'anthologie » : meme signal ambre, transpose. */
html.theme-clair .anthologie {
  background: var(--ds-accent-soft-bg); border: 0; border-left: 3px solid var(--ds-accent);
  border-radius: var(--ds-radius-tile);
}
html.theme-clair .anthologie .ant-h { color: var(--ds-accent-deep); }
html.theme-clair .anthologie.rate { background: var(--ds-bad-soft-bg); border-left-color: var(--ds-bad); }
html.theme-clair .anthologie.rate .ant-h { color: var(--ds-bad-ink); }

/* Kill feed des moments d'anthologie : le bandeau noir translucide, pense pour un
   fond sombre, virait au kaki sur la carte creme. Meme dessin, meme disposition,
   transposes : bandeau blanc, filet dore a gauche, auteur en dore fonce, victime en
   texte attenue. Aucune ligne n'est ajoutee ni retiree. */
html.theme-clair .kf-line {
  background: var(--ds-card);
  border: 1px solid var(--ds-accent-dim); border-left: 2px solid var(--ds-accent);
}
html.theme-clair .kf-line .kf-a { color: var(--ds-accent-deep); }
html.theme-clair .kf-line .kf-w { color: var(--ds-accent); }
html.theme-clair .kf-line .kf-v { color: var(--ds-text-dim); }
html.theme-clair .kf-cap { color: var(--ds-text-dim); }

/* =============================================================================
   LOT 1 DE LA REFONTE VISUELLE — ACCUEIL ET DEFI DU JOUR (2026-07-27)
   -----------------------------------------------------------------------------
   HABILLAGE SEUL. Aucun texte, aucune valeur, aucun libelle, aucune logique n'est
   touche : les deux ecrans passent au theme clair par la seule table `ECRANS_CLAIRS`
   de js/ui.js, et par les regles ci-dessous. Retirer les deux entrees de cette table
   rend les deux ecrans a leur apparence sombre d'origine — rien d'autre a defaire.

   CE QUI ETAIT DEJA LA ET SERT TEL QUEL (c'est l'interet de l'ossature commune) :
     - le FOND clair + la texture + `#app` en z-index 1 (`html.theme-clair body`,
       `body::before`, `#app`) : deja generiques, ils ne visaient pas la saison ;
     - le REMAPPAGE des variables historiques (`--txt`, `--txt-dim`, `--txt-faint`,
       `--accent`, `--accent-2`, `--bg-card`…) : le titre « DESTINY FIVE » prend donc
       le texte fonce et son « FIVE » l'or, la tagline et le disclaimer l'attenue, la
       police arrondie s'applique — sans une seule regle nouvelle ;
     - le BOUTON PRINCIPAL (`html.theme-clair .btn-primary`, degrade dore, texte
       fonce) et les CARTES narratives (`.narr`), qui servent aux etats du defi.
   NE RESTAIT DONC QUE ce que ces deux ecrans ont en propre, ci-dessous.

   PORTEE : tout ce qui modifie une apparence est SCOPE a `#screen-home` ou
   `#screen-defi`. L'ecran de saison, deja converti, n'est touche par aucune de ces
   regles — les seules regles non scopees sont l'ossature reutilisable (titre d'ecran
   et les deux composants de bouton), et l'ecran de saison n'emploie ni l'une ni
   l'autre (il n'a pas de `.screen-title` et ses boutons restent le bouton principal).
   ============================================================================= */

/* --- OSSATURE COMMUNE, REUTILISABLE PAR LES LOTS SUIVANTS ------------------- */

/* Titre d'ecran : texte fonce du theme. Present sur creation, fiche, defi,
   progression, comment ca marche et palmares — il est donc pret pour eux tous. */
html.theme-clair .screen-title { color: var(--ds-text); font-weight: 800; }

/* Bouton SECONDAIRE « carte blanche flottante » : meme silhouette qu'une tuile,
   texte fonce. Le composant `.ds-btn-card` est declare ici pour les ecrans a venir ;
   la seconde ligne l'applique aux trois boutons secondaires de l'accueil, sans avoir
   a poser une classe de plus dans le HTML. */
html.theme-clair .ds-btn-card,
html.theme-clair #screen-home .home-actions .btn-ghost {
  background: var(--ds-card); color: var(--ds-text);
  border: 0; border-radius: var(--ds-radius-btn);
  box-shadow: var(--ds-shadow-tile); font-weight: 700;
}
html.theme-clair .ds-btn-card:hover,
html.theme-clair #screen-home .home-actions .btn-ghost:hover {
  color: var(--ds-text); box-shadow: var(--ds-shadow);
}

/* Bouton DISCRET a contour leger : ni dore, ni carte — une action de retrait ou de
   retour. Meme composant pour « Reinitialiser la sauvegarde » et « Retour ». */
html.theme-clair .ds-btn-quiet,
html.theme-clair #screen-home #btn-reset,
html.theme-clair #screen-defi .create-actions .btn-ghost {
  background: transparent; color: var(--ds-text-dim);
  border: 1px solid var(--ds-line); border-radius: var(--ds-radius-btn);
  box-shadow: none; font-weight: 600;
}
html.theme-clair .ds-btn-quiet:hover,
html.theme-clair #screen-home #btn-reset:hover,
html.theme-clair #screen-defi .create-actions .btn-ghost:hover {
  color: var(--ds-text); border-color: var(--ds-line-hover); background: rgba(255,255,255,.55);
}

/* --- ACCUEIL ---------------------------------------------------------------- */

/* Ligne de sauvegarde : petite carte-pastille claire portant le blason et le texte
   attenue. `.home-hero` centre son contenu au `text-align`, un element en ligne s'y
   centre donc de lui-meme — la regle de base la laissait pleine largeur. */
html.theme-clair #screen-home .save-info {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--ds-card); border-radius: var(--ds-radius-pill);
  box-shadow: var(--ds-shadow-tile);
  padding: 7px 14px; color: var(--ds-text-dim); font-weight: 600;
}

/* Information du defi du jour : la tuile doree claire du theme. */
html.theme-clair #screen-home .defi-info {
  display: inline-block; text-align: center;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border-radius: var(--ds-radius-tile);
  padding: 9px 14px; font-weight: 600;
}

/* Le bouton de reinitialisation reste en retrait du bloc d'actions. */
html.theme-clair #screen-home #btn-reset { margin-top: 18px; }

/* --- DEFI DU JOUR ----------------------------------------------------------- */

/* Bandeau de titre : sur cet ecran il porte la DATE du defi, c'est l'accent de la
   page — il garde donc le dore profond, la ou le meme bandeau reste attenue dans le
   corps de saison (ou il n'est qu'une etiquette de phase parmi d'autres). */
html.theme-clair #screen-defi .phase-tag { color: var(--ds-accent-deep); }

/* Les trois contraintes imposees : cartes blanches arrondies, libelle attenu en
   petites capitales, valeur en gras dore profond. La bordure disparait au profit de
   l'ombre douce, comme partout ailleurs dans le theme. */
html.theme-clair #screen-defi .dchip {
  background: var(--ds-card); border: 0;
  border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile);
  padding: 9px 13px; color: var(--ds-text-dim); font-weight: 700;
}
html.theme-clair #screen-defi .dchip strong { color: var(--ds-accent-deep); font-weight: 800; }

/* ===== DEBUT ACCUEIL REFONDU =================================================
   ACCUEIL — REFONTE EN SEPT BLOCS  (2026-08-12)

   Huit cases dorees identiques ne hierarchisaient rien. Sept blocs les
   remplacent, du plus important au plus discret : la ligne de tete, la carte de
   carriere, DEUX cartes premium, quatre tuiles, la barre des mises a jour,
   « Nouvelle carriere » en pointille, les mentions.

   ⚠️ PAS UN SEUL HEXADECIMAL DANS CE BLOC, ET CE N'EST PAS UN GOUT. Tout derive
   des jetons `--ds-*`, y compris les six ecus, dont les degrades sont ecrits en
   `var(--ds-…)` dans le SVG. L'invariant g56 relit ce bloc, de son marqueur de
   DEBUT a son marqueur de FIN, et echoue sur le moindre `#rrggbb` — et aussi sur
   le moindre `rgb(` ou `rgba(`, que le filtre des autres groupes ne voit pas.
   C'est ce qui fait que l'ecran SUIT les 37 themes au lieu de les subir.

   ⚠️ LA CARTE NE SE DETACHE PAS PAR SA COULEUR, MAIS PAR SON OMBRE. Sur certains
   themes `--ds-card` et `--ds-bg-1` ne different que de 1,02:1 : une bordure
   posee la ou le theme attend une ombre disparaitrait purement et simplement.
   Toutes les surfaces d'ici portent donc `--ds-shadow` ou `--ds-shadow-tile`.

   ⚠️ L'ENCRE SUR UN APLAT D'ACCENT EST `--ds-btn-txt`, JAMAIS `--ds-on-solid` :
   du blanc sur l'or du socle ne fait que 2,4:1. Regle du projet, mesuree.
   ============================================================================= */

/* L'ecran cesse d'etre centre verticalement : il se remplit du haut vers le bas.
   ⚠️ `justify-content: center` faisait flotter la colonne au milieu ; avec sept
   blocs dont deux disparaissent quand il n'y a pas de carriere, le contenu
   sautait d'un etat a l'autre. Il est aligne en haut, et c'est l'espacement qui
   fait la respiration. */
/* ⚠️ L'ACCUEIL NE PREND PAS LA MARGE VERTICALE DE `.screen`, ET C'EST LA CAUSE
   UNIQUE DU VIDE DU BAS (2026-08-13). `.screen` pose `18px … 40px` : 58 px pris
   sur les 844, dessines pour des ecrans qui DEFILENT, ou une marge de securite en
   bas est une bonne chose. L'accueil est le seul qui doit tenir EXACTEMENT dans la
   fenetre : ces 58 px lui manquaient, et avec une carriere ils le faisaient
   defiler de 35 px des que les ecus ont grandi. Sa respiration verticale est celle
   de `.hm` (12 px en haut, 10 en bas), qui lui appartient.
   ⚠️ LA MARGE LATERALE RESTE CELLE DE `.screen` : la changer deplacerait toutes
   les cartes de l'ecran, et ce n'est pas ce qu'on corrige ici.
   ⚠️ L'ENCOCHE N'EST PAS EN JEU : elle est portee par `body`
   (`padding: env(safe-area-inset-*)`), pas par cette marge-la. */
html.theme-clair #screen-home { justify-content: flex-start; padding-top: 0; padding-bottom: 0; }
/* ⚠️ LA COLONNE PREND TOUTE LA HAUTEUR, ET C'EST CE QUI SUPPRIME LE VIDE DU BAS
   (2026-08-13). `#screen-home` fait deja 100vh, mais `.hm` s'arretait a la
   hauteur de son contenu : le bas du dernier bloc tombait a 630 px sur un ecran
   de 844, laissant 214 px de vide sous les mentions. Elle s'etire donc, et c'est
   le BLOC DU BAS qui porte `margin-top: auto` — la marge absorbe tout le mou et
   les mentions viennent se poser sur le bord bas.
   ⚠️ NI L'UN NI L'AUTRE N'EST UNE HAUTEUR FIXE : l'invariant qui interdit une
   hauteur figee sur les sept blocs (g56) reste vrai, et il le verifie bloc par
   bloc. Repartir le mou ENTRE les blocs aurait au contraire fait respirer la
   grille d'un etat a l'autre — avec carriere il ne reste que 83 px, sans carriere
   214 : les tuiles auraient change de place selon qu'on a une carriere ou non. */
/* ⚠️ ET LE MOU NE S'ENTASSE PLUS EN UN SEUL TROU (2026-08-14). Il partait tout
   entier dans la marge des mentions : l'ecran s'arretait a la barre de version et
   laissait un vide sous elle — 216 px sans carriere a 390 x 844, et 194 px avec
   carriere a 430 x 932, soit un bon quart d'un grand telephone. Les blocs qui
   peuvent respirer s'en partagent desormais la hauteur (`.hm-carte`, `.hm-duo`,
   `.hm-grille` plus bas), et l'accueil remplit la fenetre qu'il trouve, quelle
   qu'elle soit. AUCUN CONTENU N'EST INVENTE pour la remplir. */
html.theme-clair #screen-home .hm {
  display: flex; flex-direction: column; gap: 6px;
  width: 100%; max-width: 460px; margin: 0 auto; padding: 12px 14px 10px;
  text-align: left; flex: 1 1 auto;
}
/* ⚠️ LES TROIS SURFACES QUI PRENNENT LE MOU, A PARTS EGALES. `flex-grow` n'est PAS
   une hauteur fixe : l'invariant qui interdit une hauteur figee sur les blocs de
   l'accueil (g56) reste vrai, et `min-height: auto` d'un element flex les empeche
   de descendre sous leur contenu — a 390 x 844 il n'y a rien a distribuer et la
   mise en page est celle d'avant, au pixel pres.
   ⚠️ LA BANDE, LA BARRE, LA LIGNE POINTILLEE ET LES MENTIONS NE GRANDISSENT PAS :
   etirer une rangee de quatre cellules ou une barre d'une ligne ne donnerait pas
   de l'air, cela donnerait des trous a l'interieur des blocs. */
html.theme-clair #screen-home .hm-carte,
html.theme-clair #screen-home .hm-duo,
html.theme-clair #screen-home .hm-grille { flex: 1 1 auto; }

/* --- 1 · LIGNE DE TETE ------------------------------------------------------ */
html.theme-clair #screen-home .hm-tete {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
/* ⚠️ LE TITRE PERD DEUX TIERS DE SA TAILLE (2.7rem -> 1.32rem) : il occupait a lui
   seul le quart de la hauteur utile, pour une information que le joueur connait
   deja. La vedette appartient desormais a la carte de carriere. */
html.theme-clair #screen-home .hm-logo {
  font-size: 1.32rem; letter-spacing: 1.4px; margin: 0; color: var(--ds-text);
}
/* Le mot STRIKE dans le DEGRADE d'accent.
   ⚠️ LE REPLI PLEIN EST POSE EN PREMIER ET IL EST OBLIGATOIRE : sans lui, un
   navigateur sans `background-clip: text` rendrait le mot INVISIBLE. Meme patron
   que les quatre paliers de pseudo et que le score plein du Defi. */
html.theme-clair #screen-home .hm-logo span { color: var(--ds-accent-deep); }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  html.theme-clair #screen-home .hm-logo span {
    background: linear-gradient(96deg, var(--ds-accent-deep), var(--ds-accent-solid-2), var(--ds-accent));
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
/* La pastille de solde. ⚠️ Sa valeur vient de `soldeJetons()`, source unique. */
html.theme-clair #screen-home .hm-solde {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink);
  border-radius: var(--ds-radius-pill); padding: 5px 11px;
  font-size: .8rem; font-weight: 800; letter-spacing: .01em;
  box-shadow: var(--ds-shadow-tile);
}
html.theme-clair #screen-home .hm-solde:empty { display: none; }

/* ==========================================================================
   L'ETAT D'ATTENTE DE L'ACCUEIL — LA CARTE N'EST PLUS BLANCHE  (2026-08-20)

   ⚠️ `hm-attente` EST POSEE DANS LE BALISAGE, PAS A L'EXECUTION, et c'est toute
   la raison d'etre de ce bloc : au tout premier rendu, aucun script du jeu n'a
   encore tourne — ni les trente-six fichiers de donnees, ni le moteur — et la
   carte de carriere s'affichait vide, avec pour seul contenu le mot
   « Continuer ». Le proprietaire y voyait une panne. Elle porte desormais des
   barres a la place de chaque valeur ; `setupHome` retire la classe quand la
   carte est remplie, et les barres cedent la place aux vraies valeurs sans que
   rien ne se deplace.
   ⚠️ LE BOUTON EST MASQUE PAR SA COULEUR, PAS PAR SA BOITE : on ne sait pas
   encore s'il dira « Continuer » ou « Creer », et afficher l'un pour le
   remplacer par l'autre serait pire qu'une barre. Sa place, elle, est tenue.
   ⚠️ CES BARRES NE PORTENT AUCUNE VALEUR ET N'EN SUGGERENT AUCUNE.

   ⚠️ PLUS DE BARRES QUI CLIGNOTENT DEPUIS LE 2026-08-22, ET C'EST UNE DECISION,
   PAS UN OUBLI. Le balayage `ds-att` a ete retire : la carte arrive DESSINEE —
   ses places tenues d'un aplat calme, et ses TROIS JAUGES A ZERO, dessinees
   telles quelles. Un scintillement dit « ca charge » ; un dessin dit « voila ce
   qui arrive », et c'est ce que la carte doit dire. Les geometries, elles, n'ont
   pas bouge d'un pixel : rien ne se deplace quand les valeurs arrivent. */
html.theme-clair #screen-home.hm-attente .hm-solde,
html.theme-clair #screen-home.hm-attente .hm-sur,
html.theme-clair #screen-home.hm-attente .hm-pseudo,
html.theme-clair #screen-home.hm-attente .hm-meta,
html.theme-clair #screen-home.hm-attente .hm-blason,
html.theme-clair #screen-home.hm-attente .hm-jauges,
html.theme-clair #screen-home.hm-attente .hm-pan-cells,
html.theme-clair #screen-home.hm-attente .hm-continuer {
  display: block; color: transparent;
  background-image: linear-gradient(var(--ds-line), var(--ds-line));
  background-repeat: no-repeat; background-size: 100% 100%;
  border-radius: 8px; box-shadow: none; animation: none;
}
html.theme-clair #screen-home.hm-attente .hm-solde { width: 58px; height: 26px; border-radius: var(--ds-radius-pill); }
html.theme-clair #screen-home.hm-attente .hm-sur { width: 104px; height: 10px; }
html.theme-clair #screen-home.hm-attente .hm-blason { width: 34px; height: 34px; border-radius: 50%; }
html.theme-clair #screen-home.hm-attente .hm-pseudo { width: 118px; height: 16px; }
html.theme-clair #screen-home.hm-attente .hm-meta { width: 100%; height: 11px; }
/* ⚠️ LES TROIS JAUGES SONT DESSINEES A ZERO, ET ELLES LE SONT EN FOND : trois
   pistes et trois places de libelle, en six couches d'image, sur un element qui
   reste VIDE. Y poser trois vraies jauges aurait fallu connaitre le POSTE du
   joueur — les deux statistiques affichees en derivent (`UI.hudStatKeys`) —, or
   la sauvegarde n'est pas encore lue au premier rendu. On dessine donc ce qu'on
   sait (la structure, les pistes a zero) et jamais ce qu'on ignore (les deux
   libelles de poste), qui arrivent avec la donnee.
   ⚠️ ET C'EST CE QUI GARDE `g101 §101e` HONNETE : la place reste sans enfant et
   sans texte, elle est simplement PEINTE. */
html.theme-clair #screen-home.hm-attente .hm-jauges {
  width: 100%; height: 34px; border-radius: 0;
  background-image:
    linear-gradient(var(--ds-line), var(--ds-line)),
    linear-gradient(var(--ds-line), var(--ds-line)),
    linear-gradient(var(--ds-line), var(--ds-line)),
    linear-gradient(var(--ds-track), var(--ds-track)),
    linear-gradient(var(--ds-track), var(--ds-track)),
    linear-gradient(var(--ds-track), var(--ds-track));
  background-size:
    calc((100% - 20px) / 3 * .62) 8px, calc((100% - 20px) / 3 * .62) 8px, calc((100% - 20px) / 3 * .62) 8px,
    calc((100% - 20px) / 3) 7px, calc((100% - 20px) / 3) 7px, calc((100% - 20px) / 3) 7px;
  background-position: left top, center top, right top, left bottom, center bottom, right bottom;
}
html.theme-clair #screen-home.hm-attente .hm-pan-cells { width: 100%; height: 62px; }
html.theme-clair #screen-home.hm-attente .hm-continuer { width: 88px; height: 34px; border: 0; }
/* ⚠️ CES QUATRE PLACES SE CACHENT QUAND ELLES SONT VIDES — et en etat d'attente
   elles le sont TOUTES, par definition. La regle qui les cache a exactement la
   meme force que celle du dessus, et elle est ecrite plus bas dans la feuille :
   sans cette reprise, `hm-sur` et `hm-jauges` restaient a zero pixel et la carte
   redevenait un cadre a trous. Mesure : `g101` les a nommees. */
html.theme-clair #screen-home.hm-attente .hm-solde:empty,
html.theme-clair #screen-home.hm-attente .hm-sur:empty,
html.theme-clair #screen-home.hm-attente .hm-jauges:empty,
html.theme-clair #screen-home.hm-attente .hm-porte:empty { display: block; }
/* Le drapeau garde sa place sans rien affirmer d'une nationalite. */
html.theme-clair #screen-home.hm-attente .hud-flag:empty { display: inline-block; width: 20px; height: 14px; border-radius: 3px;
  background: var(--ds-line); }

/* ⚠️ LE DEVOILEMENT DE SECOURS. Si le jeu n'a pas rempli la carte au bout de
   quelques secondes — script absent, coupure au milieu du chargement —, un
   minuscule script en pied de page pose `hm-panne` sur la racine. Les barres
   s'effacent et une phrase DIT ce qui s'est passe : jamais un cadre gris
   permanent, jamais un ecran qui fait semblant de charger pour l'eternite. */
html.hm-panne #screen-home.hm-attente .hm-solde,
html.hm-panne #screen-home.hm-attente .hm-sur,
html.hm-panne #screen-home.hm-attente .hm-pseudo,
html.hm-panne #screen-home.hm-attente .hm-meta,
html.hm-panne #screen-home.hm-attente .hm-blason,
html.hm-panne #screen-home.hm-attente .hm-jauges,
html.hm-panne #screen-home.hm-attente .hm-pan-cells,
html.hm-panne #screen-home.hm-attente .hm-continuer,
html.hm-panne #screen-home.hm-attente .hud-flag:empty,
/* Les quatre places que la reprise ci-dessus a fait reapparaitre : le secours
   doit les reprendre nommement, sinon trois barres survivent a la panne. */
html.hm-panne #screen-home.hm-attente .hm-solde:empty,
html.hm-panne #screen-home.hm-attente .hm-sur:empty,
html.hm-panne #screen-home.hm-attente .hm-jauges:empty,
html.hm-panne #screen-home.hm-attente .hm-porte:empty { display: none; animation: none; }
/* ⚠️ LE PARAGRAPHE DE SECOURS NE PORTE PAS `.hm-meta`, ET C'EST DELIBERE : la
   ligne ci-dessus efface toutes les places de valeur, et `.hm-meta` en est une —
   il se serait efface lui-meme. `g101` l'a constate. */
#hm-panne { display: none; grid-area: meta; margin: 0;
  font-size: .8rem; font-weight: 700; color: var(--ds-text-dim);
  white-space: normal; text-align: left; }
html.hm-panne #hm-panne { display: block; }

/* ==========================================================================
   LES JAUGES QUI MONTENT — L'ARRIVEE DE LA CARTE DE CARRIERE   (2026-08-22)

   La carte est deja DESSINEE quand la sauvegarde arrive (bloc ci-dessus) :
   sa structure et ses trois pistes a zero sont peintes avant tout script. Ce
   bloc-ci decrit ce qui se passe A L'ARRIVEE DES DONNEES, dans cet ordre — le
   pseudo et le drapeau en fondu, la ligne de meta ensuite, les trois jauges qui
   montent jusqu'a leur valeur, et les chiffres en dernier.

   ⚠️ TOUT EST SUSPENDU A `att-pret`, POSE PAR `hmCarteCarriere` UNE FOIS LA CARTE
   REMPLIE. Sans lui, rien ne se met a zero et rien ne s'anime : un visiteur dont
   le script echoue ne voit donc jamais une carte a moitie effacee — il reste sur
   l'etat d'attente, puis sur son secours au bout de dix secondes.
   ⚠️ `att-vu` FAIT SAUTER L'ARRIVEE A SON ETAT FINAL. Personne n'attend une
   animation : au premier geste du joueur, tout est deja la.
   ⚠️ LA VALEUR VIENT DE `--w`, POSEE PAR `UI.gauge` EN MEME TEMPS QUE `width` ET
   CALCULEE UNE SEULE FOIS. Une animation ne peut pas viser une largeur ecrite en
   ligne ; elle vise la variable, et son etat final EST la largeur en ligne.
   ⚠️ AUCUN HEXADECIMAL ICI, LA PISTE PREND `--ds-track` : la maquette la donne en
   `#E7ECF3`, mais ce bloc est dans l'accueil, ou `g56 §56e` refuse toute couleur
   qui ne vienne pas d'un jeton — et `--ds-track` porte deja exactement ce role,
   sur les 37 themes. C'est la SEULE valeur de la maquette qui ait ete traduite. */
#hm-carte .att-idl { opacity: 0; }
#hm-carte.att-pret .att-idl { animation: att-appar .45s ease-out .15s forwards; }
@keyframes att-appar { to { opacity: 1; } }
#hm-carte .att-meta { opacity: 0; }
#hm-carte.att-pret .att-meta { animation: att-appar .45s ease-out .3s forwards; }
#hm-carte .att-jb { flex: 1; height: 7px; background: var(--ds-track);
  border-radius: 5px; overflow: hidden; }
#hm-carte .att-jb > .g-fill { display: block; height: 100%; border-radius: 5px; }
#hm-carte.att-pret .att-jb > .g-fill {
  animation: att-monte 1.1s cubic-bezier(.25, .8, .3, 1) forwards; }
/* ⚠️ LE ZERO EST DANS L'IMAGE DE DEPART, PAS SUR L'ELEMENT, ET IL LE FAUT : la
   jauge porte sa largeur EN LIGNE (c'est la seule chose qu'un lecteur exterieur
   puisse lire), et une declaration en ligne l'emporte sur toute regle de la
   feuille. Une ANIMATION, elle, passe devant les deux — on part donc de zero
   dans l'image, ce qui donne exactement le meme mouvement sans avoir a crier
   `!important` ni a retirer la largeur en ligne. */
@keyframes att-monte { from { width: 0; } to { width: var(--w); } }
#hm-carte .att-jv { opacity: 0; }
#hm-carte.att-pret .att-jv { animation: att-appar .4s ease-out .9s forwards; }
/* ⚠️ L'ETAT FINAL, ECRIT UNE SEULE FOIS, ET DEUX CHEMINS Y MENENT : le geste du
   joueur (`att-vu`) et le reglage « mouvement reduit ». Les deux disent la meme
   chose — tout est arrive — et aucun des deux ne doit laisser une jauge a zero. */
#hm-carte.att-vu .att-idl,
#hm-carte.att-vu .att-meta,
#hm-carte.att-vu .att-jv { animation: none; opacity: 1; }
#hm-carte.att-vu .att-jb > .g-fill { animation: none; width: var(--w); }
@media (prefers-reduced-motion: reduce) {
  #hm-carte .att-idl,
  #hm-carte .att-meta,
  #hm-carte .att-jv { animation: none; opacity: 1; }
  #hm-carte.att-pret .att-jb > .g-fill { animation: none; width: var(--w); }
}

/* ==========================================================================
   L'ECRAN DE CHARGEMENT DU LANCEMENT — UN VOILE PLEIN, ASSUME (2026-08-22, 4e)

   ⚠️ IL REMPLACE UNE TENTATIVE DE MASQUAGE, ET C'EST LE PROPRIETAIRE QUI L'A
   TRANCHE : « quand j'allume le jeu je prefere un ecran de chargement qui cache
   et rend ca smooth et fluide ». Jusqu'ici on essayait de faire passer le
   montage de l'accueil derriere une carte qui se remplit — le reste de l'accueil
   (les cinq cases, les barres, le pied) arrivait quand il pouvait, et cela se
   voyait. Le voile COUVRE tout, ne laisse paraitre que le titre et la carte, et
   ne se leve QUE quand l'accueil est monte — et, depuis le 2026-08-23
   (decision du proprietaire : « instantane, smooth »), il ne tient PLUS de
   plancher : `--att-min` reste la regle du SEUL calendrier de fin de saison.

   ⚠️ IL EST DANS LE BALISAGE, PAS POSE A L'EXECUTION — meme raison que
   `hm-attente` : c'est la seule facon qu'il soit la au TOUT PREMIER RENDU, avant
   qu'une ligne de script du jeu n'ait tourne. `html.hm-boot` est posee par le
   balisage lui aussi, et `js/main.js` la RETIRE ; le petit script en pied de
   page la retire egalement au bout de dix secondes si rien n'est jamais venu.
   ⚠️ UN ECRAN DE CHARGEMENT QUI NE PART PAS EST PIRE QUE TOUT : les deux voies de
   retrait sont independantes l'une de l'autre.

   ⚠️ LA CARTE N'EST PAS REDESSINEE ICI, ELLE EST REMONTEE. `#hm-carte` reste
   exactement ou il est, dans l'accueil, avec ses vraies donnees et son animation
   d'arrivee (`att-pret`, bloc ci-dessus) : le voile passe DESSOUS. Deux dessins
   pour une meme chose finissent toujours par diverger — il n'y en a qu'un, et
   c'est aussi ce qui fait que rien ne bouge d'un pixel quand le voile se leve.
   ⚠️ L'ANIMATION D'ENTREE DE L'ECRAN EST COUPEE PENDANT LE VOILE (`animation:
   none` sur `#screen-home`) ET CE N'EST PAS COSMETIQUE : `.screen` s'ouvre par un
   `transform`, et un `transform` en cours cree un CONTEXTE D'EMPILEMENT — la
   carte serait alors prisonniere de l'ecran et passerait SOUS le voile.
   ⚠️ ET C'EST POUR LA MEME RAISON QUE `#boot` EST DANS `#app`, A L'INVERSE DE
   `#tab` ET `#hmj` : `html.theme-clair #app` porte `z-index: 1`, il cree donc
   lui aussi un contexte d'empilement, et les 61 de la carte ne valent QUE dans
   ce contexte-la. Un voile pose dehors serait toujours au-dessus d'elle, quel
   que soit son z-index — c'est ce qui est arrive, et la planche de captures l'a
   montre : l'ecran de chargement s'affichait sans sa carte. Les deux nombres de
   ce bloc ne veulent donc rien dire l'un sans l'autre : ils vivent dans le meme
   contexte, et ils doivent y rester. */
/* ⚠️ LA MARQUE EST EN BAS, ET LA PLACE DU HAUT EST LAISSEE A LA CARTE. Celle-ci
   reste exactement ou l'accueil la met — c'est ce qui fait qu'elle ne bouge pas
   d'un pixel quand le voile se leve —, donc c'est au voile de composer AUTOUR
   d'elle. Centrer son texte l'aurait mis sous la carte, a une distance qui
   dependrait de la hauteur de celle-ci ; ancre en bas, il n'en depend pas. */
#boot {
  position: fixed; inset: 0; z-index: 60;
  display: none; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 14px; padding: 24px 16px 16vh;
  background: var(--ds-bg) fixed;
  opacity: 1; transition: opacity .35s ease;
}
html.hm-boot #boot { display: flex; }
/* Le retrait : on eteint le voile AVANT de le retirer du flux, pour que l'accueil
   apparaisse en fondu et non d'un coup. `js/main.js` pose `parti` puis retire
   `hm-boot` quand la transition est finie. */
#boot.parti { opacity: 0; pointer-events: none; }
#boot .boot-logo { font-size: 1.5rem; }
#boot .boot-logo span { color: var(--ds-accent-deep); }
#boot .boot-dit {
  margin: 0; font-size: .78rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ds-text-dim);
}
/* LA CARTE, REMONTEE AU-DESSUS DU VOILE. Elle garde sa place et sa largeur : la
   colonne de l'accueil est bornee par `#app`, la carte n'a donc rien a recentrer. */
html.hm-boot #screen-home { animation: none; }
html.hm-boot #screen-home #hm-carte { position: relative; z-index: 61; }
/* ⚠️ TOUT LE RESTE DE L'ACCUEIL EST MASQUE PAR LE VOILE LUI-MEME, PAS PAR UNE
   REGLE : il est opaque et il couvre. Rien n'est donc `display: none`, la mise en
   page de l'accueil se fait normalement dessous, et la lever ne deplace rien. */
@media (prefers-reduced-motion: reduce) { #boot { transition: none; } }

/* --- 2 · LA CARTE DE CARRIERE ----------------------------------------------- */
/* ⚠️ LA LIGNE DE META A SA PROPRE RANGEE, SUR TOUTE LA LARGEUR. Rangee a cote du
   blason, elle partageait sa colonne avec « Continuer » et se faisait tronquer des
   le premier nom d'equipe un peu long : la capture montrait « 23 ans · saison 10 ·
   … », c'est-a-dire l'equipe et le rang perdus — les deux informations que la carte
   existe pour donner. */
/* ⚠️ `align-content: center` VIENT AVEC L'ELASTICITE (2026-08-14) : la carte prend
   desormais une part du mou, et sans lui ses quatre rangees s'ecarteraient jusqu'a
   se perdre dans une carte deux fois trop haute. Elles restent groupees, et c'est
   la carte qui grandit autour d'elles. */
html.theme-clair #screen-home .hm-carte {
  position: relative; display: grid; gap: 6px 8px;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "sur sur sur" "blason ident continuer" "meta meta meta" "jauges jauges jauges";
  align-items: center; align-content: center;
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 12px 13px; overflow: hidden;
}
html.theme-clair #screen-home .hm-blason { grid-area: blason; line-height: 0; }
html.theme-clair #screen-home .hm-ident { grid-area: ident; min-width: 0; }
html.theme-clair #screen-home .hm-ligne1 {
  display: flex; align-items: center; gap: 6px; min-width: 0;
}
html.theme-clair #screen-home .hm-pseudo {
  font-size: 1.06rem; font-weight: 800; color: var(--ds-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* L'ornement porte — ecu ou medaille — est FRERE du pseudo, jamais dedans :
   `.hm-pseudo` porte `overflow: hidden` et le decouperait. Meme raison que dans
   l'en-tete de saison, ou il est frere de `#hud-name`. */
html.theme-clair #screen-home .hm-porte { flex: 0 0 auto; line-height: 0; }
html.theme-clair #screen-home .hm-porte:empty { display: none; }
html.theme-clair #screen-home .hud-flag:empty { display: none; }
html.theme-clair #screen-home .hm-meta {
  grid-area: meta; margin: 0; font-size: .76rem; font-weight: 600; color: var(--ds-text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ⚠️ LES TROIS JAUGES TIENNENT SUR UNE LIGNE, EN TROIS COLONNES EGALES
   (2026-08-13). Empilees, elles occupaient trois rangees pleine largeur — 80 px
   des 196 de la carte, pour trois nombres de deux chiffres. En colonnes elles en
   prennent le tiers, et la carte rend la difference au reste de l'ecran.
   ⚠️ LA MISE EN PAGE EST FAITE ICI, ET SURTOUT PAS DANS `UI.gauge` : ce helper est
   CELUI DE L'EN-TETE DE SAISON, ou les trois jauges sont au contraire empilees sur
   toute la largeur, chacune sur sa ligne. Le toucher aurait change deux ecrans
   pour n'en corriger qu'un — c'est la meme raison qui fait que l'accueil rappelle
   les helpers un a un plutot que `UI.renderHud`.
   ⚠️ LE LIBELLE PEUT ETRE TRONQUE, ET C'EST UNE GARANTIE, PAS UN DEFAUT : la paire
   de statistiques est DERIVEE du poste (`UI.hudStatKeys`), donc le libelle le plus
   long n'est pas connu d'ici — « Communication » fait treize caracteres quand
   « Visee » en fait cinq. L'ellipse borne le pire cas ; sans elle, c'est la VALEUR
   qui sortait de sa colonne, et la valeur est ce que la jauge existe pour dire. */
html.theme-clair #screen-home .hm-jauges {
  grid-area: jauges; margin-top: 2px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 10px;
}
html.theme-clair #screen-home .hm-jauges:empty { display: none; }
html.theme-clair #screen-home .hm-jauges .gauge { min-width: 0; }
html.theme-clair #screen-home .hm-jauges .g-label {
  gap: 5px; font-size: .63rem; letter-spacing: .02em; line-height: 1.5;
}
html.theme-clair #screen-home .hm-jauges .g-label span:first-child {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.theme-clair #screen-home .hm-jauges .g-label span + span { flex: 0 0 auto; font-weight: 800; }
/* La piste garde la hauteur du theme (8 px) : elle n'a aucune raison de maigrir,
   c'est la RANGEE qui a ete gagnee, pas l'epaisseur de la barre. */
html.theme-clair #screen-home .hm-jauges .g-track { margin-top: 6px; }
/* ⚠️ `#btn-new` PORTE CETTE MEME CLASSE quand il vient occuper la carte : la carte
   n'a qu'une place d'action, et c'est elle. */
html.theme-clair #screen-home .hm-continuer {
  grid-area: continuer; align-self: center;
  font: inherit; font-size: .84rem; font-weight: 800; cursor: pointer;
  border: 0; border-radius: var(--ds-radius-btn); padding: 9px 15px;
  background: linear-gradient(180deg, var(--ds-btn-1), var(--ds-btn-2));
  color: var(--ds-btn-txt); box-shadow: var(--ds-btn-shadow);
}
html.theme-clair #screen-home .hm-continuer:hover { filter: brightness(1.04); }
/* LE SUR-TITRE de la carte : petit, espace, discret — il nomme la carte sans
   disputer la vedette au pseudo. Il occupe sa propre rangee, donc il ne peut pas
   etre tronque par la colonne du bouton. */
html.theme-clair #screen-home .hm-sur {
  grid-area: sur; font-size: .64rem; font-weight: 800; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ds-text-faint);
}
html.theme-clair #screen-home .hm-sur:empty { display: none; }
/* ⚠️ SANS CARRIERE, LA CARTE N'A PLUS DE FILIGRANE, ET LE BOUTON EST CENTRE SUR
   LE BLOC DE TEXTE (2026-08-14). La zone « continuer » couvre les DEUX rangees du
   texte — le titre et la ligne de meta —, si bien qu'`align-self: center` centre
   le bouton sur l'ensemble et non sur la seule premiere rangee. Mesure de l'etat
   d'avant : centre du bloc de texte a 111 px, centre du bouton a 95,5 — 15,5 px
   trop haut, et c'est exactement ce qui se voyait. */
html.theme-clair #screen-home .hm-carte.vide {
  grid-template-columns: 1fr auto; grid-template-areas: "sur sur" "ident continuer" "meta continuer";
}
/* La ligne pointillee disparait avec son emplacement, pas avec son bouton. */
html.theme-clair #screen-home #hm-slot-neuve:empty { display: none; }
/* ⚠️ LE FILIGRANE A ETE RETIRE, ET LE NŒUD RESTE (2026-08-14). C'etait un ecusson
   de 96 px pose en absolu dans le coin bas-droit d'une carte de 108, a 28 %
   d'opacite, avec le bouton dore PAR-DESSUS. Mesure : il ne debordait pas (6 px
   de marge sur les trois cotes) et son monogramme « CFA » etait bien la — mais on
   n'en voyait qu'un quart, le bouton et le texte couvrant le reste. Ce n'etait
   donc ni un blason ni un filigrane : une forme pale qui salissait la carte.
   `js/main.js` ne pose plus rien dedans dans cet etat ; la regle ci-dessous
   l'enleve du flux, sans quoi le `<div>` vide prendrait une case de la grille —
   `grid-area: blason` ne designe aucune zone dans le gabarit de l'etat vide, et
   la case serait donc placee automatiquement.
   ⚠️ NE PAS SUPPRIMER LE NŒUD : `#hm-blason` porte le VRAI blason des qu'il y a
   une carriere, et `verif-accueil-refonte` l'y cherche par cet identifiant. */
html.theme-clair #screen-home .hm-carte.vide .hm-blason { display: none; }
html.theme-clair #screen-home .hm-carte.vide .hm-meta { white-space: normal; }

/* --- 2 bis · CE QUE TU PORTES ------------------------------------------------
   Quatre cellules a parts egales : le theme equipe, le revetement de l'arme, la
   medaille portee, les avantages equipes. Chacune est un bouton, et c'est deja la
   porte — AUCUN lien « Modifier » ne s'ajoute a cote.

   ⚠️ ELLE NE DESSINE RIEN ELLE-MEME. Les trois apercus viennent des fonctions du
   jeu (`themeApercuHTML`, `UI.armeStickersHTML`, `UI.medailleHTML`) ; ces regles
   ne posent que des TAILLES et des formes. Redessiner l'un des trois ici aurait
   fait un second dessin, exactement ce qui a laisse le kill feed en arriere.

   ⚠️ PAS UN SEUL HEXADECIMAL, NI UN `rgb(`, comme le reste de ce bloc : tout vient
   des jetons `--ds-*`. (Le gris neutre du contour de l'apercu de theme appartient
   a `.pg-ap`, dans le bloc de l'ecran Progression, et il est neutre par
   construction — il ne suit aucun theme parce qu'il n'en designe aucun.) */
html.theme-clair #screen-home .hm-pan {
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-tile); padding: 7px 10px;
}
html.theme-clair #screen-home .hm-pan-eyebrow {
  font-size: .625rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ds-text-faint); line-height: 1.15;
}
html.theme-clair #screen-home .hm-pan-cells {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-top: 4px;
}
/* Le fond « legerement enfonce » est celui des champs, comme partout ailleurs. */
html.theme-clair #screen-home .hm-pan-c {
  cursor: pointer; font: inherit; border: 0; min-width: 0;
  display: grid; justify-items: center; gap: 1px;
  border-radius: var(--ds-radius-tile); padding: 3px 2px 4px;
  background: var(--ds-field-bg); color: var(--ds-text);
}
html.theme-clair #screen-home .hm-pan-c:hover { box-shadow: var(--ds-shadow-tile); }
/* LA ZONE D'APERCU. ⚠️ SA HAUTEUR EST FIXE ET C'EST LEGITIME : c'est une boite de
   dessin, pas un des blocs de l'ecran — sans elle, les quatre cellules seraient de
   quatre hauteurs differentes selon ce qui est porte, et la rangee sauterait a
   chaque changement d'equipement. */
html.theme-clair #screen-home .hm-pan-v {
  width: 100%; height: 24px; display: flex; align-items: center; justify-content: center;
  line-height: 0;
}
html.theme-clair #screen-home .hm-pan-v > svg { display: block; max-width: 100%; height: auto; }
/* L'APERCU DE THEME A SON ECHELLE — memes regles que `.pa-thap` pour le passe :
   on redimensionne le rendu du jeu, on ne le refait pas. */
html.theme-clair #screen-home .hm-pan-v .pg-ap { width: 100%; height: 24px; border-radius: 7px; }
html.theme-clair #screen-home .hm-pan-v .pg-ap-c { left: 5px; right: 5px; bottom: 4px; height: 11px; border-radius: 4px; }
html.theme-clair #screen-home .hm-pan-v .pg-ap-a { left: 5px; top: 4px; width: 8px; height: 8px; }
/* LE JETON VIDE EN POINTILLES — l'ABSENCE, jamais un second dessin de medaille. */
html.theme-clair #screen-home .hm-pan-vide {
  width: 20px; height: 20px; border-radius: var(--ds-radius-pill);
  border: 1.5px dashed var(--ds-text-faint); opacity: .85;
}
/* LES TROIS PASTILLES D'AVANTAGE : allumees a l'accent, eteintes au filet. */
html.theme-clair #screen-home .hm-pan-pp { display: flex; align-items: center; gap: 4px; }
html.theme-clair #screen-home .hm-pan-p {
  width: 8px; height: 8px; border-radius: var(--ds-radius-pill);
  background: var(--ds-line-hover);
}
html.theme-clair #screen-home .hm-pan-p.on { background: var(--ds-accent); }
/* ⚠️ LES DEUX LIGNES DE TEXTE SONT BORNEES : le nom d'un revetement ou d'une
   medaille n'est pas connu d'ici, et une cellule ne fait qu'un quart de la
   largeur. Sans l'ellipse, c'est la GRILLE qui sortait de la carte. */
html.theme-clair #screen-home .hm-pan-n,
html.theme-clair #screen-home .hm-pan-s {
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-align: center;
}
html.theme-clair #screen-home .hm-pan-n { font-size: .625rem; font-weight: 800; line-height: 1.2; }
html.theme-clair #screen-home .hm-pan-s { font-size: .5625rem; font-weight: 600; color: var(--ds-text-dim); line-height: 1.2; letter-spacing: -.01em; }

/* --- 3 · LES DEUX CARTES PREMIUM -------------------------------------------- */
/* ⚠️ ELLES SONT LES SEULES A BRILLER SUR CET ECRAN. C'est la refonte tout entiere :
   l'accueil d'avant animait deux cases sur huit et en dorait cinq, si bien qu'aucune
   ne ressortait. Ne pas rendre une tuile brillante « pour l'equilibre ». */
html.theme-clair #screen-home .hm-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* ⚠️ LE CONTENU EST CENTRE (2026-08-13). Cale a gauche, l'ecu, le titre et le
   sous-titre laissaient la MOITIE DROITE de chaque carte vide : les deux seules
   surfaces de l'ecran qui doivent ressortir montraient un vide comme moitie de
   leur surface. Centre, l'ecu coiffe le titre et le sous-titre, et la barre
   d'avancement du bas devient la base de la colonne.
   ⚠️ LA PASTILLE DE COMPTE NE SUIT PAS : elle est posee en ABSOLU en haut a
   droite (`.hm-pastille`), donc elle ne participe pas a ce flux et n'a pas
   bouge. C'est aussi ce qui l'empeche de decaler le titre quand elle apparait. */
/* ⚠️ `justify-content: center` VIENT AVEC L'ELASTICITE (2026-08-14) : la carte
   grandit avec la fenetre, et sans lui l'ecu, le titre et le sous-titre restaient
   colles en haut, laissant un trou juste au-dessus de la barre d'avancement. */
html.theme-clair #screen-home .hm-prem {
  position: relative; overflow: hidden; cursor: pointer; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  border: 0; border-radius: var(--ds-radius-tile); padding: 11px 11px 15px;
  font: inherit; color: var(--ds-btn-txt);
  background: linear-gradient(152deg, var(--ds-accent-solid-1), var(--ds-accent), var(--ds-accent-solid-2));
  box-shadow: var(--ds-shadow);
}
/* La seconde carte prend le MEME metal, mais sa lumiere vient de l'autre cote :
   les deux se distinguent sans qu'aucune cesse d'etre premium.
   ⚠️ ON N'EMPLOIE PAS UN JETON D'ENCRE (`--ds-accent-deep`, `--ds-accent-ink-fort`)
   POUR UN FOND, ET LA PLANCHE L'A MONTRE. Une encre est definie par son CONTRASTE
   AVEC LA CARTE : elle est sombre sur un theme clair, et CLAIRE sur un theme
   sombre. Sous « Nuit », le degrade partait donc de l'or et finissait en pale.
   Les aplats, eux, sont `--ds-accent-solid-1` et `-solid-2` : ils gardent leur
   role dans les 37 themes. */
html.theme-clair #screen-home .hm-prem[data-fam="or2"] {
  background: linear-gradient(152deg, var(--ds-accent-solid-2), var(--ds-accent), var(--ds-accent-solid-1));
}
/* LE REFLET QUI BALAIE, TOUTES LES CINQ SECONDES. Il est porte par un
   pseudo-element pour ne rien couter au contenu, et il est coupe net par
   `prefers-reduced-motion` (regle commune, en bas de ce bloc). */
html.theme-clair #screen-home .hm-prem::after {
  content: ""; position: absolute; top: -60%; left: -40%;
  width: 42%; height: 220%; pointer-events: none; opacity: .3;
  background: linear-gradient(90deg, transparent, var(--ds-on-solid), transparent);
  transform: rotate(18deg) translateX(-160%);
  animation: hm-reflet 5s linear infinite;
}
html.theme-clair #screen-home .hm-prem[data-fam="or2"]::after { animation-delay: 2.5s; }
@keyframes hm-reflet {
  0%   { transform: rotate(18deg) translateX(-160%); }
  26%  { transform: rotate(18deg) translateX(430%); }
  100% { transform: rotate(18deg) translateX(430%); }
}
/* ---- L'EVENEMENT « WEEK-END DOUBLE » SUR LA TUILE DU PASSE.  (2026-08-21)
   ⚠️ LA TUILE RESTE DOREE — un fond sombre a ete explicitement refuse. Aucune
   couleur n'est posee ici : le « x2 » et son surtitre prennent `currentColor`,
   c'est-a-dire l'encre commune des tuiles dorees (`--ds-btn-txt`). Le contraste
   vient de la TAILLE du chiffre, pas d'un aplat.
   ⚠️ HORS FENETRE LE BLOC EST `hidden`, DONC IL N'OCCUPE RIEN : la regle
   ci-dessous est explicite parce que `.hm-prem` met ses enfants en colonne et
   qu'un `display` pose l'emporterait sur l'attribut. */
html.theme-clair #screen-home .hm-prem-bonus {
  display: flex; flex-direction: column; align-items: center; gap: 0; line-height: 1;
}
html.theme-clair #screen-home .hm-prem-bonus[hidden] { display: none; }
html.theme-clair #screen-home .hm-bonus-x { font-size: 1.9rem; font-weight: 900; letter-spacing: -.02em; }
html.theme-clair #screen-home .hm-bonus-l {
  font-size: .5rem; font-weight: 800; letter-spacing: .18em; opacity: .82; margin-top: 2px;
}
/* LA LUEUR BLANCHE QUI TRAVERSE, PENDANT L'EVENEMENT SEULEMENT.
   ⚠️ ELLE NE REMPLACE PAS LE REFLET COMMUN (`::after`), elle s'y AJOUTE sur
   `::before`, plus large, plus pale et DEUX FOIS PLUS LENTE : c'est un reflet,
   pas un clignotant. Retirer la classe `bonus` la fait disparaitre entierement,
   sans rien laisser derriere.
   ⚠️ SOUS `prefers-reduced-motion` ELLE NE S'ANIME PLUS MAIS RESTE VISIBLE, en
   travers de la tuile : une lueur FIXE n'est pas un mouvement, et c'est ce qui
   permet de la juger sur une planche de captures — qui s'executent toutes sous
   ce reglage. Le reflet commun, lui, garde sa regle : il s'efface. */
html.theme-clair #screen-home .hm-prem.bonus::before {
  content: ""; position: absolute; top: -60%; left: -40%;
  width: 68%; height: 220%; pointer-events: none; opacity: .34; z-index: 0;
  background: linear-gradient(90deg, transparent, var(--ds-on-solid), transparent);
  transform: rotate(18deg) translateX(-160%);
  animation: hm-lueur 11s linear infinite;
}
@keyframes hm-lueur {
  0%   { transform: rotate(18deg) translateX(-160%); }
  62%  { transform: rotate(18deg) translateX(300%); }
  100% { transform: rotate(18deg) translateX(300%); }
}
/* Le contenu passe DEVANT la lueur : sans cela le « x2 » serait delave a chaque
   passage.
   ⚠️ ON NE VISE PAS `> *`, ET C'EST UN DEFAUT DEJA PAYE : `position: relative`
   pose sur TOUS les enfants a sorti la barre d'avancement de son calage absolu
   (`.hm-barre` est posee en bas de la carte) — elle a purement disparu de la
   tuile pendant l'evenement, et seule la relecture de la planche l'a dit. On
   nomme donc les elements de FLUX, et l'on se contente d'un `z-index` pour ce
   qui est deja positionne. */
html.theme-clair #screen-home .hm-prem.bonus > .hm-prem-bonus,
html.theme-clair #screen-home .hm-prem.bonus > .hm-ico,
html.theme-clair #screen-home .hm-prem.bonus > .hm-prem-txt { position: relative; z-index: 1; }
html.theme-clair #screen-home .hm-prem.bonus > .hm-barre,
html.theme-clair #screen-home .hm-prem.bonus > .hm-pastille { z-index: 1; }
html.theme-clair #screen-home .hm-prem-txt { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; }
html.theme-clair #screen-home .hm-prem-nom { font-size: .9rem; font-weight: 800; line-height: 1.15; }
html.theme-clair #screen-home .hm-prem-sous { font-size: .72rem; font-weight: 700; opacity: .84; }
/* La barre d'avancement, en bas de la carte. Piste et remplissage empruntent
   l'ENCRE de la carte (`currentColor`) : elle suit donc l'or ou le clair selon la
   carte, sans un jeton de plus, et sans jamais sortir du theme. */
html.theme-clair #screen-home .hm-barre {
  position: absolute; left: 11px; right: 11px; bottom: 7px; height: 4px;
  border-radius: var(--ds-radius-pill); overflow: hidden;
  background: currentColor; opacity: .24;
}
html.theme-clair #screen-home .hm-barre > i {
  display: block; height: 100%; width: 0; border-radius: inherit; background: currentColor;
}
/* La pastille de rattrapage du Defi : elle porte un NOMBRE, pas un point. */
html.theme-clair #screen-home .hm-pastille {
  position: absolute; top: 7px; right: 8px; min-width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 5px; border-radius: var(--ds-radius-pill);
  background: var(--ds-alerte); color: var(--ds-on-solid);
  font-size: .66rem; font-weight: 800; line-height: 1;
}
html.theme-clair #screen-home .hm-pastille[hidden] { display: none; }

/* --- 4 · LES QUATRE TUILES -------------------------------------------------- */
html.theme-clair #screen-home .hm-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* ⚠️ LE COMPTE A SA PROPRE RANGEE, IL N'EST PAS POSE EN ABSOLU SUR LA TUILE. En
   absolu il chevauchait l'ecu centre des que le libelle depassait deux caracteres —
   « 24 manches » et « 7 chapitres » passaient tous deux SOUS l'icone sur la premiere
   planche. Une rangee dediee le rend impossible par construction, et il reste bien
   en haut a droite. */
/* ⚠️ `align-content: center` VIENT AVEC L'ELASTICITE (2026-08-14) : les quatre
   rangees restent groupees et la tuile grandit autour d'elles. Sans lui, le compte
   montait au ras du bord haut et l'ecu partait au milieu d'un vide. */
html.theme-clair #screen-home .hm-tuile {
  position: relative; cursor: pointer; font: inherit;
  display: grid; grid-template-rows: auto auto auto auto; justify-items: center; align-content: center; gap: 2px;
  border: 0; border-radius: var(--ds-radius-tile); padding: 7px 8px 9px;
  background: var(--ds-card); color: var(--ds-text); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair #screen-home .hm-tuile:hover { box-shadow: var(--ds-shadow); }
html.theme-clair #screen-home .hm-tuile-nom { font-size: .82rem; font-weight: 800; line-height: 1.15; text-align: center; }
html.theme-clair #screen-home .hm-tuile-det { font-size: .68rem; font-weight: 600; color: var(--ds-text-dim); text-align: center; line-height: 1.2; }
/* ⚠️ LA TUILE « Palmares » PORTE DEUX LIGNES DEPUIS LE 2026-08-15 — le pseudo de
   la meilleure carriere, puis son palier. Les deux vivent DANS `.hm-tuile-det` :
   la grille des quatre tuiles ne gagne pas de rangee, et les trois autres tuiles
   ne sont pas touchees d'un pixel. */
html.theme-clair #screen-home #hm-det-palmares .hm-det-l1 {
  display: block; color: var(--ds-text); font-weight: 800;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.theme-clair #screen-home #hm-det-palmares .hm-det-l2 {
  display: block; font-size: .93em;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.theme-clair #screen-home .hm-compte {
  grid-row: 1; justify-self: end; min-height: 13px;
  font-size: .66rem; font-weight: 800; color: var(--ds-text-faint); letter-spacing: .01em;
}
/* ⚠️ ELLE GARDE SA PLACE MEME VIDE : sans `min-height`, la tuile sans compte
   remontait de 13 px et la grille perdait son alignement. */
html.theme-clair #screen-home .hm-compte:empty { visibility: hidden; }

/* --- LES SIX ECUS ------------------------------------------------------------
   ⚠️ AUCUN PORTE-ICONE : ni rond, ni carre arrondi. L'ecu se suffit, et il porte
   sa propre ombre douce. Un porte-icone aurait ajoute une seconde silhouette
   autour d'une forme qui en est deja une. */
html.theme-clair #screen-home .hm-ico { display: block; line-height: 0; flex: 0 0 auto; }
html.theme-clair #screen-home .hm-ico > svg { display: block; width: 100%; height: auto; }
html.theme-clair #screen-home .hm-prem .hm-ico { align-self: center; }
/* L'ombre portee de l'ecu EPOUSE SA SILHOUETTE — `drop-shadow` et non `box-shadow`,
   qui aurait dessine un rectangle autour d'une forme qui n'en est pas un. Sa couleur
   est l'encre du theme, ce qui la fait exister sur un fond clair comme sur un sombre. */
html.theme-clair #screen-home .hmi { overflow: visible; }
html.theme-clair #screen-home .hm-ico > .hmi { filter: drop-shadow(0 2px 2.5px var(--ds-line-hover)); }
/* LE REFLET DE L'ECU, meme geste que celui des 35 badges : une bande claire coupee
   par la silhouette. Les six partent au meme instant — ils sont cote a cote et
   forment une rangee, la ou les badges du mur se decalent pour ne pas scintiller
   ensemble. */
html.theme-clair #screen-home .hmi-shine {
  transform-origin: 32px 37px;
  animation: hmi-reflet 5.4s linear infinite;
}
@keyframes hmi-reflet {
  0%   { transform: rotate(16deg) translateX(-180%); }
  27%  { transform: rotate(16deg) translateX(180%); }
  100% { transform: rotate(16deg) translateX(180%); }
}

/* --- 5 · LA BARRE DES MISES A JOUR ------------------------------------------ */
html.theme-clair #screen-home .hm-majbar {
  position: relative; overflow: hidden; cursor: pointer; font: inherit; width: 100%;
  display: flex; align-items: center; gap: 9px;
  border: 0; border-radius: var(--ds-radius-tile); padding: 8px 11px;
  background: var(--ds-card); color: var(--ds-text); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair #screen-home .hm-ver {
  flex: 0 0 auto; background: var(--ds-field-bg); color: var(--ds-text-dim);
  border-radius: var(--ds-radius-pill); padding: 3px 9px;
  font-size: .68rem; font-weight: 800; letter-spacing: .03em;
}
/* ⚠️ LE TITRE TIENT SUR DEUX LIGNES DEPUIS LE 2026-08-13, ET VOICI CE QUI LE
   CONTRAIGNAIT. La barre est UNE rangee : le titre n'y recoit que ce qui reste
   apres la pastille de version (`v20260813`, largeur fixe, exigee par g20), la
   pastille de nouveaute et le chevron — soit 175 px a 390 px de large. Avec
   `white-space: nowrap`, tout ce qui depasse devenait des points de suspension :
   le titre de la version courante demande 502 px, on en lisait un tiers, coupe au
   milieu d'un mot (« Un accueil qui hierarch… »).
   ⚠️ LA LONGUEUR DU TITRE N'EST PAS REGLABLE ICI : elle vient de `data/notes.json`,
   et la regle du projet dit qu'ajouter une version n'est qu'un objet de plus dans
   ce fichier — le rendu ne doit pas dependre de la longueur qu'on y ecrit. Deux
   lignes rendent donc les trois quarts du titre au lieu d'un tiers, et le panneau
   qui s'ouvre au tap porte le texte entier : la barre est une accroche, pas la
   note. */
html.theme-clair #screen-home .hm-maj-titre {
  flex: 1 1 auto; min-width: 0; font-size: .77rem; font-weight: 700; color: var(--ds-text-dim);
  text-align: left; white-space: normal; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.25;
}
/* La pastille tant que la derniere note n'a pas ete ouverte. Elle est DOREE et non
   rouge : ce n'est pas une alerte, c'est une nouveaute. */
html.theme-clair #screen-home .hm-neuf {
  position: static; width: 8px; min-width: 8px; height: 8px; padding: 0;
  background: var(--ds-accent); border-radius: var(--ds-radius-pill);
}
html.theme-clair #screen-home .hm-chev {
  flex: 0 0 auto; width: 7px; height: 7px; margin-right: 2px;
  border-right: 2px solid var(--ds-text-faint); border-bottom: 2px solid var(--ds-text-faint);
  transform: rotate(-45deg);
}
/* Le reflet de la barre balaie toutes les SIX SECONDES ET DEMIE — volontairement
   different des cinq secondes des cartes premium, pour que les trois animations ne
   battent jamais ensemble. */
html.theme-clair #screen-home .hm-majbar::after {
  content: ""; position: absolute; top: -60%; left: -30%;
  width: 22%; height: 220%; pointer-events: none; opacity: .55;
  background: linear-gradient(90deg, transparent, var(--ds-field-bg), transparent);
  transform: rotate(18deg) translateX(-200%);
  animation: hm-reflet-bar 6.5s linear infinite;
}
@keyframes hm-reflet-bar {
  0%   { transform: rotate(18deg) translateX(-200%); }
  22%  { transform: rotate(18deg) translateX(900%); }
  100% { transform: rotate(18deg) translateX(900%); }
}

/* --- 5 bis · L'ACCES AU COMPTE ----------------------------------------------
   ⚠️ UN CRAN EN DESSOUS DE LA BARRE DES MISES A JOUR, ET C'EST TOUT LE PROPOS :
   pas de carte, pas d'ombre portee, pas de reflet, pas de pastille de nouveaute.
   Le jeu se joue entierement sans compte — cette ligne ne doit donc jamais avoir
   l'air d'une etape a franchir. Elle emprunte le meme chevron que la barre du
   dessus (`.hm-chev`), ce qui suffit a dire « ca s'ouvre ».
   ⚠️ AUCUNE COULEUR EN DUR : la pastille d'etat prend `--ds-good` connectee,
   `--ds-text-faint` sinon. Un theme les redefinit toutes les deux. */
html.theme-clair #screen-home .hm-comptebar {
  position: relative; cursor: pointer; font: inherit; width: 100%;
  display: flex; align-items: center; gap: 8px;
  border: 0; border-radius: var(--ds-radius-tile); padding: 6px 11px;
  background: transparent; color: var(--ds-text-dim);
}
html.theme-clair #screen-home .hm-comptebar.hidden { display: none; }
html.theme-clair #screen-home .hm-compte-pt {
  flex: 0 0 auto; width: 7px; height: 7px; border-radius: var(--ds-radius-pill);
  background: var(--ds-text-faint);
}
html.theme-clair #screen-home .hm-comptebar.on .hm-compte-pt { background: var(--ds-good); }
/* HORS-LIGNE : la pastille se creuse au lieu de changer de teinte. Un point plein
   d'une autre couleur se lirait comme une alerte ; il n'y en a pas — la partie est
   sur l'appareil, et c'est tout ce que le joueur a besoin de savoir. */
html.theme-clair #screen-home .hm-comptebar.off .hm-compte-pt {
  background: transparent; box-shadow: inset 0 0 0 2px var(--ds-text-faint);
}
html.theme-clair #screen-home .hm-compte-lib {
  flex: 0 0 auto; font-size: .72rem; font-weight: 800; letter-spacing: .02em;
}
html.theme-clair #screen-home .hm-compte-etat {
  flex: 1 1 auto; min-width: 0; text-align: left;
  font-size: .7rem; font-weight: 600; color: var(--ds-text-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- 6 · NOUVELLE CARRIERE, EN TRAIT POINTILLE ------------------------------- */
/* ⚠️ ELLE N'EST PAS UN BOUTON PLEIN, ET C'EST DELIBERE : c'est l'action qui ARCHIVE
   la carriere en cours. Lui donner la meme silhouette qu'a « Continuer » revenait a
   proposer deux fois le meme geste pour deux consequences opposees. */
/* ⚠️ LE TRAIT SE VOYAIT SUR UNE CARTE, PAS SUR LA PAGE, ET C'EST CE QUI LE RENDAIT
   NUL (2026-08-13). `--ds-line-hover` est le filet DE CHAMP : il est calibre pour
   se detacher de `--ds-card`, la surface blanche des tuiles. Or cette ligne-ci est
   la seule de l'ecran a etre posee A MEME LE FOND — et sur `--ds-bg-1`/`-2`, un
   trait de 1,5 px dans cette valeur disparait purement et simplement. Le bouton se
   lisait alors comme du TEXTE NU, exactement ce qu'un cadre pointille existe pour
   eviter : c'est l'action qui ARCHIVE la carriere en cours, elle ne doit ressembler
   ni a « Continuer » (bouton plein) ni a un lien. Il prend donc l'encre discrete du
   texte, `--ds-text-faint`, qui est definie par son contraste — pas par son fond.
   ⚠️ LE SIGNE PLUS EST UN PSEUDO-ELEMENT DE `.hm-neuve`, ET C'EST VOULU : le meme
   nœud `#btn-new` va occuper la carte de carriere sous la classe `.hm-continuer`
   quand il n'y a pas de carriere (cf. § 4 du fichier de l'accueil). Ecrit dans le
   libelle, le plus l'aurait suivi jusque dans le bouton plein ; porte par la
   classe, il apparait et disparait avec la ligne pointillee, sans une ligne de JS. */
html.theme-clair #screen-home .hm-neuve {
  cursor: pointer; font: inherit; width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: transparent; color: var(--ds-text-dim);
  border: 1.5px dashed var(--ds-text-faint); border-radius: var(--ds-radius-btn);
  padding: 10px 12px; font-size: .82rem; font-weight: 700; box-shadow: none;
}
html.theme-clair #screen-home .hm-neuve::before {
  content: "+"; font-size: 1.06rem; font-weight: 800; line-height: 1;
}
html.theme-clair #screen-home .hm-neuve:hover { color: var(--ds-text); border-color: var(--ds-accent); }

/* --- 7 · MENTIONS ------------------------------------------------------------ */
/* ⚠️ `margin-top: auto` DOIT ETRE ECRIT ICI, ET PAS PLUS HAUT. Une premiere
   version l'avait pose a cote de `.hm` : cette regle-ci vient APRES dans la
   feuille, a specificite egale, et son `margin: 0` l'annulait sans rien signaler
   — les mentions restaient collees sous la barre et le vide du bas subsistait.
   ⚠️ ELLE N'ABSORBE PLUS RIEN DEPUIS LE 2026-08-14, ET ON LA GARDE QUAND MEME :
   les trois surfaces elastiques consomment le mou AVANT elle (une marge `auto`
   ne recoit que ce que `flex-grow` a laisse), donc les mentions se posent au bas
   parce que la colonne est pleine, et non parce qu'une marge les y pousse. Le
   filet reste : si un jour les trois cessaient de grandir, il n'y aurait pas de
   trou sous les mentions, juste au-dessus d'elles. */
html.theme-clair #screen-home .hm-pied {
  margin: auto 0 0; padding: 0 2px; text-align: center;
  font-size: .64rem; line-height: 1.35; color: var(--ds-text-faint);
}
html.theme-clair #screen-home .hm-effacer {
  display: block; margin: 4px auto 0; cursor: pointer; font: inherit;
  font-size: .64rem; font-weight: 700;
  background: none; border: 0; padding: 0; color: var(--ds-text-faint);
  text-decoration: underline; text-underline-offset: 2px;
}
html.theme-clair #screen-home .hm-effacer:hover { color: var(--ds-bad-ink); }

/* --- LE PANNEAU DES MISES A JOUR, GLISSANT PAR LE BAS -------------------------
   ⚠️ IL VIT HORS DE `#app`, comme le voile du tableau de fin de saison, et pour la
   meme raison : ce n'est pas un ecran du jeu. Il n'a donc PAS d'identifiant en
   `screen-`, et n'entre pas dans `ECRANS_CLAIRS` — l'invariant g32 n'a rien a y
   couvrir. Ses surfaces reprennent les jetons de carte, comme tout le reste.
   ⚠️ SES REGLES NE SONT PAS SCOPEES A `html.theme-clair` : le panneau est pose HORS
   de `#app`, et la classe est portee par `<html>`, donc elle s'appliquerait bien —
   mais le panneau doit rester lisible meme si un ecran futur sortait de la table.
   Les jetons, eux, sont definis sur `:root` et suivent le theme dans tous les cas. */
.hmj { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; }
.hmj[hidden] { display: none; }
.hmj-fond { position: absolute; inset: 0; background: var(--ds-text); opacity: 0; transition: opacity .22s ease; }
.hmj.on .hmj-fond { opacity: .42; }
.hmj-panneau {
  position: relative; width: 100%; max-width: 460px; margin: 0 auto;
  max-height: 78vh; display: flex; flex-direction: column;
  background: var(--ds-card); color: var(--ds-text);
  border-radius: var(--ds-radius-card) var(--ds-radius-card) 0 0;
  box-shadow: var(--ds-shadow);
  transform: translateY(100%); transition: transform .26s cubic-bezier(.2, .8, .3, 1);
}
.hmj.on .hmj-panneau { transform: translateY(0); }
.hmj-poignee { width: 38px; height: 4px; border-radius: var(--ds-radius-pill); background: var(--ds-line-hover); margin: 8px auto 4px; }
.hmj-tete { display: flex; align-items: center; gap: 8px; padding: 2px 14px 8px; }
.hmj-titre { flex: 1 1 auto; margin: 0; font-size: .96rem; font-weight: 800; }
.hmj-x {
  flex: 0 0 auto; cursor: pointer; font: inherit; font-size: 1rem; line-height: 1;
  background: var(--ds-field-bg); color: var(--ds-text-dim);
  border: 0; border-radius: var(--ds-radius-pill); width: 28px; height: 28px;
}
/* Les deux onglets. Un onglet = un panneau, et le lien se fait par `aria-controls`. */
.hmj-onglets { display: flex; gap: 6px; padding: 0 14px 8px; }
.hmj-ong {
  flex: 1 1 0; cursor: pointer; font: inherit; font-size: .8rem; font-weight: 800;
  background: var(--ds-field-bg); color: var(--ds-text-dim);
  border: 0; border-radius: var(--ds-radius-pill); padding: 7px 10px;
}
.hmj-ong[aria-selected="true"] { background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink); }
.hmj-corps { overflow-y: auto; padding: 2px 14px 16px; -webkit-overflow-scrolling: touch; }
.hmj-vue[hidden] { display: none; }

/* LA FRISE VERTICALE — un fil, un point par version. Le fil est un pseudo-element
   de l'entree, jamais un element de plus : il doit s'arreter net a la derniere. */
.hmj-e { position: relative; padding: 0 0 14px 22px; }
.hmj-e::before {
  content: ""; position: absolute; left: 4px; top: 13px; bottom: -1px;
  width: 2px; background: var(--ds-line);
}
.hmj-e:last-child::before { display: none; }
.hmj-e::after {
  content: ""; position: absolute; left: 0; top: 5px;
  width: 10px; height: 10px; border-radius: var(--ds-radius-pill);
  background: var(--ds-line-hover);
}
/* La plus recente : point entoure d'un halo, et marquee « Actuelle ». */
.hmj-e.actuelle::after { background: var(--ds-accent); box-shadow: 0 0 0 4px var(--ds-accent-soft-bg); }
.hmj-e-tete { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.hmj-e-ver { font-size: .78rem; font-weight: 800; color: var(--ds-text); letter-spacing: .02em; }
.hmj-e-act {
  font-size: .62rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink);
  border-radius: var(--ds-radius-pill); padding: 2px 7px;
}
.hmj-e-titre { margin: 2px 0 5px; font-size: .8rem; font-weight: 700; color: var(--ds-text); }
.hmj-l { display: flex; gap: 7px; margin: 0 0 4px; font-size: .75rem; line-height: 1.35; }
.hmj-et {
  flex: 0 0 auto; align-self: flex-start; font-size: .6rem; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
  border-radius: var(--ds-radius-pill); padding: 2px 7px; margin-top: 1px;
}
.hmj-et.neuf { background: var(--ds-good-soft-bg); color: var(--ds-good-ink); }
.hmj-et.mieux { background: var(--ds-info-soft-bg); color: var(--ds-info-ink); }
.hmj-et.corrige { background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink); }
.hmj-l span { color: var(--ds-text-dim); }

/* LA FEUILLE DE ROUTE — trois etats, et AUCUNE DATE. */
.hmj-r { position: relative; padding: 0 0 12px 22px; }
.hmj-r::after {
  content: ""; position: absolute; left: 0; top: 4px; box-sizing: border-box;
  width: 10px; height: 10px; border-radius: var(--ds-radius-pill);
}
.hmj-r.encours::after { background: var(--ds-accent); box-shadow: 0 0 0 4px var(--ds-accent-soft-bg); }
.hmj-r.prevu::after { background: var(--ds-text-faint); }
.hmj-r.etude::after { background: transparent; border: 2px solid var(--ds-line-hover); }
.hmj-r-etat {
  font-size: .6rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ds-text-faint);
}
.hmj-r.encours .hmj-r-etat { color: var(--ds-accent-ink); }
.hmj-r-nom { margin: 1px 0 0; font-size: .82rem; font-weight: 700; color: var(--ds-text); }
.hmj-note {
  margin: 8px 0 0; padding: 9px 11px; border-radius: var(--ds-radius-tile);
  background: var(--ds-field-bg); color: var(--ds-text-dim);
  font-size: .71rem; line-height: 1.4;
}

/* --- LE CONTENU DU PANNEAU DU COMPTE ---------------------------------------
   ⚠️ LA COQUILLE N'EST PAS ICI : `#hmc` porte la classe `.hmj`, donc le fond, le
   glissement, la tete, la croix et le corps defilant sont ceux du panneau des
   mises a jour, aux memes valeurs. Ce bloc ne decrit QUE ce qui lui est propre.
   ⚠️ ET IL N'ECRIT AUCUNE COULEUR : tout vient des jetons, comme partout — un
   theme change le panneau du compte sans qu'une ligne d'ici ne bouge. */
/* ⚠️ `display` EXPLICITE APPELLE SON `[hidden]`, TOUJOURS, ET C'EST UN PIEGE QUI A
   MORDU. La regle du navigateur est `[hidden] { display: none }` — une declaration
   de `display` dans la feuille du jeu la BAT, et l'attribut `hidden` pose par
   js/main.js ne cache alors plus rien. Le formulaire de connexion restait affiche
   SOUS le bloc « Connecte en tant que… », ce que la premiere planche a montre.
   Les deux blocs du panneau portent donc leur `[hidden]`, et il ne faut en retirer
   aucun des deux. */
.hmc-form { display: block; }
.hmc-form[hidden] { display: none; }
.hmc-lab {
  display: block; margin: 6px 0 3px;
  font-size: .64rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ds-text-faint);
}
/* ⚠️ `font-size: 16px` SUR LES CHAMPS, ET CE N'EST PAS UN CHOIX ESTHETIQUE : en
   dessous de 16 px, iOS ZOOME la page a la mise au point et ne la dezoome jamais
   — l'accueil se retrouve de travers derriere le panneau. C'est la seule taille
   ecrite en pixels de tout ce bloc, et elle est un garde-fou. */
.hmc-champ {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 16px;
  padding: 9px 11px; border-radius: var(--ds-radius-tile);
  border: 1px solid var(--ds-line); background: var(--ds-field-bg); color: var(--ds-text);
}
.hmc-champ:focus { outline: none; border-color: var(--ds-accent); }
.hmc-champ:disabled { opacity: .55; }
.hmc-actions { display: flex; gap: 8px; margin: 12px 0 0; }
.hmc-btn {
  flex: 1 1 0; cursor: pointer; font: inherit; font-size: .78rem; font-weight: 800;
  padding: 10px 8px; border-radius: var(--ds-radius-tile);
  border: 1px solid var(--ds-btn-soft-line); background: var(--ds-card); color: var(--ds-text);
}
/* Le couple accent / encre de bouton est celui du bouton principal de la creation
   (`#btn-start`) : la meme paire de jetons, jamais une seconde. */
.hmc-btn-plein { border-color: transparent; background: var(--ds-accent); color: var(--ds-btn-txt); }
.hmc-btn:disabled { opacity: .5; cursor: default; }
.hmc-connecte { display: block; }
.hmc-connecte[hidden] { display: none; }
.hmc-qui { margin: 6px 0 2px; font-size: .9rem; font-weight: 800; color: var(--ds-text); }
.hmc-sync { margin: 0 0 12px; font-size: .72rem; color: var(--ds-text-dim); }
/* Le message : il ne crie pas. Un refus du serveur et une perte de reseau ont la
   meme silhouette — seule l'encre change, et `.mauvais` est la seule variante. */
.hmc-msg {
  margin: 10px 0 0; padding: 8px 11px; border-radius: var(--ds-radius-tile);
  background: var(--ds-field-bg); color: var(--ds-text-dim);
  font-size: .73rem; line-height: 1.4;
}
.hmc-msg[hidden] { display: none; }
.hmc-msg.mauvais { background: var(--ds-bad-soft-bg); color: var(--ds-bad-ink); }
.hmc-note {
  margin: 14px 0 0; font-size: .68rem; line-height: 1.45; color: var(--ds-text-faint);
}

/* ⚠️ TOUT MOUVEMENT S'ARRETE quand le systeme le demande. Les trois reflets et le
   glissement du panneau sont coupes ensemble : c'est la meme regle pour les trois,
   et les captures s'executent sous ce reglage. */
@media (prefers-reduced-motion: reduce) {
  html.theme-clair #screen-home .hm-prem::after,
  html.theme-clair #screen-home .hm-majbar::after { animation: none; opacity: 0; }
  /* ⚠️ LA LUEUR DE L'EVENEMENT S'ARRETE MAIS NE DISPARAIT PAS : figee en travers
     de la tuile, elle ne bouge plus — donc elle respecte le reglage — et reste
     jugeable a l'oeil sur une planche de captures. */
  html.theme-clair #screen-home .hm-prem.bonus::before {
    animation: none; opacity: .26; transform: rotate(18deg) translateX(70%);
  }
  html.theme-clair #screen-home .hmi-shine { animation: none; opacity: 0; }
  .hmj-panneau, .hmj-fond { transition: none; }
}
/* ===== FIN ACCUEIL REFONDU =================================================== */

/* =============================================================================
   MARCHE DES TRANSFERTS — OFFRES REPLIABLES ET MISES EN GARDE REPLIABLES
   (2026-07-27)
   -----------------------------------------------------------------------------
   PRESENTATION SEULE. Aucune valeur, aucun montant, aucun texte de fond, aucune
   regle de transfert ne change : les memes lignes de detail, aux memes sources et
   au meme format, sont simplement MASQUEES tant que l'offre n'est pas depliee.

   POURQUOI UN `<details>` NATIF plutot qu'une bascule de classe : il n'y a aucun
   etat a memoriser ni a reinitialiser. Le marche est re-rendu a chaque action
   (`renderTransferts` reecrit `#season-body`), donc un `<details>` sans attribut
   `open` revient TOUJOURS replie a l'ouverture de l'ecran — c'est exactement le
   comportement par defaut demande, obtenu sans une ligne de script. Il apporte en
   prime le clavier (Entree / Espace) et le repli a l'impression.
   Une mise en garde imbriquee dans une offre NE LA REPLIE PAS : un `<summary>` ne
   bascule que son propre `<details>`, il n'y a pas de propagation a arreter.
   ============================================================================= */

/* La carte porte desormais deux parties qui ont chacune leur rembourrage. */
.offer { padding: 0; overflow: hidden; }

/* --- LIGNE REPLIEE (le `<summary>`) : blason, equipe, pastille de Tier, VRS, salaire ---
   Refonte 2026-07-29 : la ligne tient sur UNE SEULE ligne physique, sans jamais passer
   a la ligne (`flex-wrap: nowrap`) — SEUL le nom d'equipe se tronque (« … ») s'il manque
   de place ; blason, pastille de Tier, VRS, salaire et fleche ne retrecissent jamais
   (`flex: 0 0 auto`). Avant cette tache, un `flex-wrap: wrap` laissait les conditions
   cles et la fleche passer a la ligne suivante ; ce comportement n'existe plus, la carte
   ne portant plus que des elements a largeur fixe apres le nom. */
.offer-tete {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 7px;
  padding: 11px 13px; cursor: pointer; overflow: hidden;
  list-style: none; -webkit-tap-highlight-color: transparent;
}
.offer-tete::-webkit-details-marker { display: none; }   /* pas de triangle natif */
.offer-tete::marker { content: ""; }
.offer-tete:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.offer-tete .offer-emb { flex: 0 0 auto; display: inline-flex; line-height: 0; }
.offer-nom { flex: 1 1 auto; min-width: 3ch; font-weight: 700; font-size: .95rem; color: var(--txt);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pastille de TIER coloree par rarete : couleurs propres a ce composant, cf. bloc
   theme clair plus bas (Amateur gris, Tier 3 vert, Tier 2 bleu, Tier 1 violet, Tier S
   dore — meme echelle que la fiche de fin de carriere, transposee sur fond clair). */
.otier { flex: 0 0 auto; display: inline-flex; align-items: center; white-space: nowrap;
  border-radius: 999px; padding: 3px 8px; font-size: 10.5px; font-weight: 800; }
/* Classement VRS et salaire : jamais tronques, chiffres alignes. */
.offer-vrs { flex: 0 0 auto; font-size: .72rem; color: var(--txt-faint);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.offer-sal { flex: 0 0 auto; font-size: .82rem; font-weight: 700; color: var(--txt);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.offer-fleche { flex: 0 0 auto; font-size: .95rem; line-height: 1; color: var(--txt-faint);
  transition: transform .18s ease; }
.offer[open] .offer-fleche { transform: rotate(180deg); }

/* --- CORPS : masque tant que l'offre n'est pas depliee. Contenu inchange. --- */
.offer-corps { padding: 0 13px 13px; }

/* --- MISE EN GARDE REPLIABLE ---
   Le conteneur garde ses classes historiques (`offer-risque`, `risque-ligne`) : il
   herite donc du fond ambre et de la couleur deja definis, en theme sombre comme en
   theme clair, sans qu'aucune couleur nouvelle soit introduite ici. Seul son
   rembourrage passe a ses deux parties. */
.mg { padding: 0; overflow: hidden; }
.mg-tete {
  display: flex; align-items: center; gap: 7px; padding: 8px 11px;
  cursor: pointer; list-style: none; -webkit-tap-highlight-color: transparent;
  font-size: .8rem; font-weight: 700;
}
.mg-tete::-webkit-details-marker { display: none; }
.mg-tete::marker { content: ""; }
.mg-tete:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mg-ico { flex: 0 0 auto; line-height: 1; }
.mg-lab { flex: 1 1 auto; }
.mg-fleche { flex: 0 0 auto; margin-left: auto; line-height: 1; opacity: .75;
  transition: transform .18s ease; }
.mg[open] .mg-fleche { transform: rotate(180deg); }
.mg-corps { padding: 0 11px 9px; line-height: 1.45; }
/* Dans une offre, la mise en garde ne doit pas coller au bouton d'action. */
.offer-corps .mg { margin-bottom: 11px; }

/* Les deux fleches sont le seul mouvement ajoute : neutralise si l'appareil le demande. */
@media (prefers-reduced-motion: reduce) {
  .offer-fleche, .mg-fleche { transition: none; }
}

/* --- Transposition sur le THEME CLAIR ---
   La carte d'offre recoit deja le blanc, le rayon et l'ombre du theme (regle
   `html.theme-clair .narr, .offer, .choice-btn`). Restent le nom, le VRS, le salaire,
   la fleche (2026-07-29 : desormais DOREE, elle porte l'action de deplier) et les
   cinq couleurs de la pastille de Tier — valeurs de reference donnees pour ce
   composant, non derivees d'une echelle preexistante (celle de la fiche de fin de
   carriere, `.fc-tier-*`, est pensee en surcouches translucides pour un fond sombre,
   illisible telle quelle sur les cartes blanches de cet ecran). */
html.theme-clair .offer-nom { color: var(--ds-text); }
html.theme-clair .offer-vrs { color: var(--ds-text-dim); }
html.theme-clair .offer-sal { color: var(--ds-text); }
html.theme-clair .offer-fleche { color: var(--ds-accent); }
html.theme-clair .offer-tete:focus-visible,
html.theme-clair .mg-tete:focus-visible { outline-color: var(--ds-accent); }
html.theme-clair .otier-ts { background: #FAE7C4; color: #96610A; }
html.theme-clair .otier-t1 { background: #EBE2FB; color: #6D3BD1; }
html.theme-clair .otier-t2 { background: #DFEAFB; color: #2560DE; }
html.theme-clair .otier-t3 { background: #DAF1E4; color: #178A50; }
html.theme-clair .otier-am { background: #ECEEF2; color: #5A6577; }
/* Carte de PROLONGATION : liseret dore a gauche (seule marque distinctive desormais,
   la ligne ne portant plus de badge « PROLONGATION »). */
html.theme-clair .offer-ext { border-left: 3px solid var(--ds-accent); }
/* Fin separateur entre la ligne repliee et le detail deplie — la carte n'en portait
   aucun avant cette tache, seul le rembourrage les distinguait. */
html.theme-clair .offer-corps { border-top: 1px solid var(--ds-line); padding-top: 10px; }

/* =====================================================================
   « SAUTER CE TOURNOI » : un vrai bouton secondaire (2026-07-27)
   ---------------------------------------------------------------------
   L'action existait deja (meme bouton, meme classe `ct-btn`, meme `data-tid`,
   meme gestionnaire) mais elle etait rendue en `btn-ghost small` : fond
   transparent, largeur automatique, texte attenue — elle se lisait comme un
   libelle, pas comme une action. Elle porte desormais `ct-skip` :
     - pleine largeur de la carte, hauteur de cible tactile confortable ;
     - fond gris-bleu clair + contour marque (jetons `--ds-btn-soft-*`), donc
       visible sur la carte blanche du theme clair SANS employer le dore, qui
       reste reserve aux actions principales ;
     - chevron d'avance rapide en tete, en `currentColor`.
   RIEN D'AUTRE ne bouge : les incontournables gardent leur ligne « 🔒 toujours
   dispute » (aucun bouton, on ne peut pas les sauter), le retour en arriere
   « Finalement, on y va » garde son `btn-primary`, et la logique de saut, les
   seuils de fidelite et les valeurs des cartes sont hors de ce bloc.
   ===================================================================== */
.ct-skip {
  flex: 1 1 100%; width: 100%;
  gap: 8px;
  padding: 11px 12px; min-height: 42px;
  border-radius: 13px;
  font-weight: 700;
  background: var(--bg-3); border-color: var(--line); color: var(--txt-dim);
}
.ct-skip:hover { background: var(--bg-2); color: var(--txt); border-color: var(--accent-dim); }
.ct-skip .ct-skip-ico { flex: 0 0 auto; opacity: .85; }

html.theme-clair .ct-skip {
  background: var(--ds-btn-soft-bg);
  border: 1px solid var(--ds-btn-soft-line);
  color: var(--ds-btn-soft-txt);
  box-shadow: none;
}
html.theme-clair .ct-skip:hover {
  background: var(--ds-btn-soft-bg-h);
  border-color: var(--ds-btn-soft-line);
  color: var(--ds-text);
}
html.theme-clair .ct-skip:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }

/* =====================================================================
   PASTILLE D'IDENTITE — SIMPLIFIEE LE 2026-07-28
   ---------------------------------------------------------------------
   La residence fiscale (`.hud-res`, pin + lieu) et les POINTS VRS (`.hud-vrs-pts`)
   ont ete retires de la pastille pour qu'elle tienne sur UNE SEULE LIGNE. Les deux
   informations restent affichees dans la FICHE JOUEUR, aux memes sources exactement
   (`DF.fiscInfo` pour la residence, `DF.vrsSnapshot` pour le rang et les points) —
   deplacement d'affichage, aucun calcul touche.
   Les regles NEUTRES de `.hud-res` et `.hud-vrs-pts` sont conservees ci-dessous :
   elles ne s'appliquent plus a rien dans l'en-tete, et resteraient justes si ces
   blocs devaient resservir ailleurs.
   ===================================================================== */
.hud-res { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%;
  font-size: .78rem; color: var(--txt-dim); }
.hud-res .ico-pin { flex: 0 0 auto; }
.hud-res-nom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hud-vrs-pts { white-space: nowrap; font-variant-numeric: tabular-nums; }
.hud-vrs-pts::before { content: "·"; margin: 0 5px 0 4px; opacity: .55; font-weight: 400; }

/* =====================================================================
   ECRAN UNIQUE « RESULTATS DE LA SAISON » — FUSION DU 2026-07-28
   ---------------------------------------------------------------------
   Les ecrans « Resultats de la saison » et « Bilan de la saison » n'en font
   plus qu'un : un RESUME qui tient sans defiler (huit cases en deux colonnes,
   le bandeau du Grand Slam, le bouton « Continuer ») et un DETAIL par case,
   replie par defaut, qui s'ouvre pleine largeur SOUS SA RANGEE.

   Le placement des panneaux ne doit rien a du JavaScript : la grille a deux
   colonnes, les cases occupent une colonne chacune et les panneaux les deux
   (`grid-column: 1 / -1`). Comme ils suivent leur rangee dans le document,
   ils s'ouvrent exactement dessous, sans jamais decaler les autres cases.

   Bloc STRICTEMENT ADDITIF : rien de ce qui precede n'est modifie. Les regles
   neutres valent pour le theme sombre (chemin de rollback) ; le theme clair
   « Clair doux » ne fait que rehausser, avec ses jetons `--ds-*` existants.
   ===================================================================== */
/* ==========================================================================
   L'ETAT D'ATTENTE — DES BARRES, JAMAIS UN CADRE VIDE          (2026-08-20)

   Deux transitions du jeu demandaient un calcul avant de pouvoir dessiner : le
   LANCEMENT (la carte de carriere restait blanche, avec le seul bouton) et le
   BILAN de saison (l'ecran ne bougeait pas tant que tout n'etait pas pret). Les
   deux montrent desormais la MEME chose pendant l'attente : la forme de ce qui
   arrive, en gris. Un cadre vide ressemble a une panne ; une forme grise dit
   « ca vient ».

   ⚠️ CES BARRES NE PORTENT AUCUNE VALEUR ET N'EN DEDUISENT AUCUNE. Elles sont
   du decor pur (`aria-hidden`), et c'est la phrase en `role="status"` qui dit ce
   qui se passe a qui n'a pas les yeux dessus.
   ⚠️ LA CLASSE `df-occupe` COUPE LES ORDRES, elle ne cache rien : elle est posee
   le temps d'une transition decoupee et retiree des que l'ecran est complet.
   Sans elle, un second appui entrerait dans un etat a moitie calcule. */
html.df-occupe #app { pointer-events: none; }
.ds-attente {
  background: linear-gradient(90deg, var(--bg-3) 0%, var(--bg-card) 50%, var(--bg-3) 100%);
  background-size: 200% 100%; border-radius: 8px;
  animation: ds-att 1.25s ease-in-out infinite;
}
@keyframes ds-att { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { .ds-attente { animation: none; } }

/* ⚠️ L'ETAT D'ATTENTE A UNE ANIMATION D'ENTREE, ET SA DUREE EST LUE PAR
   js/main.js — ELLE N'EST RECOPIEE NULLE PART.        (2026-08-22, 2e passage)
   Ce n'est pas un chargeur : c'est une ARRIVEE. L'ecran n'est plus retenu par un
   seuil de duree (il s'affiche desormais TOUJOURS, meme tres brievement), et il
   n'est retire qu'une fois cette course finie — sinon on verrait des barres
   monter a mi-hauteur puis sauter d'un coup, ce qui serait pire que rien.
   `js/main.js` lit `animation-duration` sur cet element meme (`getComputedStyle`)
   pour savoir combien de temps le garder : changer la duree ICI suffit.
   ⚠️ « MOUVEMENT REDUIT » LA MET A ZERO, ET C'EST COHERENT : la lecture rend
   alors 0 ms, l'ecran n'est plus retenu du tout, et l'etat final est le meme. */
.rs-attente { margin-top: 10px; animation: att-entree .3s ease-out both; }
@keyframes att-entree { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* ⚠️ PERSONNE N'ATTEND UNE ANIMATION : au premier geste du joueur, `att-vu` fait
   SAUTER l'arrivee a son etat final — l'ecran entier et les barres deja
   allumees. Meme geste que la carte de l'accueil (`#hm-carte.att-vu`). */
.rs-attente.att-vu { animation: none; opacity: 1; transform: none; }
.rs-attente.att-vu .att-cal i.on { animation: none;
  background: linear-gradient(180deg, #EFC15C, #D99A21); transform: scaleY(1); }
@media (prefers-reduced-motion: reduce) { .rs-attente { animation: none; } }
.rs-att-dit { font-size: .78rem; font-weight: 700; color: var(--txt-dim); margin: 0 0 10px; }

/* ==========================================================================
   LE CALENDRIER QUI SE JOUE — L'ETAT D'ATTENTE DE LA FIN DE SAISON
                                                             (2026-08-22)

   ⚠️ IL REMPLACE HUIT BLOCS GRIS (`.rs-att-g` / `.rs-att-c`, retires le meme
   jour) QUI NE DISAIENT RIEN DE CE QUI AVANCAIT. Une barre par tournoi du
   calendrier de la saison ; chacune s'allume quand SON TOURNOI EST REELLEMENT
   SIMULE — c'est `js/main.js` qui pose `on`, sur ce que le moteur lui dit, et
   jamais sur un minuteur.

   ⚠️ CE BLOC PORTE DES COULEURS LITTERALES, ET C'EST LA SEULE FAMILLE DE REGLES
   DE CET ECRAN QUI EN PORTE. La maquette validee par le proprietaire les fournit
   VERBATIM : le blanc d'une barre non jouee, l'or de la barre acquise, le gris
   des mois. ⚠️ CONSEQUENCE ASSUMEE, ET ELLE EST ECRITE DANS `CLAUDE-transitions.md`
   §8 : ces six valeurs NE SUIVENT PAS les 37 themes. Elles ne s'etendent a rien
   d'autre, et il ne faut pas s'en servir d'exemple ailleurs.
   ⚠️ CE BLOC EST PLACE AVANT LE MARQUEUR « ECRAN PROGRESSION » DE LA FEUILLE, ET
   CE N'EST PAS UN HASARD : deux controles lisent la feuille DEPUIS ce marqueur
   JUSQU'A LA FIN et y refusent tout hexadecimal. Deplacer ce bloc plus bas les
   ferait tomber.

   ⚠️ LES BARRES SONT DU DECOR PUR (`aria-hidden`) : elles ne portent aucune
   valeur et n'en suggerent aucune. Ce sont les deux phrases — le libelle de
   phase en `role="status"` et le nom du tournoi en cours — qui disent ce qui se
   passe a qui n'a pas les yeux dessus. */
/* ⚠️ `--att-pas` EST LE PAS ENTRE DEUX BARRES, ET C'EST LUI QUI DONNE SON RYTHME
   A L'ECRAN D'ATTENTE.                                 (2026-08-22, 4e passage)
   `js/main.js` le LIT ici (`getPropertyValue`) et n'en detient aucune copie :
   le calendrier se remplit en `--att-pas` x (nombre de barres - 1) + la duree de
   `att-allume`. Changer le rythme, c'est changer ce nombre ICI, et rien d'autre.
   ⚠️ IL EST PASSE DE 45 A 130 MS LE 2026-08-22 (4e PASSAGE), ET LE PROPRIETAIRE
   L'A DEMANDE EN CES TERMES : « meme si elle dure plus d'une voire deux secondes
   voire plus, l'essentiel c'est que ce soit style, fluide et smooth ». A 45 ms,
   les seize barres tombaient en 975 ms et le NOM DU TOURNOI changeait seize fois
   en moins d'une seconde — illisible. A 130 ms, une saison de seize tournois se
   remplit en 2 250 ms et chaque nom tient le temps d'etre lu. Ce n'est pas un
   chiffre rond choisi pour lui-meme : c'est le pas a partir duquel le nom se
   lit, et la duree en decoule.
   ⚠️ CE PAS NE FAIT QUE RETARDER : une barre ne s'allume JAMAIS avant que son
   tournoi ne soit reellement simule. Sur un processeur lent, c'est le moteur qui
   mene et le pas ne se voit pas ; sur une machine rapide, c'est le pas qui mene
   et le calcul est fini depuis longtemps. On etire une attente, on n'annonce
   jamais un resultat qui n'existe pas. */
/* ⚠️ `--att-min` EST LE PLANCHER D'AFFICHAGE DU CALENDRIER DE LA FIN DE SAISON
   — et, depuis le 2026-08-23 (decision du proprietaire : « instantane »), PLUS
   CELUI DU LANCEMENT : `#boot` se leve des que l'accueil est monte, sans
   attendre ce plancher. IL N'A QU'UN SEUL DOMICILE, CETTE LIGNE.
                                                           (2026-08-22, 4e passage
                                                            ; restreint au
                                                            calendrier le 2026-08-23)
   Le pas ci-dessus suffit tant que le calendrier est long ; une saison courte
   retomberait sous les deux secondes que le proprietaire demande. Le calendrier
   LIT cette valeur (`getPropertyValue`, `js/main.js`) et n'en detient aucune
   copie : c'est un PLANCHER, jamais un delai — si le calcul dure plus
   longtemps, c'est lui qui mene et l'ecran reste jusqu'a sa fin.
   ⚠️ IL RESTE DECLARE SUR LA RACINE PARCE QUE L'ECRAN D'ATTENTE DU BILAN EN
   HERITE. L'ecrire deux fois, c'etait deux verites a faire diverger au premier
   reglage.
   ⚠️ « MOUVEMENT REDUIT » LE MET A ZERO, comme le pas et les animations : plus
   rien ne retient l'ecran, l'etat final est le meme. */
:root { --att-min: 2000ms; }
@media (prefers-reduced-motion: reduce) { :root { --att-min: 0ms; } }
.att-cal { display: flex; gap: 4px; margin: 16px 2px 0; --att-pas: 130ms; }
.att-cal i { flex: 1; height: 26px; border-radius: 5px; background: #fff;
  box-shadow: 0 1px 3px rgba(35, 55, 95, .10); transform-origin: bottom; }
.att-cal i.on { animation: att-allume .30s ease-out forwards; }
@keyframes att-allume {
  0% { background: #fff; transform: scaleY(1); }
  45% { background: #F3D383; transform: scaleY(1.35); }
  100% { background: linear-gradient(180deg, #EFC15C, #D99A21); transform: scaleY(1); }
}
/* ⚠️ `att-deja` A ETE RETIREE LE 2026-08-22 (3e passage), ET IL NE FAUT PAS LA
   REMETTRE. Elle posait sans animation les barres deja acquises au moment ou
   l'ecran arrivait — utile tant qu'un seuil de 150 ms retenait l'ecran, car on
   pouvait alors se poser avec cinq tournois derriere soi et cinq eclairs
   simultanes n'auraient rien voulu dire. Le calendrier arrive desormais ETEINT
   dans tous les cas et se remplit au pas : il n'y a plus de rattrapage a faire,
   et le rattrapage aurait justement supprime l'animation que cet ecran existe
   pour montrer. */
.att-mois { display: flex; gap: 4px; margin-top: 5px; }
.att-mois span { flex: 1; font-size: 7.5px; font-weight: 800; color: #8A93A5;
  text-align: center; letter-spacing: .02em; }
/* Le tournoi en cours. ⚠️ SA PLACE EST TENUE MEME VIDE (`min-height`) : elle se
   vide quand la saison est jouee, et une ligne qui disparait ferait sauter tout
   ce qui est au-dessus. */
.att-en { margin: 9px 2px 0; min-height: 1.1em; font-size: .74rem;
  font-weight: 700; color: var(--txt-dim); }
/* ⚠️ MOUVEMENT REDUIT : les barres acquises gardent leur or, elles ne clignotent
   pas. On coupe l'animation, jamais l'information.
   ⚠️ ET LE PAS TOMBE A ZERO, SANS QUOI LA DUREE MINIMALE SUBSISTERAIT : le
   calendrier se remplirait encore en un peu moins d'une seconde, barre apres
   barre, alors que le joueur a demande qu'on ne l'anime pas. A zero, tout
   s'allume d'un coup et plus rien ne retient l'ecran — meme regle que
   `animation-duration`, que ce bloc met deja a zero. */
@media (prefers-reduced-motion: reduce) {
  .att-cal { --att-pas: 0ms; }
  .att-cal i.on { animation: none;
    background: linear-gradient(180deg, #EFC15C, #D99A21); transform: scaleY(1); }
}

.rs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.rs-card {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; min-height: 80px; padding: 10px 8px 9px; position: relative;
  font-family: inherit; text-align: center; cursor: pointer;
  background: var(--bg-card); color: var(--txt);
  border: 1px solid var(--line); border-radius: 16px;
}
.rs-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rs-c-main { font-size: 1.5rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 5px; }
.rs-c-main.ic { line-height: 0; }
.rs-c-main .rs-ico svg { width: 28px; height: 28px; display: block; }
.rs-c-em { font-size: 1.35rem; line-height: 1; }
.rs-c-lab { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .6px;
  color: var(--txt-dim); line-height: 1.12; }
.rs-chev { position: absolute; right: 9px; top: 7px; font-size: .8rem; line-height: 1;
  color: var(--txt-faint); transition: transform .18s ease; }
.rs-card.ouvert .rs-chev { transform: rotate(180deg); }
.rs-badge { font-size: .66rem; font-weight: 800; padding: 2px 6px; border-radius: 999px;
  background: var(--bg-3); color: var(--txt-dim); vertical-align: middle; }
.rs-badge.up { color: var(--good); } .rs-badge.down { color: var(--bad); }
.rs-pos { color: var(--good); } .rs-neg { color: var(--bad); }
.rs-panel { grid-column: 1 / -1; padding: 2px 2px 6px; }
.rs-panel[hidden] { display: none; }
.rs-panel .section-label { margin-top: 14px; }
.rs-panel .section-label:first-child { margin-top: 4px; }
.rs-alerte { font-size: .82rem; color: var(--bad); margin: 6px 0 0; }
.rs-cal-l { font-size: .86rem; margin: 2px 0 8px; }
.rs-chronique { font-size: .8rem; line-height: 1.45; margin: 0 0 8px; }
.rs-leg { font-size: .72rem; color: var(--txt-faint); margin: 4px 0 0; text-align: center; }
.rs-leg-moy { letter-spacing: -1px; }
.rs-vide { font-size: .8rem; margin: 6px 0; }
.rs-chips-best { margin-bottom: 4px; }

/* Courbes (SVG original) : le trace prend la largeur disponible, la boite garde
   ses proportions. Aucune animation, donc rien a conditionner au reglage de
   reduction des animations. */
.rs-courbe { margin: 6px 0 0; }
.rs-courbe svg { width: 100%; height: auto; display: block; overflow: visible; }
.rsc-line { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.rsc-moy { stroke: var(--txt-faint); stroke-width: 1.2; stroke-dasharray: 5 4; }
.rsc-pt { fill: var(--accent); }
.rsc-pt.best { fill: var(--good); }
.rsc-pt.fin { fill: var(--accent-2, var(--accent)); stroke: var(--bg-card); stroke-width: 1.6; }
.rsc-txt { fill: var(--txt-faint); font-size: 10px; font-weight: 700; }

/* Liste des titres de la saison (case « Trophees ») : le trophee, le nom, la
   famille et la ville, l'equipe. Aucun montant — le detail financier a sa case. */
.rs-titres { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.rs-titre { display: flex; align-items: center; gap: 10px; padding: 9px 10px;
  border: 1px solid var(--line); border-radius: 13px; background: var(--bg-2); }
.rs-titre.major { border-color: var(--accent); }
.rst-tr { flex: 0 0 auto; line-height: 0; }
.rst-b { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rst-n { font-weight: 700; font-size: .9rem; }
.rst-maj { font-style: normal; font-size: .62rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .8px; color: var(--accent-2, var(--accent)); margin-left: 4px; }
.rst-m { font-size: .74rem; color: var(--txt-dim); }
.rst-e { display: inline-flex; align-items: center; gap: 5px; font-size: .76rem; color: var(--txt-dim); }

/* Bandeau du Grand Slam : pleine largeur, dore, distinct des cases. Le lingot est
   le trophee DEJA dessine par le jeu (famille `GrandSlam`), il n'est pas redessine.
   Barre segmentee : une case par titre requis, remplie a hauteur des titres acquis. */
.gsb { display: flex; align-items: flex-start; gap: 11px; margin-top: 12px; padding: 11px 13px;
  border: 1px solid var(--accent); border-radius: 18px; background: var(--bg-card); }
.gsb-ic { flex: 0 0 auto; line-height: 0; }
.gsb-b { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1 1 auto; }
.gsb-t { font-weight: 800; font-size: .92rem; color: var(--accent-2, var(--accent)); }
.gsb-bar { display: flex; align-items: center; gap: 9px; }
.gsb-seg { display: flex; gap: 5px; flex: 1 1 auto; }
.gsb-seg i { flex: 1 1 0; height: 9px; border-radius: 999px; background: var(--bg-3); }
.gsb-seg i.on { background: var(--accent); }
.gsb-n { flex: 0 0 auto; font-size: .8rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.gsb-l { font-size: .78rem; line-height: 1.35; color: var(--txt-dim); }
.gsb-d { font-size: .72rem; line-height: 1.35; color: var(--txt-faint); }

/* ------------------------------- theme clair « Clair doux » ------------------- */
html.theme-clair .rs-card {
  background: var(--ds-card); border: 0; border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); color: var(--ds-text);
}
html.theme-clair .rs-card.gold { background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep); }
html.theme-clair .rs-card.gold .rs-c-lab { color: var(--ds-accent-deep); opacity: .8; }
html.theme-clair .rs-c-lab { color: var(--ds-text-dim); }
html.theme-clair .rs-chev { color: var(--ds-text-faint); }
html.theme-clair .rs-c-main .rs-ico { color: var(--ds-accent-deep); }
html.theme-clair .rs-badge { background: var(--ds-track); color: var(--ds-text-dim); }
html.theme-clair .rs-badge.up { color: var(--ds-good); }
html.theme-clair .rs-badge.down { color: var(--ds-bad); }
html.theme-clair .rs-pos { color: var(--ds-good); }
html.theme-clair .rs-neg { color: var(--ds-bad); }
html.theme-clair .rs-panel {
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 12px 13px 14px;
}
html.theme-clair .rs-titre { background: var(--ds-bg-1); border: 0; border-radius: var(--ds-radius-tile); }
html.theme-clair .rs-titre.major { background: var(--ds-accent-soft-bg); }
html.theme-clair .rst-maj { color: var(--ds-accent-deep); }
html.theme-clair .rsc-line { stroke: var(--ds-accent-deep); }
html.theme-clair .rsc-pt { fill: var(--ds-accent-deep); }
html.theme-clair .rsc-pt.best { fill: var(--ds-good); }
html.theme-clair .rsc-pt.fin { fill: var(--ds-accent-deep); stroke: var(--ds-card); }
html.theme-clair .rsc-moy { stroke: var(--ds-text-faint); }
html.theme-clair .rsc-txt { fill: var(--ds-text-faint); }
html.theme-clair .gsb {
  background: var(--ds-accent-soft-bg); border: 0; border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-tile);
}
html.theme-clair .gsb-t { color: var(--ds-accent-deep); }
html.theme-clair .gsb-ic { color: var(--ds-accent-deep); }
html.theme-clair .gsb-seg i { background: var(--ds-accent-dim); }
html.theme-clair .gsb-seg i.on { background: linear-gradient(90deg, var(--ds-fill-1), var(--ds-fill-2)); }
html.theme-clair .gsb-l { color: var(--ds-accent-deep); }
html.theme-clair .gsb-d { color: var(--ds-text-dim); }

/* =========================================================================
   RANGEE « GRAND SLAM + STICKER DE LA SAISON »                (2026-08-09)

   Le bandeau du Grand Slam et la carte du sticker partagent UNE rangee de la
   MEME grille que les huit tuiles : l'ecran ne gagne donc pas une rangee, il
   en reutilise une. Le bandeau n'est pas redessine — ces regles ne touchent
   que sa GEOMETRIE en demi-largeur (le titre y tient sur deux lignes).

   ⚠️ AUCUNE COULEUR N'EST DECLAREE ICI. Le fond de nuit de la vignette et
   celui de l'apercu des armes REUTILISENT `.ar-vit` / `.ar-vit-n` — la seule
   exception de couleur declaree du jeu (`sansVitrine` de suite.js), parce que
   les armes sont dessinees claires et qu'un aplat clair les efface. En ouvrir
   une seconde serait refuse par les quatre controles « aucun hexadecimal hors
   des jetons ». Ces regles ne changent que la geometrie, comme `.ar-mo-v`.
   ========================================================================= */
.rs-rang-gs .gsb { margin-top: 0; border-radius: 16px; padding: 9px 10px; gap: 7px; }
.rs-rang-gs .gsb-ic svg { width: 26px; height: auto; }
.rs-rang-gs .gsb-b { gap: 4px; }
.rs-rang-gs .gsb-t { font-size: .78rem; line-height: 1.18; }
.rs-rang-gs .gsb-bar { gap: 6px; }
.rs-rang-gs .gsb-n { font-size: .72rem; }
.rs-rang-gs .gsb-l { font-size: .68rem; line-height: 1.28; }
.rs-rang-gs .gsb-d { font-size: .64rem; line-height: 1.28; }

/* LA CARTE REPLIEE : vignette sur fond de nuit, nom en gros, libelle en
   petites capitales — la presentation « 1.22 / RATING ANNUEL » des huit
   tuiles, avec le meme chevron, qui vient de `.rs-card`. */
/* ⚠️ SELECTEURS COMPOSES A DESSEIN. `.ar-vit` et `.ar-vit-n` sont declarees PLUS
   BAS dans cette feuille : a specificite egale elles gagneraient, et la vignette
   reprendrait le rembourrage de la grande vitrine (28 px) plus sa marge basse de
   16 px — la carte depassait de 42 px, et l'ecran s'allongeait d'autant. On
   qualifie donc chaque regle par son conteneur. */
.rs-card.rs-st { justify-content: center; gap: 4px; padding: 8px; }
.rs-card.rs-st .rs-c-main { flex-direction: column; gap: 5px; max-width: 100%; }
.rs-card .rs-st-v { display: flex; align-items: center; justify-content: center;
  padding: 6px; margin: 0; border-radius: 12px; box-shadow: none; }
.rs-card .rs-st-nul { display: flex; align-items: center; justify-content: center;
  height: 40px; margin: 0; padding: 0 11px; font-size: .6rem; font-weight: 800;
  letter-spacing: .1em; opacity: 1; }
.rs-st-n { display: block; font-size: .88rem; font-weight: 800; line-height: 1.14;
  max-width: 100%; overflow-wrap: anywhere; }

/* L'APERCU DES QUATRE ARMES QUI PRENNENT UN STICKER — deux colonnes. */
.rs-panel .rs-st-ap { padding: 11px 10px 8px; margin: 4px 0 2px; }
.rs-st-ap-g { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; align-items: center; }
.rs-st-ap-a { display: block; line-height: 0; }
.rs-st-ap-a svg { display: block; width: 100%; height: auto; }
.rs-panel .rs-st-ap-n { margin: 9px 0 0; font-size: .64rem; text-transform: none;
  letter-spacing: 0; }

/* LE SELECTEUR D'ARME DE LA CARTE — SES PROPRES CLASSES, ET C'EST LE PRECEDENT
   DE `.ar-e` : la rangee des emplacements de « Mon arme » reprend elle aussi le
   MARQUAGE des vignettes d'arme sans porter leur classe, avec les MEMES jetons.
   ⚠️ POURQUOI PAS `.ar-a` TELLE QUELLE — LES DEUX DEGATS ONT ETE CONSTATES.
   (1) `g45 §41a` repere la rangee de « Mon arme » par la PREMIERE occurrence de
   `<span class="ar-a-i">` dans `js/main.js` : cette carte etant declaree plus
   haut, elle lui prenait sa place et le controle tombait. (2) Plusieurs scripts
   navigateur cherchent `.ar-a[data-arme]` SANS conteneur, or `#season-body`
   reste dans la page une fois l'ecran quitte.
   ⚠️ LA MISE EN PAGE EST RECOPIEE DE `.ar-a`, COMME `.ar-e` LE FAIT DEJA — mais
   AUCUNE COULEUR ne l'est : ce sont les memes jetons `--ds-*`, jamais un
   hexadecimal.
   ⚠️ LE NOMBRE DE COLONNES N'EST PAS ECRIT : les colonnes automatiques suivent le
   nombre d'armes REELLEMENT rendues. Ecrire « quatre » ici aurait fait une
   seconde source du compte, et une sixieme arme porteuse aurait deborde. */
.rs-st-sel { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 5px; margin: 0 0 12px; }
.rs-st-a { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0;
  padding: 7px 2px 6px; border-radius: var(--ds-radius-btn); cursor: pointer; font: inherit;
  background: var(--ds-field-bg); border: 1px solid var(--ds-line); color: var(--ds-text-dim); }
.rs-st-a.on { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent);
  color: var(--ds-accent-ink-fort); }
.rs-st-a-i { display: block; line-height: 0; }
.rs-st-a-i svg { display: block; width: 100%; height: auto; }
.rs-st-a-n { font-size: .56rem; font-weight: 700; letter-spacing: .02em; line-height: 1.1;
  text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 100%; }

/* LES DEUX RANGEES DE TUILES. `.ar-st` et `.ar-s` sont celles de « Mon arme » :
   il n'existe qu'UNE tuile de sticker dans le jeu, elle n'est pas recopiee ici.
   `.ar-s-p` est le seul ajout — le pseudo D'ORIGINE, sous les stickers d'une
   ancienne carriere. */
.rs-st-g { margin: 4px 0 12px; }
.rs-st-g .ar-s { display: flex; flex-direction: column; align-items: center; }
.ar-s-p { display: block; max-width: 58px; margin-top: 3px; font-size: .54rem; font-weight: 700;
  line-height: 1.15; color: var(--ds-text-faint); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
/* OU L'EXEMPLAIRE EST DEJA POSE — la marque discrete de la tuile.  (2026-08-13)
   ⚠️ MEME GABARIT QUE `.ar-s-p` : meme largeur de coupe, meme interligne — deux
   marques sous une meme vignette ne peuvent pas avoir deux metriques. Ce qui la
   distingue est la COULEUR, la meme que le liseré `.ar-s.on`, pas une taille de
   plus : elle nomme des armes, elle ne crie pas. Un sticker qui n'est pose nulle
   part n'en porte AUCUNE (le HTML ne l'ecrit pas) — un « nulle part » affiche
   aurait mis une ligne vide sous les trois quarts de la grille.
   ⚠️ DEUX LIGNES, ET C'EST MESURE : a 58 px, « Assaut, PM » tient sur une ligne
   mais « Precision, Assaut, PM » — un exemplaire pose sur TROIS armes, ce que la
   regle du 2026-08-13 rend possible — sortait en « Precision, … » et perdait les
   deux tiers de ce qu'il avait a dire. Au-dela de deux lignes la coupe reprend,
   et l'infobulle du bouton porte de toute facon la liste ENTIERE. */
.ar-s-o { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  max-width: 58px; margin-top: 2px; font-size: .52rem; font-weight: 600;
  line-height: 1.15; color: var(--ds-accent); overflow: hidden; }
.rs-st-c { font-variant-numeric: tabular-nums; }
.rs-st-abs, .rs-st-note { margin: 0 0 8px; font-size: .72rem; line-height: 1.4;
  color: var(--ds-text-faint); }

/* Les panneaux sont plus etroits que la pleine largeur de la page (ils ont leur
   propre rembourrage de carte) : on autorise la coupure des mots tres longs —
   un pseudo colle a une organisation, un motif d'absence — plutot que de laisser
   un contenu deborder de sa carte. Regle de securite, strictement limitee aux
   panneaux de l'ecran de resultats. */
.rs-panel .rec-cat, .rs-panel .rec-note, .rs-panel .rec-win,
.rs-panel .distinc-detail, .rs-panel .bc-liste li, .rs-panel .fid-list li,
.rs-panel .chg-detail, .rs-panel .rst-n, .rs-panel .rst-m { overflow-wrap: anywhere; }

/* Le kill feed entre en scene par un glissement de 16 px (`kf-in`). Dans un panneau,
   qui est plus etroit que la pleine page, ces 16 px depassaient brievement du cadre
   de la carte pendant l'animation. On les contient : le feed est desormais son propre
   cadre de defilement, les lignes glissent depuis SON bord. L'animation, sa duree et
   ses retards sont inchanges, et `prefers-reduced-motion` continue de la supprimer. */
.rs-panel .killfeed { overflow: hidden; }

/* Les trois tuiles du calendrier partagent une largeur plus etroite dans un panneau
   qu'en pleine page : a 390 px, « VOLONTAIREMENT SAUTE(S) » se coupait en plein mot.
   Un cran de moins sur l'intitule (la valeur, elle, ne bouge pas) et il tient. */
.rs-panel .bc-k { font-size: .63rem; letter-spacing: .2px; }

/* ============================================================================
   BARRE DE PROGRESSION DE CARRIERE — PUREMENT COSMETIQUE (2026-07-28)
   ----------------------------------------------------------------------------
   Posee SOUS le bloc des trois jauges de l'en-tete de saison, sur toute la
   largeur, dans l'espace qui precede la section « SAISON … ». Elle n'a NI
   libelle NI chiffre : c'est une illustration de l'avancement de la carriere,
   comme une barre de chargement. Son remplissage est calcule dans la couche
   d'affichage (js/ui.js) a partir de l'age deja montre juste au-dessus, borne
   0-100 % ; AUCUNE mecanique de jeu ne le lit ni ne s'en sert.
   Les TROIS JAUGES ne sont pas touchees : elles gardent leur grille, leur
   ecartement et leur alignement. Les 15 px de marge separent franchement la
   barre du bloc au-dessus, pour qu'elle se lise comme un element distinct et
   non comme une quatrieme jauge (qui, elle, porterait un libelle et un nombre).
   ============================================================================ */
.hud-progress {
  margin: 15px 0 0;
  height: 8px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--bg-3, #1b1b22);
  overflow: hidden;                 /* le remplissage ne deborde jamais de la piste */
}
.hud-progress-fill {
  height: 100%;
  width: 0;                          /* valeur reelle posee par js/ui.js (renderHud) */
  border-radius: inherit;            /* coins arrondis complets, aux deux extremites */
  background: linear-gradient(90deg, var(--ds-accent-light, #E7A94A), var(--ds-accent, #E39A1F));
  transition: width .45s ease;
}
@media (prefers-reduced-motion: reduce) { .hud-progress-fill { transition: none; } }

/* THEME CLAIR — la piste devient blanche, avec un contour INTERNE tres discret
   (une ombre en `inset`, jamais une bordure : une bordure ajouterait de la
   hauteur et casserait l'epaisseur de 8 px voulue). Le remplissage garde le
   degrade dore du theme. */
html.theme-clair .hud-progress {
  background: var(--ds-card);
  box-shadow: inset 0 0 0 1px rgba(30,45,80,.06);
}

/* ============================================================================
   ECRAN DE FIN DE CARRIERE « TA LEGENDE » — refonte 2026-07-28
   ----------------------------------------------------------------------------
   L'ecran reprend l'ossature de l'ecran de fin de saison : les CASES et les
   PANNEAUX sont les composants `.rs-card` / `.rs-panel` deja definis plus haut,
   rien n'est duplique. Ne sont declarees ici que les parties qui lui sont
   propres : le HERO, ses deux tuiles, les bulles de tier du parcours, la section
   doree du Grand Slam et le pied de boutons. Tout le reste (cartes blanches,
   boutons, libelles de section, courbes, vitrine des trophees) vient du theme.
   ============================================================================ */

/* --- Eyebrow + hero ------------------------------------------------------- */
.fc-eyebrow { font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 1.5px;
  color: var(--accent); margin-bottom: 8px; }
.fc-hero { text-align: center; padding: 16px 14px 14px; border-radius: var(--radius, 18px); background: var(--bg-card); }
.fc-honor { font-size: 1.6rem; font-weight: 800; line-height: 1.15; color: var(--accent); }
.fc-desc { margin-top: 7px; }
.fc-descp { display: inline-block; padding: 3px 12px; border-radius: 999px; font-size: .74rem; font-weight: 700; }
.fc-id { margin-top: 9px; font-size: .82rem; color: var(--txt-dim); overflow-wrap: anywhere; }
.fc-id .flagico { font-size: 1rem; line-height: 1; }
.fc-id .flagsvg { width: 18px; height: 13px; vertical-align: -2px; border-radius: 2px; }
.fc-rev { margin: 9px 0 0; font-size: .82rem; font-style: italic; line-height: 1.45; color: var(--txt-dim); }
/* Les DEUX tuiles du hero : leur chiffre est a la meme taille que celui des cases
   (`.rs-c-main`), pour que le regard lise une seule et meme famille de chiffres. */
.fc-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 13px; }
.fc-tile { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 10px 6px; min-height: 62px; border-radius: 14px; background: var(--bg-3); }
.fc-t-v { font-size: 1.5rem; font-weight: 800; line-height: 1.05; font-variant-numeric: tabular-nums; }  /* meme taille que .rs-c-main */
.fc-t-k { font-size: .62rem; font-weight: 800; text-transform: uppercase; letter-spacing: .6px;
  text-align: center; color: var(--txt-dim); }
/* Mentions courtes sous le hero (mode Defi, avantages equipes) : rares par nature. */
.fc-note { margin: 9px 0 0; font-size: .74rem; text-align: center; color: var(--txt-faint); overflow-wrap: anywhere; }

/* --- Section doree du GRAND SLAM, en tete de la case « Trophees » ---------
   Le lingot est celui que `js/emblems.js` dessine deja : il n'est pas redessine,
   seule sa boite est posee ici. Aucun montant n'apparait dans ce bloc. */
.fc-gs { margin-bottom: 12px; padding: 11px 12px; border-radius: 15px;
  background: rgba(242,193,78,.10); border: 1px solid rgba(242,193,78,.30); }
.fc-gs-h { display: flex; align-items: center; gap: 10px; }
.fc-gs-ic { flex: 0 0 auto; line-height: 0; }
.fc-gs-t { font-size: .92rem; font-weight: 800; color: var(--accent); overflow-wrap: anywhere; }
.fc-gs-x { font-weight: 800; }
.fc-gs-l { margin-top: 8px; display: flex; flex-direction: column; gap: 7px; }
.fc-gs-line { display: flex; flex-direction: column; gap: 2px; }
.fc-gs-org { display: flex; align-items: center; gap: 6px; font-size: .82rem; font-weight: 700; }
.fc-gs-org .emb { flex: 0 0 auto; }
.fc-gs-d { font-size: .74rem; line-height: 1.35; color: var(--txt-dim); overflow-wrap: anywhere; }

/* --- Parcours : une ligne par equipe, bulle de tier coloree, annee a droite -- */
.fc-parcours { display: flex; flex-direction: column; gap: 6px; }
.fc-p-line { display: flex; align-items: center; gap: 8px; }
.fc-p-team { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1 1 auto;
  font-size: .84rem; font-weight: 700; }
.fc-p-team > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fc-p-an { flex: 0 0 auto; font-size: .76rem; font-variant-numeric: tabular-nums; color: var(--txt-faint); }
/* ECHELLE DE RARETE : Amateur gris, Tier 3 vert, Tier 2 bleu, Tier 1 violet,
   Tier S dore. Chaque pastille porte un liseré de sa propre couleur. */
.fc-tier { flex: 0 0 auto; padding: 2px 9px; border-radius: 999px; font-size: .64rem; font-weight: 800;
  letter-spacing: .3px; white-space: nowrap; border: 1px solid transparent; }
.fc-tier-am { color: #9aa3b2; background: rgba(154,163,178,.14); border-color: rgba(154,163,178,.42); }
.fc-tier-t3 { color: #43b581; background: rgba(67,181,129,.14); border-color: rgba(67,181,129,.42); }
.fc-tier-t2 { color: #4a90d9; background: rgba(74,144,217,.14); border-color: rgba(74,144,217,.42); }
.fc-tier-t1 { color: #9b7ede; background: rgba(155,126,222,.16); border-color: rgba(155,126,222,.44); }
.fc-tier-ts { color: #d1a02f; background: rgba(242,193,78,.16); border-color: rgba(242,193,78,.48); }

.fc-brut { margin: 0 0 6px; font-size: .84rem; }
/* Repere de DEBUT sur la courbe de carriere (les autres reperes existaient deja). */
.rsc-pt.debut { fill: var(--info, #4a90d9); }

/* --- Pied de boutons ------------------------------------------------------ */
.fc-actions { margin-top: 16px; display: flex; flex-direction: column; gap: 9px; }
.fc-actions .btn { margin: 0; }

/* ============================ THEME « CLAIR DOUX » ========================= */
html.theme-clair .fc-eyebrow { color: var(--ds-accent-deep); }
/* HERO : carte doree claire, centree, sans bordure — la seule surface doree de
   l'ecran, pour que le titre de prestige reste le point d'entree du regard. */
html.theme-clair .fc-hero {
  background: var(--ds-accent-soft-bg); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-tile);
}
html.theme-clair .fc-honor { color: var(--ds-accent-deep); }
html.theme-clair .fc-descp { background: var(--ds-card); color: var(--ds-accent-deep); }
html.theme-clair .fc-id { color: var(--ds-text); }
html.theme-clair .fc-rev { color: var(--ds-accent-deep); opacity: .92; }
/* Les deux tuiles du hero sont BLANCHES sur le dore, comme les tuiles-stats de
   l'en-tete de saison le sont sur le fond. */
html.theme-clair .fc-tile {
  background: var(--ds-card); border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair .fc-t-v { color: var(--ds-accent-deep); }
html.theme-clair .fc-t-k { color: var(--ds-text-dim); }
html.theme-clair .fc-note { color: var(--ds-text-dim); }
html.theme-clair .fc-gs {
  background: var(--ds-accent-soft-bg); border: 0; border-radius: var(--ds-radius-tile);
}
html.theme-clair .fc-gs-t { color: var(--ds-accent-deep); }
html.theme-clair .fc-gs-d { color: var(--ds-accent-deep); opacity: .85; }
html.theme-clair .fc-p-an { color: var(--ds-text-faint); }
html.theme-clair .rsc-pt.debut { fill: var(--ds-info); }
/* « Retour a l'accueil » : bouton secondaire BLANC a contour leger, distinct du
   dore de l'action principale (« Nouvelle carriere »). */
html.theme-clair #screen-end .fc-quiet {
  background: var(--ds-card); color: var(--ds-text-dim);
  border: 1px solid var(--ds-line); border-radius: var(--ds-radius-btn);
  box-shadow: none; font-weight: 700;
}
html.theme-clair #screen-end .fc-quiet:hover { color: var(--ds-text); border-color: var(--ds-line-hover); }

/* VITRINE DES TROPHEES sur fond clair. Les groupes « Major » et « Grand Slam »
   portaient un DEGRADE SOMBRE (`#221d11` / `#221b0f`), calcule pour un fond
   presque noir : dans un panneau blanc il perce la carte en bloc marron. Meme
   traitement qu'au lot 0 pour les socles des emblemes — la surface passe sur la
   pastille doree du theme, le liseré dore et le DESSIN des trophees ne bougent
   pas d'un pixel. Le theme sombre, lui, reste inchange (regles scopees). */
html.theme-clair .tshow-group { background: var(--ds-bg-1); border-color: transparent; border-radius: var(--ds-radius-tile); }
html.theme-clair .tshow-group.major,
html.theme-clair .tshow-group.grandslam { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent); }
html.theme-clair .tshow-fam { color: var(--ds-accent-deep); }
html.theme-clair .tshow-lab { color: var(--ds-text); }
html.theme-clair .tshow-anterieur { background: var(--ds-bg-1); border-color: var(--ds-line); color: var(--ds-text-dim); }

/* =============================================================================
   ECRAN « CREE TON JOUEUR » — THEME CLAIR ET CONDENSATION (2026-07-28)
   -----------------------------------------------------------------------------
   PRESENTATION SEULE. Aucun texte, aucune valeur, aucune regle, aucun choix ne
   change : memes 5 roles, memes 26 nationalites et leurs niveaux de difficulte,
   memes 3 styles de vie, memes descriptions, meme validation du pseudo, memes
   actions. L'ecran bascule au theme clair par la seule entree `screen-create` de
   la table `ECRANS_CLAIRS` (js/ui.js) — la retirer, avec ce bloc, rend l'ecran a
   son apparence sombre d'origine.

   CE QUI ETAIT DEJA LA ET SERT TEL QUEL : le fond clair et sa texture, le
   REMAPPAGE des variables historiques (le titre d'ecran, le champ de saisie sur
   `--bg-2` devenu blanc, son liseré de focus sur `--accent` devenu l'or), le
   BOUTON PRINCIPAL (`html.theme-clair .btn-primary`) et le composant de bouton
   secondaire en carte blanche (`.ds-btn-card`). Ne restent ci-dessous que les
   trois cartes de groupe, les puces de choix, le selecteur repliable de
   nationalite et les points de difficulte.

   PORTEE : tout est scope a `#screen-create`. Aucun autre ecran n'est touche —
   `.card` et `.chip` servent aussi ailleurs (chips d'effets, cartes de choix),
   et ces regles ne peuvent pas les atteindre.
   ============================================================================= */

html.theme-clair #screen-create {
  /* Couleurs propres aux puces de choix : un gris-bleu du meme axe que le fond et
     la piste du theme, et la pastille doree pour l'etat selectionne. */
  --cp-bg: var(--ds-field-bg);  /* fond d'une puce au repos */
  --cp-line: var(--ds-line);        /* son contour */
  --cp-sel-bg: var(--ds-accent-soft-bg);      /* fond d'une puce selectionnee */
  --cp-sel-line: var(--ds-accent);  /* son contour */
  --cp-sel-txt: var(--ds-accent-ink);  /* son texte */
  --cp-dot-off: var(--ds-line-hover);     /* point de difficulte eteint */
}

/* --- Champ pseudo : plus de libelle au-dessus, le placeholder le porte. ------ */
html.theme-clair #screen-create .field { margin-bottom: 12px; }
html.theme-clair #screen-create input[type=text] {
  border-radius: 16px; border: 1px solid var(--ds-line);
  padding: 13px 16px; min-height: 48px; box-shadow: var(--ds-shadow-tile);
}
html.theme-clair #screen-create input[type=text]:focus {
  border-color: var(--ds-accent); box-shadow: 0 0 0 3px rgba(227,154,31,.16);
}

/* --- Les trois groupes, chacun dans sa carte flottante ---------------------- */
html.theme-clair #screen-create .create-card {
  background: var(--ds-card); border: 0;
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow);
  padding: 13px 15px 14px;
  margin-bottom: 12px;
}
/* Le libelle de section perd sa grosse marge : la carte fait deja la separation. */
html.theme-clair #screen-create .group-title {
  margin: 0 0 9px; font-size: .72rem; letter-spacing: 1.4px;
  color: var(--ds-accent-deep); font-weight: 800;
}

/* --- Puces de choix (roles, styles de vie) ---------------------------------- */
/* `.cards` est une grille dans le theme d'origine ; en puces c'est une rangee qui
   se replie. La classe `.card` est CONSERVEE sur chaque puce (contrat du DOM), ses
   regles de carte sont donc entierement neutralisees ici. */
html.theme-clair #screen-create .cards-pills { display: flex; flex-wrap: wrap; gap: 7px; }
html.theme-clair #screen-create .cards-pills .card {
  font: inherit; font-size: .84rem; line-height: 1.2;
  background: var(--cp-bg); color: var(--ds-text);
  border: 1.5px solid var(--cp-line); border-radius: var(--ds-radius-pill);
  padding: 8px 13px; cursor: pointer; text-align: center;
  transition: background .15s, border-color .15s, color .15s;
  -webkit-tap-highlight-color: transparent;
}
html.theme-clair #screen-create .cards-pills .card:hover { border-color: var(--ds-line-hover); }
html.theme-clair #screen-create .cards-pills .card.selected {
  background: var(--cp-sel-bg); border-color: var(--cp-sel-line); color: var(--cp-sel-txt); font-weight: 700;
}
/* Description du SEUL choix selectionne. La hauteur minimale evite que la carte
   saute quand on passe d'un choix a l'autre, ou depuis l'etat « rien de choisi ». */
html.theme-clair #screen-create .pick-desc {
  margin: 8px 0 0; font-size: .81rem; line-height: 1.4;
  color: var(--ds-text-dim); min-height: 36px;
}
html.theme-clair #screen-create .pick-desc strong { color: var(--ds-text); font-weight: 700; }

/* --- Selecteur de nationalite : ligne repliee + panneau ---------------------- */
html.theme-clair #screen-create .nat-toggle {
  display: flex; align-items: center; gap: 7px; width: 100%;
  font: inherit; text-align: left; cursor: pointer;
  background: var(--cp-bg); color: var(--ds-text);
  border: 1.5px solid var(--cp-line); border-radius: 14px;
  padding: 9px 12px; min-height: 44px;
  -webkit-tap-highlight-color: transparent;
}
html.theme-clair #screen-create .nat-toggle:hover { border-color: var(--ds-line-hover); }
html.theme-clair #screen-create .nat-cur { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1 1 auto; }
html.theme-clair #screen-create .nat-cur-nom {
  font-size: .91rem; font-weight: 700; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
html.theme-clair #screen-create .nat-cur-nom.nat-cur-vide { color: var(--ds-text-dim); font-weight: 600; }
html.theme-clair #screen-create .nat-cur-lab { font-size: .75rem; color: var(--ds-text-dim); white-space: nowrap; }
/* Chevron dore, cale a droite ; il pivote quand le panneau est ouvert. */
html.theme-clair #screen-create .nat-chev {
  flex: 0 0 auto; margin-left: auto; color: var(--ds-accent);
  transition: transform .18s ease;
}
html.theme-clair #screen-create .nat-toggle.open .nat-chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  html.theme-clair #screen-create .nat-chev { transition: none; }
}

html.theme-clair #screen-create .nat-panel { margin-top: 10px; }
html.theme-clair #screen-create .nat-legende {
  margin: 0 0 8px; font-size: .72rem; color: var(--ds-text-dim); line-height: 1.5;
}
html.theme-clair #screen-create .nat-note {
  margin: 9px 0 0; font-size: .72rem; color: var(--ds-text-faint); line-height: 1.45;
}
html.theme-clair #screen-create .chips { gap: 6px; }
html.theme-clair #screen-create .chips .chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .78rem; line-height: 1.2;
  background: var(--cp-bg); color: var(--ds-text);
  border: 1.5px solid var(--cp-line); border-radius: var(--ds-radius-pill);
  padding: 6px 11px;
}
html.theme-clair #screen-create .chips .chip:hover { border-color: var(--ds-line-hover); }
html.theme-clair #screen-create .chips .chip.selected {
  background: var(--cp-sel-bg); border-color: var(--cp-sel-line); color: var(--cp-sel-txt); font-weight: 700;
}

/* --- Points de difficulte ---------------------------------------------------
   Trois pastilles rondes. Niveau 1 : une seule, VERTE. Niveaux 2 et 3 : deux puis
   trois, en OR. Les pastilles eteintes sont pleines et neutres (elles etaient
   creusees d'un filet sur fond sombre, illisible sur fond clair). Le NIVEAU de
   chaque pays vient de data/nationalites.json et n'est pas touche. */
html.theme-clair #screen-create .nat-diff { gap: 2.5px; }
html.theme-clair #screen-create .nat-diff i { width: 5.5px; height: 5.5px; }
html.theme-clair #screen-create .nat-diff i.off { background: var(--cp-dot-off); box-shadow: none; opacity: 1; }
html.theme-clair #screen-create .nat-diff-court i.on { background: var(--ds-good); }
html.theme-clair #screen-create .nat-diff-moyen i.on,
html.theme-clair #screen-create .nat-diff-long i.on { background: var(--ds-accent); }
html.theme-clair #screen-create .nat-leg-item { display: inline-flex; align-items: center; gap: 4px; }

/* --- Les deux actions, cote a cote ------------------------------------------
   « Retour » prend un tiers de la largeur et reprend le bouton secondaire en carte
   blanche du theme ; « Lancer la carriere » prend les deux tiers et garde le
   bouton principal dore commun a tous les ecrans clairs. */
html.theme-clair #screen-create .create-actions { margin-top: 14px; gap: 10px; }
/* `min-width: 0` leve le minimum AUTOMATIQUE des elements flex : sans lui, « Retour »
   ne peut pas descendre sous la largeur de son propre contenu et le partage derive
   (127 / 221 px mesures, au lieu du 116 / 232 px attendu). */
html.theme-clair #screen-create .create-actions .btn { min-height: 52px; border-radius: 16px; min-width: 0; }
html.theme-clair #screen-create .create-actions #btn-back-home {
  flex: 0 0 calc((100% - 10px) / 3); background: var(--ds-card); color: var(--ds-text);
  border: 0; box-shadow: var(--ds-shadow-tile); font-weight: 700;
}
html.theme-clair #screen-create .create-actions #btn-back-home:hover { color: var(--ds-text); box-shadow: var(--ds-shadow); }
html.theme-clair #screen-create .create-actions #btn-start { flex: 1 1 auto; font-weight: 700; }
html.theme-clair #screen-create .create-actions #btn-start:disabled { opacity: .55; cursor: default; }

/* =============================================================================
   CIRCUIT FACEIT — ELO DE LA PHASE AMATEUR                       (2026-07-29)
   Pastille d'ELO dans l'en-tete + ecran de saison amateur. Tout est pose sur les
   jetons « Clair doux » deja en place (--ds-*) : l'ecran de saison porte deja le
   theme clair, il n'y a donc rien a basculer. Aucune regle existante n'est
   modifiee — ces selecteurs sont tous nouveaux.
   ============================================================================= */

/* --- En-tete : pastille « NV 10 · 2014 ELO », a la place du rang VRS --------
   Elle prend EXACTEMENT la place que `hud-vrs-rang` occupe pendant la phase pro
   et suit les memes regles de flex (flex: 0 0 auto, nowrap) : seul le nom
   d'equipe se tronque, la pastille ne passe jamais a la ligne. */
.hud-elo { font-size: .78rem; color: var(--txt); white-space: nowrap; }
.hud-elo .hud-elo-nv { font-weight: 800; }
html.theme-clair .hud-pill .hud-elo {
  flex: 0 0 auto;                    /* jamais tronquee, jamais renvoyee a la ligne */
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink);
  border-radius: var(--ds-radius-pill);
  padding: 2px 8px 2px 3px;
  font-size: .72rem; font-weight: 700;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
html.theme-clair .hud-pill .hud-elo::before {
  content: "·"; margin: 0 5px 0 3px; color: var(--ds-text-dim); opacity: .55; font-weight: 400;
}
html.theme-clair .hud-pill .hud-elo-nv {
  background: var(--ds-accent); color: var(--ds-btn-txt);
  border-radius: 5px; padding: 3px 6px;
  font-size: .66rem; font-weight: 800; letter-spacing: .3px;
}
html.theme-clair .hud-pill .hud-elo-n { font-weight: 800; color: var(--ds-accent-ink); }
/* Repartition de la place PENDANT LA PHASE AMATEUR. La pastille d'ELO est large
   (badge de niveau + nombre + « ELO ») : sans ces deux regles, a 390 px, elle
   poussait le nom du circuit a zero pixel puis rognait le PSEUDO. Ici, le pseudo
   ne se tronque plus jamais et le nom du circuit garde une largeur lisible ; c'est
   lui, et lui seul, qui porte le « … » — la regle habituelle de l'en-tete. */
.hud-pill.amateur .hud-name { flex: 0 0 auto; }
.hud-pill.amateur .hud-team-nom { min-width: 3.5ch; }

/* --- Carte de l'ecran amateur. `.ds-card` n'existe que sous le theme clair
   (c'est l'ecran de saison, il l'a) ; ce repli garantit un rendu correct si
   l'ecran revenait un jour au theme sombre. --------------------------------- */
.fc-card { background: var(--bg-card); border-radius: var(--radius, 18px);
  padding: 16px 18px; margin-bottom: 14px; }
html.theme-clair .fc-card { margin-bottom: 14px; }

/* --- Sur-titre de l'ecran ------------------------------------------------- */
.fc-eyebrow-saison { font-size: .72rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 1.3px; color: var(--txt-dim); margin-bottom: 10px; }

/* --- Carte « PALIER FRANCHI » (degrade dore, centree) ---------------------- */
.fcp { background: linear-gradient(160deg, var(--ds-accent-soft-bg), var(--ds-accent-soft-bg-2));
  border-radius: var(--ds-radius-card, 22px); padding: 18px 16px 16px;
  text-align: center; margin-bottom: 14px; }
.fcp + .fcp { margin-top: -4px; }
.fcp-eyebrow { font-size: .66rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 1.4px; color: var(--ds-accent-ink); }
.fcp-carre { width: 76px; height: 76px; margin: 10px auto 8px;
  border-radius: 18px; background: linear-gradient(160deg, var(--ds-accent-solid-1), var(--ds-accent-solid-2));
  display: flex; align-items: center; justify-content: center;
  color: var(--ds-btn-txt); font-size: 56px; font-weight: 800; line-height: 1;
  box-shadow: 0 6px 16px rgba(180,120,10,.28); }
.fcp-carre.mot { font-size: 30px; letter-spacing: .5px; }
.fcp-nom { font-size: 1.12rem; font-weight: 800; color: var(--ds-accent-ink-fort); }
.fcp-elo { font-size: .78rem; font-weight: 700; color: var(--ds-accent-ink); margin-top: 2px;
  font-variant-numeric: tabular-nums; }
.fcp-txt { font-size: .86rem; line-height: 1.45; color: var(--ds-accent-ink-fort); margin-top: 10px; }

/* --- Carte « TON ELO CETTE SAISON » --------------------------------------- */
.fce-tete { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.fce-val { font-size: 2.1rem; font-weight: 800; color: var(--txt);
  line-height: 1; font-variant-numeric: tabular-nums; }
.fce-val small { font-size: .8rem; font-weight: 700; color: var(--txt-dim); margin-left: 4px; }
.fce-gain { font-size: 1rem; font-weight: 800; white-space: nowrap; }
.fce-gain.pos { color: var(--good); }
.fce-gain.neg { color: var(--bad); }
.fce-barre { height: 9px; margin-top: 12px; background: var(--bg-3);
  border-radius: 999px; overflow: hidden; }
html.theme-clair .fce-barre { background: var(--ds-track); }
.fce-barre > i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--ds-accent-light), var(--ds-accent)); }
.fce-bornes { display: flex; justify-content: space-between; gap: 10px;
  margin-top: 6px; font-size: .7rem; font-weight: 700; color: var(--txt-dim); }
.fce-bornes .droite { text-align: right; }

/* --- « La route vers le pro » : quatre etapes horizontales ------------------ */
.fcr { display: flex; align-items: flex-start; gap: 4px; margin-top: 14px; }
.fcr-e { flex: 1 1 0; min-width: 0; text-align: center; position: relative; }
.fcr-p { width: 15px; height: 15px; margin: 0 auto 6px; border-radius: 50%;
  background: var(--ds-line-hover); display: block; }
.fcr-e.faite .fcr-p { background: var(--ds-good); }
.fcr-e.encours .fcr-p { background: var(--ds-accent); box-shadow: 0 0 0 4px rgba(227,154,31,.20); }
.fcr-l { font-size: .58rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .5px; color: var(--txt-faint); line-height: 1.25;
  overflow-wrap: anywhere; }
.fcr-e.faite .fcr-l { color: var(--ds-good); }
.fcr-e.encours .fcr-l { color: var(--ds-accent-deep); }
/* Le trait de liaison, dessine entre deux pastilles (jamais apres la derniere). */
.fcr-e::after { content: ""; position: absolute; top: 7px; left: 50%; width: 100%;
  height: 2px; background: var(--ds-line-hover); z-index: 0; }
.fcr-e:last-child::after { display: none; }
.fcr-e.faite::after { background: var(--ds-good); }
.fcr-p { position: relative; z-index: 1; }

/* --- Feuille de match ------------------------------------------------------ */
.fcm-bilan { display: flex; gap: 8px; margin-bottom: 12px; }
.fcm-bilan .fcm-case { flex: 1 1 0; min-width: 0; text-align: center;
  background: var(--bg-3); border-radius: var(--ds-radius-tile, 15px); padding: 8px 6px; }
html.theme-clair .fcm-bilan .fcm-case { background: var(--ds-field-bg); }
.fcm-case .fcm-k { display: block; font-size: .58rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .6px; color: var(--txt-faint); }
.fcm-case .fcm-v { display: block; font-size: 1rem; font-weight: 800; margin-top: 2px;
  font-variant-numeric: tabular-nums; }
.fcm-case .fcm-v.pos { color: var(--good); }
.fcm-case .fcm-v.or { color: var(--ds-accent-deep, #A96E00); }

.fcm-l { display: flex; align-items: center; gap: 10px; padding: 8px 0;
  border-top: 1px solid var(--line); }
.fcm-l:first-child { border-top: 0; }
.fcm-vd { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ds-on-solid); font-weight: 800; font-size: .82rem; }
.fcm-vd.v { background: var(--ds-good); }
.fcm-vd.d { background: var(--ds-bad); }
.fcm-mid { flex: 1 1 auto; min-width: 0; }
.fcm-score { font-size: .86rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.fcm-map { font-size: .86rem; font-weight: 600; color: var(--txt-dim); margin-left: 6px; }
.fcm-kda { display: block; font-size: .68rem; color: var(--txt-faint); margin-top: 2px;
  font-variant-numeric: tabular-nums; }
.fcm-right { flex: 0 0 auto; text-align: right; }
.fcm-rat { display: inline-block; border-radius: 999px; padding: 2px 8px;
  font-size: .72rem; font-weight: 800; font-variant-numeric: tabular-nums;
  background: var(--ds-field-bg); color: var(--ds-text-dim); }
.fcm-rat.bon { background: var(--ds-good-soft-bg); color: var(--ds-good-ink); }
.fcm-rat.top { background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink); }
.fcm-delta { display: block; font-size: .7rem; font-weight: 800; margin-top: 3px;
  font-variant-numeric: tabular-nums; }
.fcm-delta.pos { color: var(--ds-good); }
.fcm-delta.neg { color: var(--ds-bad); }

/* Case depliable « tous les matchs de la saison » : meme patron que les autres
   depliants du jeu (<details>/<summary> natif, aucun etat a memoriser). */
.fcm-tous { margin-top: 10px; }
.fcm-tous > summary { list-style: none; cursor: pointer; padding: 9px 12px;
  border-radius: var(--ds-radius-tile, 15px); background: var(--bg-3);
  font-size: .78rem; font-weight: 800; color: var(--txt-dim);
  display: flex; align-items: center; justify-content: space-between; gap: 8px; }
html.theme-clair .fcm-tous > summary { background: var(--ds-field-bg); }
.fcm-tous > summary::-webkit-details-marker { display: none; }
.fcm-tous > summary::after { content: "⌄"; font-size: .9rem; color: var(--ds-accent, #E39A1F);
  transition: transform .18s ease; }
.fcm-tous[open] > summary::after { transform: rotate(180deg); }
.fcm-tous .fcm-liste { padding: 4px 2px 0; max-height: 60vh; overflow-y: auto; }
@media (prefers-reduced-motion: reduce) { .fcm-tous > summary::after { transition: none; } }
.fc-p-faceit { margin-top: 10px; font-size: .8rem; line-height: 1.45; }

/* ============================================================================
   ECRAN « PROFIL JOUEUR » — REFONTE DE PRESENTATION (2026-07-29)
   ----------------------------------------------------------------------------
   L'ancienne « Fiche joueur » (theme sombre, deux onglets, une longue colonne de
   lignes) devient un ecran CLAIR : une carte d'en-tete, puis HUIT TUILES
   depliables en deux colonnes. AUCUNE valeur, AUCUN calcul n'est touche —
   ce bloc n'habille que le nouvel agencement.

   REUTILISATION — la grille, les cases et les panneaux sont les composants DEJA
   poses par l'ecran de fin de saison et celui de fin de carriere (`.rs-grid`,
   `.rs-card`, `.rs-panel`, avec leur variante `html.theme-clair` plus haut). Ne
   sont definis ici que les elements PROPRES a cet ecran : la carte d'en-tete, la
   valeur secondaire d'une tuile, la tuile hero, la pile de blasons du parcours et
   la frise chronologique. Les pastilles de tier sont `UI.otierHTML` (`.otier-*`),
   celles du marche des transferts, deja calibrees pour un fond clair.

   PORTEE — tout est scope a `#screen-sheet` (ou a la classe `.pf-*`, qui
   n'existe que la). Aucun autre ecran n'est atteint ; le theme sombre reste le
   chemin de rollback si `screen-sheet` sort de ECRANS_CLAIRS (js/ui.js).
   ============================================================================ */

/* --- Carte d'en-tete : titre centre, puis un filet dore sous le titre. --- */
#screen-sheet .pf-head { padding: 13px 16px 14px; text-align: center; }
#screen-sheet .pf-title { margin: 0; font-size: 1.44rem; font-weight: 800; letter-spacing: .2px; }
html.theme-clair #screen-sheet .pf-title { color: var(--ds-text); }
#screen-sheet .pf-rule {
  display: block; width: 46px; height: 4px; margin: 8px auto 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--ds-btn-1), var(--ds-accent));
}

/* --- La grille : memes deux colonnes que l'ecran de fin, tuiles un peu plus
       hautes (la valeur secondaire prend une ligne de plus). --- */
#screen-sheet .pf-grid { margin-top: 10px; }
#screen-sheet .pf-card { min-height: 110px; gap: 2px; }
/* Valeur SECONDAIRE : sous la valeur principale, discrete, jamais tronquee en
   plein mot (un nom de pays + son drapeau doit tenir a 390 px).
   PORTEE ELARGIE le 2026-07-29 : la meme enveloppe sert desormais aussi a la tuile
   « Niveau FACEIT » de l'ecran de fin de saison (« NV 9 » puis « 1932 ELO »), pour
   que les deux ecrans presentent la meme valeur exactement de la meme facon. Le
   selecteur perd donc son prefixe `#screen-sheet` ; la regle de couleur en theme
   clair reste identique et vaut pour les deux ecrans. */
.pf-c-sub {
  font-size: .74rem; font-weight: 700; line-height: 1.2;
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.theme-clair .pf-c-sub { color: var(--ds-text-dim); }
#screen-sheet .pf-c-sub .stars .star { font-size: .8rem; }
#screen-sheet .rs-c-lab { margin-top: 3px; font-size: .6rem; letter-spacing: .9px; }
/* TUILE HERO (« Niveau ») : creme doree, chiffre et libelle en dore fonce. */
html.theme-clair #screen-sheet .pf-card.pf-hero {
  background: linear-gradient(160deg, var(--ds-accent-soft-bg), var(--ds-accent-soft-bg-2));
  color: var(--ds-accent-deep); box-shadow: var(--ds-shadow-tile);
}
html.theme-clair #screen-sheet .pf-hero .rs-c-lab,
html.theme-clair #screen-sheet .pf-hero .pf-c-sub,
html.theme-clair #screen-sheet .pf-hero .rs-chev { color: var(--ds-accent-ink); }
html.theme-clair #screen-sheet .pf-hero .rs-c-main { color: var(--ds-accent-ink); }
/* TUILE ACTIVE : contour dore de 2 px, pose EN DEDANS (une bordure decalerait la
   tuile d'un pixel et ferait sauter la rangee). */
html.theme-clair #screen-sheet .pf-card.ouvert { box-shadow: inset 0 0 0 2px var(--ds-accent), var(--ds-shadow-tile); }

/* --- Tuile « Parcours » : pile de blasons qui se chevauchent, bordes de blanc. --- */
#screen-sheet .pf-stack { display: inline-flex; align-items: center; }
#screen-sheet .pf-s-emb {
  display: inline-flex; line-height: 0; border-radius: 999px; padding: 2px;
  background: var(--ds-card); box-shadow: 0 1px 2px rgba(30,45,80,.18);
}
#screen-sheet .pf-s-emb + .pf-s-emb { margin-left: -8px; }
#screen-sheet .pf-card.pf-par .rs-c-main { line-height: 1; }

/* --- Panneaux : memes cartes blanches que l'ecran de fin ; on ne regle ici que
       le premier ecart vertical et la coupure des noms tres longs. --- */
#screen-sheet .pf-panel .list-line:first-child { border-top: 0; }
#screen-sheet .pf-panel .pf-e-nom,
#screen-sheet .pf-panel .list-line span { overflow-wrap: anywhere; }
#screen-sheet .pf-note { font-size: .78rem; margin: 6px 0 0; }
#screen-sheet .pf-renvoi { font-size: .82rem; margin: 8px 0 2px; }
html.theme-clair #screen-sheet .pf-renvoi { color: var(--ds-text-dim); }
html.theme-clair #screen-sheet .pf-renvoi strong { color: var(--ds-text); }
#screen-sheet .pf-champion { font-weight: 800; }
html.theme-clair #screen-sheet .pf-champion { color: var(--ds-accent-deep); }

/* --- FRISE CHRONOLOGIQUE des organisations traversees (tuile « Parcours »).
       Une ligne verticale doree relie les etapes ; chaque etape porte un point
       colore par le TIER de l'organisation — meme echelle que les pastilles
       `.otier-*` : Amateur gris, Tier 3 vert, Tier 2 bleu, Tier 1 violet,
       Tier S dore. --- */
#screen-sheet .pf-frise { position: relative; margin: 2px 0 0; padding-left: 22px; }
#screen-sheet .pf-frise::before {
  content: ""; position: absolute; left: 5px; top: 8px; bottom: 8px; width: 2px;
  border-radius: 999px; background: linear-gradient(180deg, var(--ds-accent), var(--ds-accent-dim));
}
#screen-sheet .pf-etape { position: relative; padding: 0 0 14px; }
#screen-sheet .pf-etape:last-child { padding-bottom: 0; }
#screen-sheet .pf-dot {
  position: absolute; left: -21px; top: 5px; width: 12px; height: 12px; border-radius: 999px;
  box-shadow: 0 0 0 3px var(--ds-card);
}
#screen-sheet .pf-dot-am { background: #8B95A6; }
#screen-sheet .pf-dot-t3 { background: #178A50; }
#screen-sheet .pf-dot-t2 { background: #2560DE; }
#screen-sheet .pf-dot-t1 { background: #6D3BD1; }
#screen-sheet .pf-dot-ts { background: #E39A1F; }
#screen-sheet .pf-e-top { display: flex; align-items: center; gap: 8px; }
#screen-sheet .pf-e-org { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
#screen-sheet .pf-e-nom { font-weight: 800; font-size: .92rem; }
#screen-sheet .pf-e-meta { font-size: .76rem; line-height: 1.4; margin-top: 2px; }
html.theme-clair #screen-sheet .pf-e-meta { color: var(--ds-text-dim); }
/* Titres gagnes PENDANT cette etape, en pastilles dorees. Le Grand Slam porte le
   lingot deja dessine par le jeu (famille `GrandSlam`), jamais un autre trophee. */
#screen-sheet .pf-titres { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
#screen-sheet .pf-titre {
  display: inline-flex; align-items: center; gap: 5px; border-radius: 999px;
  padding: 3px 9px; font-size: .7rem; font-weight: 700; line-height: 1.25;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink);
}
#screen-sheet .pf-titre.gs { background: linear-gradient(160deg, var(--ds-accent-soft-bg), var(--ds-accent-soft-bg-2)); color: var(--ds-accent-ink-fort); }
#screen-sheet .pf-titre svg { display: block; }
#screen-sheet .pf-t-an { font-weight: 800; opacity: .72; }

/* --- Bas de page : le renvoi discret vers « Comment ca marche », le bouton
       « Retour » restant celui de la page (`#btn-sheet-back`, bouton principal). --- */
#screen-sheet .pf-aide { margin-top: 10px; text-align: center; }
/* Le renvoi « Comment ca marche ? » reste un acces secondaire : il ne doit pas
   rivaliser avec le bouton « Retour » juste en dessous. */
#screen-sheet .pf-aide .btn { font-size: .78rem; padding: 6px 14px; }
html.theme-clair #screen-sheet .pf-aide .btn { background: rgba(255,255,255,.6); color: var(--ds-text-dim); }

/* ==========================================================================
   LES QUATRE METAUX — LEURS TEINTES DE REFERENCE          (2026-08-22, soir)

   ⚠️ C'EST LE SEUL ENDROIT DU JEU OU UN METAL EST ECRIT. Le bronze, l'argent,
   l'or et le diamant vivent ici, une fois chacun, et partout ailleurs on ecrit
   `var(--ds-metal-…)`. Avant cette date ils etaient recopies en huit endroits —
   les aplats du nom d'equipe, les replis du pseudo, les cinq stops de chacun de
   ses quatre degrades — et deux d'entre eux DIVERGEAIENT deja (`.eqr-argent`
   #7C8CA0 contre `.pseudo-argent` #4A5768, `.eqr-major` #B0800E contre
   `.pseudo-major` #B06E00), sans que personne ait decide que l'argent du pseudo
   devait etre plus sombre que celui d'une equipe.

   ⚠️ DEUX FAMILLES, ET IL NE FAUT PAS LES CONFONDRE :
     `--ds-metal-X-socle`    la teinte de REFERENCE, celle-ci ne bouge JAMAIS ;
     `--ds-metal-X`          la teinte DECLINEE, posee par js/themes.js sur la
                             racine a chaque application de theme.
   Sans theme applique, la seconde vaut la premiere : la page est juste des le
   premier pixel, avant qu'un script du jeu n'ait tourne.

   ⚠️ POURQUOI UNE DECLINAISON, ET CE QU'ELLE N'EST PAS. Mesure du 2026-08-22 :
   bronze 1,45:1 sur « Kaki », diamant 1,53 sur « Kaki », argent 1,82 et or 1,87
   sur « Cannelle », et sur la carte BLANCHE du socle l'or et l'argent etaient
   deja sous le plancher — 137 couples sur 188. Une recompense illisible ne
   recompense rien. ⚠️ SEULE LA CLARTE S'AJUSTE : la teinte est conservee (moins
   de trois degres CIELAB sur les 47 themes), le chroma n'est rabattu que si la
   couleur sort du gamut. ⚠️ CE N'EST PAS UNE JETONISATION : aucun theme ne peut
   ecrire `--ds-metal-*`, qui n'est pas dans la liste `JETONS` de js/themes.js —
   c'est le moteur qui calcule, et l'echelle reste une echelle. `g109` mesure
   les deux moities de cette regle.

   ⚠️ LES SUFFIXES NUMEROTES SONT LES STOPS DU REFLET DU PSEUDO, DANS L'ORDRE
   BORD -> CORPS -> CRETE. `js/themes.js` en lit autant qu'il en trouve : le
   diamant en a quatre, les trois autres en ont trois, et en ajouter un se fait
   ici seulement.
   ========================================================================== */
:root {
  /* --- BRONZE — un titre du haut du circuit ------------------------------- */
  --ds-metal-bronze-socle:   #8C5A2B;
  --ds-metal-bronze-socle-1: #5E3512;   /* bord du reflet */
  --ds-metal-bronze-socle-2: #B87333;   /* corps */
  --ds-metal-bronze-socle-3: #E8C08F;   /* crete */
  /* --- ARGENT — un des trois grands rendez-vous non-Major -----------------
     ⚠️ ACIER NEUTRE, VOLONTAIREMENT SANS BLEU : il se lit juste au-dessus du
     bronze et juste en dessous de l'or, et il ne doit PAS pouvoir etre confondu
     avec le diamant, qui est franchement bleu. Les bords le disent seuls —
     #38455A ici tire vers l'ardoise, #1E4D80 la vers l'outremer. */
  --ds-metal-argent-socle:   #7C8CA0;
  --ds-metal-argent-socle-1: #38455A;
  --ds-metal-argent-socle-2: #8FA0B4;
  --ds-metal-argent-socle-3: #FFFFFF;
  /* --- OR — un Major ------------------------------------------------------ */
  --ds-metal-or-socle:   #B0800E;
  --ds-metal-or-socle-1: #8A5E08;
  --ds-metal-or-socle-2: #E39A1F;
  --ds-metal-or-socle-3: #FBE08A;
  /* --- DIAMANT — le Grand Slam -------------------------------------------- */
  --ds-metal-diamant-socle:   #2E6BAA;
  --ds-metal-diamant-socle-1: #1E4D80;
  --ds-metal-diamant-socle-2: #3E8FD0;
  --ds-metal-diamant-socle-3: #9EE6FF;   /* la crete traverse en CIEL */
  --ds-metal-diamant-socle-4: #FFFFFF;

  /* Les quatre vivants : la reference tant que le moteur n'a rien pose. */
  --ds-metal-bronze:    var(--ds-metal-bronze-socle);
  --ds-metal-bronze-1:  var(--ds-metal-bronze-socle-1);
  --ds-metal-bronze-2:  var(--ds-metal-bronze-socle-2);
  --ds-metal-bronze-3:  var(--ds-metal-bronze-socle-3);
  --ds-metal-argent:    var(--ds-metal-argent-socle);
  --ds-metal-argent-1:  var(--ds-metal-argent-socle-1);
  --ds-metal-argent-2:  var(--ds-metal-argent-socle-2);
  --ds-metal-argent-3:  var(--ds-metal-argent-socle-3);
  --ds-metal-or:        var(--ds-metal-or-socle);
  --ds-metal-or-1:      var(--ds-metal-or-socle-1);
  --ds-metal-or-2:      var(--ds-metal-or-socle-2);
  --ds-metal-or-3:      var(--ds-metal-or-socle-3);
  --ds-metal-diamant:   var(--ds-metal-diamant-socle);
  --ds-metal-diamant-1: var(--ds-metal-diamant-socle-1);
  --ds-metal-diamant-2: var(--ds-metal-diamant-socle-2);
  --ds-metal-diamant-3: var(--ds-metal-diamant-socle-3);
  --ds-metal-diamant-4: var(--ds-metal-diamant-socle-4);
}

/* ==========================================================================
   PSEUDO DU JOUEUR — PALIERS COSMETIQUES  (2026-07-29, bronze 07-30, argent 07-31)
   --------------------------------------------------------------------------
   QUATRE recompenses PERMANENTES, purement visuelles, posees par une seule classe
   venue d'une seule source (`UI.pseudoHTML` <- `DF.pseudoPalier`) :
     .pseudo-bronze         — au moins un titre du HAUT DU CIRCUIT, Majors COMPRIS
                              (l'index `hautIndex` de js/engine.js) ;
     .pseudo-argent         — au moins un des trois grands rendez-vous NON-MAJOR
                              (IEM Krakow, IEM Cologne, Esports World Cup) ;
     .pseudo-major  dore    — au moins un Major remporte ;
     .pseudo-slam   diamant — au moins un Grand Slam ESL / IEM.
   Les quatre ne coexistent jamais : la classe est exclusive par construction, et le
   plus haut palier atteint l'emporte toujours — un palier peut donc etre saute.
   ⚠️ L'ECHELLE N'EST PAS DEFINIE ICI : elle vit dans `pseudoPalierDe` (js/engine.js),
   en un seul endroit. Ce commentaire la DECRIT — et il a deja menti une fois, en
   restant a trois paliers apres l'arrivee de l'argent le 2026-07-31.

   LA VITESSE DU REFLET ENCODE LE RANG — plus le palier est rare, plus le reflet est
   vif : bronze 7 s, argent 6,2 s, dore 5,5 s, diamant 4,2 s. Ce qui se raccourcit est
   surtout le TEMPS D'ARRET entre deux passages ; le balayage lui-meme dure ~1,5 s
   pour les trois premiers et 1,2 s pour le diamant, seul a etre aussi plus tranchant.
   ⚠️ Sa duree exacte n'est PAS recopiee ici : elle se lit sur chaque `@keyframes`
   plus bas, ou elle est calculee du pourcentage. Une redaction anterieure annoncait
   « ~1,5 s dans les trois cas » et se contredisait deja avec la keyframe du diamant.

   REGLE DE MISE EN PAGE : le pseudo garde exactement sa graisse, sa taille, sa
   troncature et son alignement a chaque emplacement — `font` et `color` sont
   herites, aucune boite n'est creee (`display` reste inline). SEULE la couleur
   change, il n'y a donc aucun decalage par rapport a l'etat normal.

   LISIBILITE : la couleur pleine (`color`) est posee EN PREMIER et sert de REPLI.
   Le degrade n'est applique que dans @supports background-clip:text ; un
   navigateur qui ne sait pas decouper le fond sur le texte garde donc un pseudo
   parfaitement lisible, jamais transparent.
   ========================================================================== */
/* ==========================================================================
   RANG D'UNE EQUIPE — LA COULEUR DU NOM               (2026-08-22)
   --------------------------------------------------------------------------
   LES CINQ COULEURS DU REGISTRE DES EQUIPES, ET ELLES NE VIVENT QU'ICI.
   Le registre (`prog.rangEquipes`, `DF.rangEquipes`) dit le PLUS HAUT TITRE gagne
   avec chaque organisation de la carriere ; `UI.equipeHTML` pose la classe, cette
   feuille pose la couleur, et aucun ecran n'en connait une seule valeur.

   L'ECHELLE EST CELLE DU PSEUDO — c'est `pseudoPalierDe` (js/engine.js) qui la
   tranche, en un seul endroit, pour les deux. LES TEINTES AUSSI SONT LES MEMES
   depuis la mise en commun des quatre metaux.

   ⚠️ ET LA BRILLANCE AUSSI, DEPUIS LE 2026-08-22 (4e PASSAGE). Le nom d'equipe
   etait un APLAT IMMOBILE ; le proprietaire l'a voulu BRILLANT « de la meme
   facon » que le pseudo, a partir du bronze. ⚠️ CES REGLES-CI N'ONT PAS BOUGE
   D'UN CARACTERE POUR CELA, ET C'EST LE POINT : `UI.rangEquipeClasse` pose
   DESORMAIS, en plus de `.eqr-<rang>`, la classe que `UI.pseudoClasse` pose sur
   le pseudo — donc le reflet du bloc « PSEUDO DU JOUEUR » ci-dessous s'applique
   tel quel. Il n'y a qu'UN dessin de brillance dans tout le jeu ; en ecrire un
   second ici, meme identique, c'etait garantir qu'ils divergent un jour.
   ⚠️ LE RANG « SANS TITRE » N'EN PREND AUCUNE : `.eqr-nul` reste seul, sans
   classe de pseudo — l'encre plate du theme, et rien d'autre.
   ⚠️ RESERVE ASSUMEE, ELLE N'EST PAS CORRIGEE ET ELLE ATTEND UN ARBITRAGE : deux
   reflets coexistent maintenant dans la ligne d'identite de l'en-tete quand le
   pseudo et l'equipe portent le meme palier — ce que l'aplat distinguait. Voir
   `CLAUDE-registre-equipes.md`.

   ⚠️ QUATRE COULEURS HORS DE PORTEE DE TOUT THEME, UNE QUI LE SUIT — ET LA
   FRONTIERE EST LA REGLE, PAS UN DETAIL. Les quatre METAUX (bronze, argent, or,
   diamant) sont des couleurs de RECOMPENSE : elles encodent un accomplissement,
   elles valent la meme chose partout, aucune n'est une variable CSS de la racine,
   donc aucun theme ne peut les redefinir — meme doctrine que les cinq couleurs de
   TIER (`.otier-*`) et que les replis du pseudo.
   ⚠️ L'ENCRE, ELLE, N'EST PAS UNE COULEUR DE RECOMPENSE : C'EST LA COULEUR DU
   TEXTE, ET ELLE SUIT LE THEME COMME TOUT AUTRE TEXTE DU JEU. Elle vaut donc
   `--ds-text`, le jeton d'encre principale, et rien d'autre.
   ⚠️ CE N'EST PAS UN ASSOUPLISSEMENT, C'EST LA CORRECTION D'UNE REGRESSION
   MESUREE : ecrite en dur (`#2B3242`, 2026-08-22), l'encre tombait a 1,03:1 sur
   la carte du theme « Tison » — un nom d'equipe sans titre y etait ILLISIBLE, du
   noir sur du noir. Sous `--ds-text`, elle retrouve le contraste que le jeu
   garantit deja a son texte principal sur les 37 themes (`g48`).
   ⚠️ NE PAS REPASSER LES QUATRE METAUX EN JETONS DE THEME « pour la coherence » :
   une recompense qui change de couleur selon le theme cesse d'etre une echelle.
   `g109 §109d` mesure les deux moities de cette regle, et il TOMBE si l'une des
   deux est enfreinte.

   ⚠️ `.eqr-nul` N'EST PAS « PAS DE COULEUR », C'EST L'ENCRE DU TEXTE, ET ELLE EST
   ECRITE. Elle couvre TROIS cas que rien ne distingue a l'oeil, et c'est voulu :
   « rien gagne sous ce maillot », « registre absent » (carriere archivee avant le
   2026-08-22, jamais migree) et « valeur inconnue de l'echelle ». Aucun trou,
   aucune couleur inventee.
   ⚠️ LE NOM D'EQUIPE S'AFFICHAIT EN BRUN DORE (`--ds-accent-deep`) JUSQU'AU
   2026-08-22, ET IL NE FAUT PAS Y REVENIR : ce dore etait a un cheveu du BRONZE,
   si bien que « rien gagne » et « un titre » se seraient ressembles. `--ds-text`
   suit le theme comme lui, sans le confondre avec un metal.
   ⚠️ SEUL LE NOM EST CONCERNE. L'ECUSSON NE PORTE AUCUNE DE CES CLASSES.
   ========================================================================== */
.eqr { font: inherit; }                  /* la classe-marqueur ne porte AUCUNE couleur */
.eqr-nul    { color: var(--ds-text); }              /* l'encre du theme : rien gagne / registre absent */
.eqr-bronze { color: var(--ds-metal-bronze); }      /* un titre du haut du circuit */
.eqr-argent { color: var(--ds-metal-argent); }      /* l'un des trois grands rendez-vous */
.eqr-major  { color: var(--ds-metal-or); }          /* un Major */
.eqr-slam   { color: var(--ds-metal-diamant); }     /* le Grand Slam */

/* Le repli plein du pseudo. ⚠️ C'EST LE MEME METAL QUE CELUI DU NOM D'EQUIPE, ET
   CE N'EST PLUS UNE SECONDE VALEUR : l'argent et l'or du pseudo divergeaient de
   ceux du registre (#4A5768 contre #7C8CA0, #B06E00 contre #B0800E) sans qu'une
   decision l'ait voulu. Un metal encode un accomplissement : il vaut la meme
   chose partout, et il se decline maintenant de la meme facon partout. */
.pseudo-j { font: inherit; color: inherit; }
.pseudo-bronze { color: var(--ds-metal-bronze); }
.pseudo-argent { color: var(--ds-metal-argent); }
.pseudo-major  { color: var(--ds-metal-or); }
.pseudo-slam   { color: var(--ds-metal-diamant); }

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .pseudo-bronze, .pseudo-argent, .pseudo-major, .pseudo-slam {
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;   /* le repli `color` reste sous-jacent */
    /* REPETITION VOLONTAIRE, et non `no-repeat` : aux deux extremes du balayage
       (positions 120 % et -20 %) le degrade, large de 220 %, ne recouvre plus
       toute la boite du texte. Sans repetition, la portion decouverte n'aurait
       AUCUN fond — et le texte etant en `text-fill-color: transparent`, ces
       lettres-la deviendraient INVISIBLES. Les deux bouts de chaque degrade
       portent exactement le MEME stop (le bord, `--ds-metal-X-1`) : la
       repetition est donc sans couture, et le pseudo reste peint en entier a
       chaque instant du cycle. */
    background-repeat: repeat;
  }
  /* ⚠️ PLUS UN SEUL HEXADECIMAL DANS CES QUATRE DEGRADES DEPUIS LE 2026-08-22 :
     chaque stop est un jeton de metal, et le moteur les decline ensemble. Le
     degrade est DEPLACE d'un bloc, jamais stop par stop — sinon le modele (bord
     sombre, corps, crete) s'ecraserait et le metal perdrait son relief. */
  .pseudo-bronze {
    background-image: linear-gradient(100deg, var(--ds-metal-bronze-1) 0%, var(--ds-metal-bronze-2) 34%, var(--ds-metal-bronze-3) 50%, var(--ds-metal-bronze-2) 66%, var(--ds-metal-bronze-1) 100%);
    background-size: 220% 100%;
    animation: pseudo-reflet-bronze 7s ease-in-out infinite;
  }
  /* ARGENT — palier NOUVEAU du 2026-07-31 (IEM Krakow, IEM Cologne, EWC).
     ⚠️ C'EST UN ACIER NEUTRE, VOLONTAIREMENT SANS BLEU : il se lit juste au-dessus
     du bronze et juste en dessous de l'or, et il ne doit PAS pouvoir etre confondu
     avec le diamant, qui est franchement BLEU. Les deux teintes de bord le disent
     seules — l'une tire vers l'ardoise, l'autre vers l'outremer ; les valeurs sont
     dans le bloc des teintes de reference, plus haut, et nulle part ailleurs. La
     crete blanche est commune aux deux, mais le diamant la traverse en ciel quand
     l'argent passe du gris clair au blanc pur, sans jamais virer. */
  .pseudo-argent {
    background-image: linear-gradient(100deg, var(--ds-metal-argent-1), var(--ds-metal-argent-2) 30%, var(--ds-metal-argent-3) 50%, var(--ds-metal-argent-2) 70%, var(--ds-metal-argent-1));
    background-size: 220% 100%;
    animation: pseudo-reflet-argent 6.2s ease-in-out infinite;
  }
  .pseudo-major {
    background-image: linear-gradient(100deg, var(--ds-metal-or-1) 0%, var(--ds-metal-or-2) 38%, var(--ds-metal-or-3) 50%, var(--ds-metal-or-2) 62%, var(--ds-metal-or-1) 100%);
    background-size: 220% 100%;
    animation: pseudo-reflet-or 5.5s ease-in-out infinite;
  }
  .pseudo-slam {
    background-image: linear-gradient(100deg, var(--ds-metal-diamant-1) 0%, var(--ds-metal-diamant-2) 28%, var(--ds-metal-diamant-3) 45%, var(--ds-metal-diamant-4) 51%, var(--ds-metal-diamant-3) 57%, var(--ds-metal-diamant-2) 74%, var(--ds-metal-diamant-1) 100%);
    background-size: 230% 100%;
    animation: pseudo-reflet-diam 4.2s ease-in-out infinite;
  }
}
/* Le balayage occupe ~1,5 s du cycle ; le degrade est IMMOBILE le reste du temps
   (le reflet doit rester un evenement discret, pas un scintillement continu).
   Les deux positions extremes montrent la meme teinte sombre de bord : la reprise
   du cycle ne produit donc aucun a-coup visible. */
@keyframes pseudo-reflet-bronze {
  0%   { background-position: 120% 0; }
  21%  { background-position: -20% 0; }   /* 1,5 s sur 7 s : le plus lent des quatre reflets */
  100% { background-position: -20% 0; }
}
@keyframes pseudo-reflet-argent {
  0%   { background-position: 120% 0; }
  24%  { background-position: -20% 0; }   /* 1,5 s sur 6,2 s */
  100% { background-position: -20% 0; }
}
@keyframes pseudo-reflet-or {
  0%   { background-position: 120% 0; }
  27%  { background-position: -20% 0; }   /* 1,5 s sur 5,5 s */
  100% { background-position: -20% 0; }
}
@keyframes pseudo-reflet-diam {
  0%   { background-position: 125% 0; }
  29%  { background-position: -25% 0; }   /* 1,2 s sur 4,2 s : plus vif, plus tranchant */
  100% { background-position: -25% 0; }
}

/* ==========================================================================
   CARTES DE DEBLOCAGE DU PSEUDO — une par palier, donc QUATRE
   Elles s'inserent a la fin de l'ecran de resultats de la saison, avant le
   bouton « Continuer ». Elles n'apparaissent qu'a la saison ou la couleur du
   pseudo change reellement (cf. `DF.pseudoDeblocage`), et une seule a la fois.
   ⚠️ Les paliers eux-memes sont decrits plus haut, dans le bloc « PSEUDO DU JOUEUR »,
   et definis dans `pseudoPalierDe` (js/engine.js) — ils ne se redisent pas ici. Une
   redaction anterieure les listait a trois, en donnant au BRONZE la definition qui
   est celle de l'ARGENT depuis le 2026-07-31, et en oubliant la carte argent.
   ========================================================================== */
.pdb {
  position: relative; overflow: hidden;
  margin: 18px auto 0; max-width: 380px;
  padding: 18px 18px 20px; border-radius: 22px;
  text-align: center;
  /* ⚠️ LA SEULE SURFACE DU JEU QUI RENDE SES METAUX A LEUR REFERENCE, ET C'EST
     PARCE QU'ELLE NE SUIT AUCUN THEME. Les quatre cartes de deblocage portent un
     degrade pastel CLAIR ecrit en dur, identique sous les 47 themes : y poser un
     metal eclairci pour une carte sombre le rendrait illisible ici, alors meme
     que la declinaison existe pour l'inverse. On redit donc la reference, et le
     pseudo de la carte redevient exactement celui de la maquette validee.
     ⚠️ Ne pas retirer ces quatre lignes « puisque les metaux se declinent » :
     c'est justement ce qui ferait le defaut. */
  --ds-metal-bronze:    var(--ds-metal-bronze-socle);
  --ds-metal-bronze-1:  var(--ds-metal-bronze-socle-1);
  --ds-metal-bronze-2:  var(--ds-metal-bronze-socle-2);
  --ds-metal-bronze-3:  var(--ds-metal-bronze-socle-3);
  --ds-metal-argent:    var(--ds-metal-argent-socle);
  --ds-metal-argent-1:  var(--ds-metal-argent-socle-1);
  --ds-metal-argent-2:  var(--ds-metal-argent-socle-2);
  --ds-metal-argent-3:  var(--ds-metal-argent-socle-3);
  --ds-metal-or:        var(--ds-metal-or-socle);
  --ds-metal-or-1:      var(--ds-metal-or-socle-1);
  --ds-metal-or-2:      var(--ds-metal-or-socle-2);
  --ds-metal-or-3:      var(--ds-metal-or-socle-3);
  --ds-metal-diamant:   var(--ds-metal-diamant-socle);
  --ds-metal-diamant-1: var(--ds-metal-diamant-socle-1);
  --ds-metal-diamant-2: var(--ds-metal-diamant-socle-2);
  --ds-metal-diamant-3: var(--ds-metal-diamant-socle-3);
  --ds-metal-diamant-4: var(--ds-metal-diamant-socle-4);
}
.pdb-bro  { background: linear-gradient(160deg, #F7EADA 0%, #E4C6A0 100%); box-shadow: 0 10px 26px rgba(140,90,43,.28); }
/* ARGENT — carte du palier ajoute le 2026-07-31. Acier NEUTRE, comme le pseudo :
   aucune trace de bleu, pour qu'on ne la confonde pas avec la carte diamant. */
.pdb-arg  { background: linear-gradient(160deg, #F4F6F9 0%, #D5DCE5 100%); box-shadow: 0 10px 26px rgba(74,87,104,.26); }
.pdb-or   { background: linear-gradient(160deg, #FCEFCF 0%, #F4D89C 100%); box-shadow: 0 10px 26px rgba(176,110,0,.28); }
.pdb-diam { background: linear-gradient(160deg, #EAF5FD 0%, #BFD8F2 100%); box-shadow: 0 10px 26px rgba(55,105,165,.30); }
/* Reflet diagonal en surimpression : purement decoratif, hors du flux et
   hors de l'arbre d'accessibilite (aria-hidden cote HTML). */
.pdb-shine {
  position: absolute; inset: -50% -70%; pointer-events: none;
  background: linear-gradient(100deg, transparent 40%, rgba(255,255,255,.55) 50%, transparent 60%);
  transform: translateX(-55%);
  animation: pdb-reflet 5.5s ease-in-out infinite;
}
/* Meme regle que pour le pseudo : le reflet de la carte est d'autant plus vif que le
   palier est rare — bronze 7 s, argent 6,2 s, dore 5,5 s (la valeur par defaut de
   `.pdb-shine`, elle n'est donc pas redeclaree), diamant 4,2 s. */
.pdb-bro .pdb-shine {
  background: linear-gradient(100deg, transparent 40%, rgba(255,255,255,.42) 50%, transparent 60%);
  animation-duration: 7s;
}
.pdb-arg .pdb-shine {
  background: linear-gradient(100deg, transparent 40%, rgba(255,255,255,.60) 50%, transparent 60%);
  animation-duration: 6.2s;
}
.pdb-diam .pdb-shine {
  background: linear-gradient(100deg, transparent 42%, rgba(255,255,255,.78) 50%, transparent 58%);
  animation-duration: 4.2s;
}
@keyframes pdb-reflet {
  0%   { transform: translateX(-55%); }
  27%  { transform: translateX(55%); }
  100% { transform: translateX(55%); }
}
.pdb > *:not(.pdb-shine) { position: relative; z-index: 1; }
.pdb-sur { text-transform: uppercase; font-size: 10.5px; letter-spacing: .16em; font-weight: 700; }
.pdb-lab { text-transform: uppercase; font-size: 11px; letter-spacing: .14em; font-weight: 700; }
.pdb-bro  .pdb-sur, .pdb-bro  .pdb-lab { color: #8A5E2B; }
.pdb-arg  .pdb-sur, .pdb-arg  .pdb-lab { color: #55637A; }
.pdb-or   .pdb-sur, .pdb-or   .pdb-lab { color: #A9791F; }
.pdb-diam .pdb-sur, .pdb-diam .pdb-lab { color: #4A7FB5; }
.pdb-ic { margin: 10px 0 4px; line-height: 0; }
.pdb-t { font-size: 21px; font-weight: 800; line-height: 1.2; }
/* Le titre de la carte bronze est un NOM DE TOURNOI, souvent plus long qu'un
   libelle fixe : il descend a 20 px et se coupe proprement s'il le faut. */
.pdb-bro  .pdb-t { color: #6B4218; font-size: 20px; overflow-wrap: anywhere; }
.pdb-arg  .pdb-t { color: #38455A; font-size: 20px; overflow-wrap: anywhere; }
.pdb-or   .pdb-t { color: #7A4E00; }
.pdb-diam .pdb-t { color: #1B4E82; }
.pdb-s { font-size: 13px; margin-top: 4px; }
.pdb-bro  .pdb-s { color: #8A5E2B; font-size: 12.5px; }
.pdb-arg  .pdb-s { color: #55637A; font-size: 12.5px; }
.pdb-or   .pdb-s { color: #96701C; }
.pdb-diam .pdb-s { color: #4A7FB5; }
.pdb-fil { height: 1px; margin: 14px 8px; }
.pdb-bro  .pdb-fil { background: rgba(107,66,24,.22); }
.pdb-arg  .pdb-fil { background: rgba(56,69,90,.20); }
.pdb-or   .pdb-fil { background: rgba(122,78,0,.22); }
.pdb-diam .pdb-fil { background: rgba(27,78,130,.20); }
.pdb-nom { font-size: 26px; font-weight: 800; margin-top: 6px; line-height: 1.25; overflow-wrap: anywhere; }
.pdb-p { font-size: 13px; line-height: 1.5; margin: 10px auto 0; max-width: 34ch; }
.pdb-bro  .pdb-p { color: #6B4218; }
.pdb-arg  .pdb-p { color: #38455A; }
.pdb-or   .pdb-p { color: #7A4E00; }
.pdb-diam .pdb-p { color: #1B4E82; }

/* MOUVEMENT REDUIT — aucune animation nulle part, et le degrade reste FIXE.
   La position retenue est exactement la position de REPOS du balayage (-20 % pour
   l'or, -25 % pour le diamant), celle ou le degrade passe le plus clair de son
   cycle : c'est la plus sombre, donc la plus lisible, et c'est aussi ce que voit
   la plupart du temps un joueur sans reglage de mouvement reduit — les deux
   rendus concordent au lieu de diverger. */
@media (prefers-reduced-motion: reduce) {
  .pseudo-bronze, .pseudo-argent, .pseudo-major, .pseudo-slam { animation: none; }
  .pseudo-bronze { background-position: -20% 0; }
  .pseudo-argent { background-position: -20% 0; }
  .pseudo-major { background-position: -20% 0; }
  .pseudo-slam  { background-position: -25% 0; }
  .pdb-shine { animation: none; transform: translateX(0); opacity: .30; }
}

/* ============================================================================
   VERROU DES 16 ANS — ecran de saison amateur                    (2026-07-29)
   Bandeau d'explication affiche pendant les saisons jouees a 14 et 15 ans, quand
   aucune organisation n'a le DROIT de signer le joueur. Purement informatif : il
   n'y a rien a cliquer. Le ton reste celui des cartes claires du reste de
   l'ecran (fond pastel, filet dore), pour qu'il se lise comme une explication et
   non comme une alerte d'erreur.
   ========================================================================== */
.fc-verrou {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 0 14px; padding: 12px 14px;
  border-radius: 14px;
  background: linear-gradient(160deg, var(--ds-accent-wash-2), var(--ds-accent-wash-3));
  border: 1px solid rgba(176, 110, 0, .28);
  box-shadow: 0 6px 18px rgba(176, 110, 0, .12);
}
.fc-verrou-ic { font-size: 1.15rem; line-height: 1.25; flex: 0 0 auto; }
.fc-verrou p {
  margin: 0; font-size: .84rem; line-height: 1.4; font-weight: 600;
  color: var(--ds-accent-ink-fort);   /* 7,1:1 sur le fond pastel : lisible a 390 px */
}

/* ==========================================================================
   AVERTISSEMENT « SAUVEGARDE IMPOSSIBLE »                       (2026-07-30)
   Les quatre ecritures du jeu avalaient un debordement de quota en silence : le
   joueur ne decouvrait la perte qu'au rechargement. Cet encadre rend l'echec
   VISIBLE. Il reprend exactement la famille des encadres d'alerte deja en place
   (cf. `.fc-verrou` ci-dessus) : degrade dore pale, filet dore, texte fonce.

   IL N'EST PAS MODAL, ET C'EST VOULU. Le conteneur fixe ne prend PAS les clics
   (`pointer-events: none`) ; seule la carte les prend. Le jeu reste donc
   entierement jouable et l'export du palmares reste atteignable derriere lui :
   l'avertissement informe, le joueur decide.
   ========================================================================== */
.sa-wrap {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  display: flex; justify-content: center;
  padding: 10px 10px 0;
  pointer-events: none;                 /* le jeu reste cliquable autour */
}
.sa-box {
  pointer-events: auto;                 /* ... mais l'encadre, lui, est cliquable */
  width: 100%; max-width: 520px;
  border-radius: 14px;
  padding: 12px 14px;
  background: linear-gradient(160deg, var(--ds-accent-wash-2), var(--ds-accent-wash-3));
  border: 1px solid rgba(176, 110, 0, .28);
  box-shadow: 0 10px 28px rgba(30, 25, 5, .28);
}
.sa-head { display: flex; align-items: flex-start; gap: 10px; }
.sa-ic { font-size: 1.15rem; line-height: 1.25; flex: 0 0 auto; }
.sa-tx {
  margin: 0; flex: 1 1 auto; min-width: 0;
  font-size: .84rem; line-height: 1.45; font-weight: 600;
  color: var(--ds-accent-ink-fort);     /* 7,1:1 sur le fond pastel, comme .fc-verrou */
}
.sa-tx strong { color: var(--ds-accent-ink-fort); }
/* Bouton de fermeture : cible tactile de 30 px, jamais sous les 24 px recommandes. */
.sa-x {
  flex: 0 0 auto; width: 30px; height: 30px; margin: -4px -4px 0 0;
  border: 0; border-radius: 8px; background: transparent; cursor: pointer;
  font-size: 1.05rem; line-height: 1; color: var(--ds-accent-ink-fort);
}
.sa-x:hover { background: rgba(176, 110, 0, .12); }
.sa-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.sa-btn {
  border: 1px solid rgba(176, 110, 0, .40); border-radius: 10px;
  background: var(--ds-accent-wash-1); color: var(--ds-accent-ink-fort); cursor: pointer;
  font: inherit; font-size: .8rem; font-weight: 700; padding: 7px 12px;
}
.sa-btn:hover { background: var(--ds-card); }
/* Zone d'export DANS l'encadre : c'est la seule porte de sortie du joueur, elle
   ne doit dependre d'aucune navigation (partir vers un autre ecran puis revenir
   par « Continuer » rechargerait la sauvegarde PERIMEE, donc detruirait justement
   la partie que l'on cherche a sauver). */
.sa-export { margin: 10px 0 0; }
.sa-export textarea {
  width: 100%; box-sizing: border-box; resize: vertical;
  border: 1px solid rgba(176, 110, 0, .32); border-radius: 10px;
  background: var(--ds-accent-wash-1); color: var(--ds-accent-ink-fort);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .68rem;
  line-height: 1.35; padding: 8px;
}
.sa-note { margin: 6px 0 0; font-size: .72rem; line-height: 1.35; color: var(--ds-accent-ink); }


/* ==========================================================================
   LES ECUSSONS DE DISTINCTION                                   (2026-07-31)

   Ils REMPLACENT les pastilles plates `.dsb` du 2026-07-30. Meme donnee, meme
   metal, meme libelle de quatre caracteres : seule la FORME change. Aucune
   condition d'obtention, aucun seuil, aucune attribution de metal n'est touche
   par ce bloc — c'est de la peinture, et rien d'autre.

   L'ECUSSON EST UN COMPOSANT AUTONOME. Il ne depend d'aucun ecran et se pose a
   l'identique dans le mur de l'ecran Distinctions (56 px), la bulle de detail
   (76 px), la tuile « Badges » de l'en-tete (26 px), la ligne d'acces du Profil
   (30 px), les sections repliees (34 px) et le bloc de fin de saison (38 px).

   ⚠️ LES COULEURS NE SONT PAS ICI. Elles vivent dans une table unique, en tete
   de js/ui.js (`DSE_METAUX`), qui alimente a la fois le dessin (via les degrades
   SVG injectes au demarrage) et la pastille de compte ci-dessous. Ecrire un
   metal dans cette feuille creerait une seconde verite ; les seules couleurs
   d'ecusson qu'on trouvera ici sont celles des pastilles de compte, qui ne sont
   pas peintes en SVG.
   ========================================================================== */
.dse {
  position: relative; display: inline-block; flex: 0 0 auto;
  line-height: 0;                      /* aucune gouttiere sous le SVG */
  vertical-align: middle;
}
/* OMBRE PORTEE DOUCE sous l'ecusson — posee sur le SVG, elle epouse donc la
   silhouette et non une boite rectangulaire. */
.dse > svg {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 3px 4px rgba(35, 55, 95, .24));
}
/* Le code inscrit herite de la police du jeu : un SVG ne le fait pas seul. */
.dse text { font-family: inherit; letter-spacing: .02em; }

/* --- REFLET -------------------------------------------------------------
   Une bande claire diagonale traverse l'ecusson, DECOUPEE A SA FORME par le
   clipPath `#dse-clip` : elle ne deborde jamais du contour. Cycle 5,4 s, la
   traversee durant 1,5 s (27,8 % du cycle). Purement decoratif : `aria-hidden`
   cote SVG et `pointer-events: none` ici, pour ne jamais intercepter le tap qui
   ouvre la bulle. */
.dse-shine {
  pointer-events: none;
  transform-box: fill-box; transform-origin: center;
  animation: dse-reflet 5.4s ease-in-out infinite;
}
@keyframes dse-reflet {
  0%    { transform: rotate(16deg) translateX(-180%); }
  27.8% { transform: rotate(16deg) translateX(180%); }
  100%  { transform: rotate(16deg) translateX(180%); }
}
/* DELAIS DECALES, en rotation de HUIT, pas de 0,7 s. Deux ecussons cote a cote
   ne scintillent jamais ensemble : la classe est posee par l'index d'affichage
   PARMI LES ECUSSONS ANIMES (js/ui.js). Avec quatre ecussons par ligne, deux
   voisins horizontaux different de 0,7 s et deux voisins verticaux de 2,8 s. */
.dse-d0 .dse-shine { animation-delay: 0s; }
.dse-d1 .dse-shine { animation-delay: .7s; }
.dse-d2 .dse-shine { animation-delay: 1.4s; }
.dse-d3 .dse-shine { animation-delay: 2.1s; }
.dse-d4 .dse-shine { animation-delay: 2.8s; }
.dse-d5 .dse-shine { animation-delay: 3.5s; }
.dse-d6 .dse-shine { animation-delay: 4.2s; }
.dse-d7 .dse-shine { animation-delay: 4.9s; }
/* VERROUILLE : aucun reflet du tout — il n'y a rien a celebrer. Il n'a donc
   meme pas de bande dans son SVG ; cette regle n'est qu'une ceinture. */
.dse-lock .dse-shine { animation: none; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .dse-shine { animation: none; opacity: 0; }
}

/* --- PASTILLE DE COMPTE -------------------------------------------------
   Posee sur l'angle SUPERIEUR DROIT de l'ecusson, cerclee de blanc, a la
   couleur du metal, chiffre blanc.
   ELLE N'APPARAIT QU'A PARTIR DE 2 (regle tenue par js/ui.js) : un « 1 » sur
   chaque ecusson ne serait que du bruit, et un badge sans notion de compte n'en
   porte jamais. */
.dse-n {
  position: absolute; top: -3px; right: -5px;
  min-width: 18px; height: 18px; box-sizing: border-box; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--ds-outline); border-radius: 999px;
  font-size: 11px; font-weight: 800; line-height: 1; color: var(--ds-on-solid);
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 2px rgba(35, 55, 95, .28);
}
/* Les seules couleurs d'ecusson de cette feuille : la pastille de compte n'est
   pas peinte en SVG, elle ne peut donc pas lire le degrade. Elles reprennent au
   chiffre pres la colonne « pastille de compte » de la table de js/ui.js. */
.dse-n-diamant { background: #2E6BAA; }
.dse-n-or      { background: #E39A1F; color: #3A2600; }   /* du blanc sur cet or ne ferait que 2,4:1 */
.dse-n-argent  { background: #7D8EA1; color: #202634; }   /* du blanc sur cet argent ne ferait que 3,4:1 */
.dse-n-bronze  { background: #A9662C; }

/* --- CASE « +N » du mur -------------------------------------------------
   Ni un ecusson, ni une distinction : un carre en pointilles, au MEME gabarit
   que ses voisins, qui ouvre la collection complete. */
.dse-plus {
  width: 56px; height: 65px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px dashed var(--ds-btn-soft-line); border-radius: 12px;
  background: none; color: var(--ds-text-dim);
  font: inherit; font-size: .92rem; font-weight: 800; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.dse-plus:hover { border-color: var(--ds-line-hover); color: var(--ds-text); }
.dse-plus:focus-visible { outline: 2px solid var(--ds-accent-deep); outline-offset: 2px; }
/* Le conteneur des degrades ne dessine rien et ne prend aucune place. */
.dse-defs, #dse-defs-host { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ==========================================================================
   TUILE « BADGES » DE L'EN-TETE ET SA NOTIFICATION               (2026-07-31)

   CINQUIEME tuile de la rangee, en AVANT-DERNIERE position (eclair, etoiles,
   argent, BADGES, presse-papiers). Elle remplace la pastille d'identite comme
   porte vers l'ecran Distinctions.
   ========================================================================== */
.hud-tile-dst {
  position: relative; border: 0; background: none; font: inherit; cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
.hud-tile-dst:focus-visible { outline: 2px solid var(--ds-accent-deep); outline-offset: 2px; }
/* LES DEUX TUILES REVEILLEES (2026-08-16) — « Niveau » et « Fortune » etaient des
   `<div>` sans ecouteur : la moitie de la rangee ne repondait pas au doigt. Elles
   ouvrent desormais le Profil joueur, comme la zone de la carte d'identite qui
   porte la meme information.
   ⚠️ CES DEUX DECLARATIONS NE DEPLACENT PAS UN PIXEL, et c'est la condition qui
   les autorise : `cursor` et `outline` ne participent ni au flux, ni au calcul de
   taille. L'en-tete A est mesure octet a octet ET boite a boite — un `padding` ou
   une `border` ici l'aurait fait bouger. Elles restent des `<div role="button">`
   pour la meme raison. */
.hud-tile-niv, .hud-tile-arg { cursor: pointer; }
.hud-tile-niv:focus-visible, .hud-tile-arg:focus-visible {
  outline: 2px solid var(--ds-accent-deep); outline-offset: 2px;
}
/* PASTILLE ROUGE DE NOTIFICATION : le nombre de badges debloques depuis la
   derniere ouverture de l'ecran. Elle n'apparait jamais a zero (js/main.js ne la
   pose pas), et disparait des l'ouverture. Le battement est LENT et discret :
   c'est un rappel, pas une alarme. */
.hud-notif {
  position: absolute; top: 0; right: 4px;
  min-width: 17px; height: 17px; box-sizing: border-box; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ds-alerte); color: var(--ds-on-solid);
  border: 2px solid var(--ds-outline); border-radius: 999px;
  font-size: 10px; font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 3px rgba(120, 20, 10, .35);
  animation: hud-notif-pulse 2.4s ease-in-out infinite;
}
@keyframes hud-notif-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.14); }
}
@media (prefers-reduced-motion: reduce) { .hud-notif { animation: none; } }

/* ==========================================================================
   PASTILLE D'IDENTITE — PLANCHER LISIBLE POUR L'ORGANISATION    (2026-07-31)

   Retirer les badges de la pastille lui rend l'ordre de cession d'avant : le
   NOM D'ORGANISATION se tronque en premier, le pseudo est protege. Mais il
   manquait a ce nom un PLANCHER — il avait `min-width: 0` — et une MESURE l'a
   montre : a 390 px, avec un pseudo de 16 caracteres (le maximum du jeu) et
   l'organisation au nom le plus long du circuit (22 caracteres), le nom
   d'organisation etait ecrase A ZERO PIXEL. Il ne se tronquait pas, il
   DISPARAISSAIT.

   ⚠️ C'EST LE DEFAUT SYMETRIQUE DE CELUI DU 2026-07-30, ou c'etait le PSEUDO
   qui tombait a zero. Et il etait, lui aussi, invisible pour un controle qui ne
   verifie que « la pastille tient sur une ligne » : elle y tenait parfaitement
   — en effacant une information.

   Chacun des deux garde donc desormais un plancher : 3ch pour le pseudo (regle
   de base, inchangee) et 4ch ici pour l'organisation. LA PRIORITE N'EST PAS
   TOUCHEE : c'est toujours l'organisation qui cede la premiere, jusqu'a son
   plancher, et le pseudo ensuite. La capsule ne se replie toujours pas.

   ⚠️ POURQUOI 4ch, ET PAS PLUS — C'EST MESURE, PAS CHOISI A VUE. A 390 px, le
   pseudo et l'organisation se partagent 148 px : ce que l'un prend en plancher,
   l'autre le perd. Largeur VISIBLE du pseudo, mesuree en navigateur sur le meme
   etat, aux trois valeurs essayees :

     plancher   pseudo « s870000 »       pseudo « Konstantinopolis »
       6ch       92 / 104  TRONQUE         92 / 180
       5ch      101 / 104  TRONQUE        101 / 180
       4ch      104 / 104  ENTIER         111 / 180

   4ch est la SEULE valeur ou un pseudo de longueur ORDINAIRE — ceux que le jeu
   engendre lui-meme — n'est pas tronque du tout. L'organisation y garde 37 px,
   soit deux caracteres et des points de suspension, JUSTE A COTE DE SON BLASON,
   qui l'identifie deja ; son nom complet reste en infobulle et en toutes lettres
   dans le Profil joueur. Au-dela de 4ch, on abime le pseudo pour gagner une
   lettre d'organisation : c'est le mauvais echange.

   ⚠️ CE QUI RESTE VRAI ET N'EST PAS CORRIGE : a 390 px, un pseudo de 16
   caracteres (le maximum que le jeu ACCEPTE, mais qu'il n'engendre jamais) reste
   tronque, a 111 px sur 180. Il n'y a pas de reglage qui l'evite — les elements
   incompressibles de la capsule (drapeau, age, blason, rang VRS) en occupent
   deja l'essentiel. Le seul moyen serait de replier la capsule sur deux lignes,
   ce que cette tache retire precisement. */
html.theme-clair .hud-team-nom { min-width: 4ch; }
/* ⚠️ … SAUF QUAND UN ORNEMENT EST PORTE (2026-08-12), et c'est une MESURE qui l'a
   impose. Le plancher de 4ch maintenu, l'emplacement de l'en-tete tombait a ZERO
   PIXEL aux DEUX largeurs sur le pire cas du jeu (pseudo de 16 caracteres) :
   l'objet porte etait invisible, et depuis qu'il ouvre un panneau, sa zone
   tapable etait introuvable. Un ornement replie a un filet ne montre RIEN — ce
   n'est pas du texte tronque, c'est un dessin efface.
   L'ordre de cession devient donc, et seulement dans ce cas : le NOM
   d'organisation d'abord, JUSQU'A ZERO — son BLASON reste, juste a cote, et
   l'identifie deja ; son nom complet reste en infobulle et en toutes lettres dans
   le Profil joueur —, l'emplacement JAMAIS, le pseudo protege comme avant.
   Sans ornement, ce marqueur tombe et le plancher de 4ch revient : la pastille
   retrouve exactement sa mise en page d'avant. */
html.theme-clair .hud-pill.porte .hud-team-nom { min-width: 0; }

/* CINQ TUILES A 390 px. La rangee passe de quatre a cinq elements : les
   gouttieres et le rembourrage sont RESSERRES, jamais la taille des valeurs —
   c'est le chiffre de la fortune et la note de niveau qui doivent rester
   lisibles, pas l'espace autour d'eux. */
@media (max-width: 430px) {
  html.theme-clair .hud-tiles { gap: 5px; }
  html.theme-clair .hud-tile { padding: 8px 4px; }
}

/* ==========================================================================
   ECRAN DISTINCTIONS — LE MUR                                    (2026-07-31)

   L'ecran s'ouvre sur ce que le joueur A GAGNE : en-tete, puis le mur des
   ecussons obtenus. Ce qui manque vient APRES, dans deux sections repliees.

   ⚠️ CONTRAINTE TENUE PAR CE BLOC : replie, l'ecran doit tenir sur une hauteur
   de telephone SANS DEFILEMENT. C'est le plafond de huit ecussons (js/main.js)
   et le repliement des deux sections qui le permettent — d'ou des marges
   volontairement serrees. Deplier une section ou ouvrir la collection complete
   peut defiler, c'est normal et assume.
   ========================================================================== */
#screen-distinctions .dst-head { padding: 14px 16px 13px; margin: 0 0 12px; }
.dst-head-l { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
#screen-distinctions .dst-title {
  margin: 0; font-size: 1.2rem; font-weight: 800; letter-spacing: .2px; color: var(--ds-text);
}
.dst-cnt {
  flex: 0 0 auto; font-size: 1rem; font-weight: 800; color: var(--ds-accent-deep);
  font-variant-numeric: tabular-nums;
}
/* IDENTITE : drapeau, pseudo (dans sa couleur de palier, inchangee), poste,
   organisation, age. Une seule ligne, tronquee plutot que repliee. */
.dst-id {
  margin: 5px 0 9px; font-size: .78rem; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dst-id-flag { margin-right: 5px; }
.dst-id-sec { color: var(--ds-text-dim); font-weight: 600; }
/* Fine barre de progression doree, comme toutes les jauges du jeu. */
.dst-prog-piste { height: 6px; border-radius: 999px; background: var(--ds-track); overflow: hidden; }
.dst-prog-piste > i {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--ds-accent-light), var(--ds-accent));
}

/* LE MUR : QUATRE ECUSSONS PAR LIGNE, et AUCUN PLAFOND depuis le 2026-08-12 — il
   portait huit ecussons plus une case « +N Tout voir », qui cachait le reste de la
   collection. Les colonnes sont egales et fixes en fraction : la grille reste
   alignee que la derniere ligne soit pleine ou non, quel qu'en soit le nombre. */
.dst-mur {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 12px 6px; margin: 0 0 14px; padding: 0 2px;
}
.dst-case {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  border: 0; background: none; padding: 0; font: inherit; cursor: pointer;
  min-width: 0;
}
.dst-case:focus-visible { outline: 2px solid var(--ds-accent-deep); outline-offset: 3px; border-radius: 8px; }
/* ⚠️ SANS APPELANT depuis le 2026-08-12 (retrait du plafond du mur), conservee comme
   chemin de rollback avec `.dse-plus` et `UI.ecussonPlusHTML`. */
.dst-case-plus { cursor: default; }
/* LE NOM COMPLET SOUS CHAQUE ECUSSON, en 8 px : le code de quatre caracteres ne
   doit jamais etre la seule facon de savoir ce qu'un ecusson veut dire. */
.dst-case-nom {
  font-size: 8px; font-weight: 700; line-height: 1.25; text-align: center;
  color: var(--ds-text-dim); width: 100%; overflow-wrap: anywhere;
}
.dst-note { margin: -6px 0 12px; font-size: .72rem; text-align: center; }
.dst-vide { padding: 16px; margin: 0 0 12px; }
.dst-vide p { margin: 0; font-size: .82rem; line-height: 1.4; color: var(--ds-text-dim); }

/* --- LES DEUX SECTIONS REPLIEES ----------------------------------------
   Repliees, elles ne coutent qu'une ligne chacune : c'est ce qui fait tenir
   l'ecran sur une hauteur de telephone. */
.dst-sec-h {
  display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box;
  margin: 0 0 8px; padding: 11px 13px;
  border: 1px solid var(--ds-line); border-radius: var(--ds-radius-tile);
  background: var(--ds-card); color: var(--ds-text);
  font: inherit; text-align: left; cursor: pointer;
}
.dst-sec-h:hover { background: var(--ds-field-bg); }
.dst-sec-h:focus-visible { outline: 2px solid var(--ds-accent-deep); outline-offset: 2px; }
.dst-sec-t { flex: 1 1 auto; min-width: 0; font-size: .82rem; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dst-sec-n {
  flex: 0 0 auto; font-size: .76rem; font-weight: 800; color: var(--ds-text-dim);
  font-variant-numeric: tabular-nums;
}
.dst-sec-ch { flex: 0 0 auto; color: var(--ds-text-faint); font-size: .95rem; line-height: 1; transition: transform .15s ease; }
.dst-sec-h.ouvert .dst-sec-ch { transform: rotate(90deg); }
.dst-sec-b { padding: 2px 12px; margin: -4px 0 10px; }
/* UNE LIGNE DEPLIEE : l'ecusson verrouille (colonne fixe), le nom et sa phrase,
   puis ce qui manque — « Verrouille », ou le poste requis. */
.dst-row {
  display: grid; grid-template-columns: 40px 1fr auto; align-items: start; gap: 10px;
  width: 100%; box-sizing: border-box; padding: 10px 2px; text-align: left;
  border: 0; border-top: 1px solid var(--ds-line); background: none;
  font: inherit; color: inherit; cursor: pointer;
}
.dst-row:first-child { border-top: 0; }
.dst-row:focus-visible { outline: 2px solid var(--ds-accent-deep); outline-offset: -2px; }
.dst-row-ec { display: flex; align-items: flex-start; }
.dst-txt { min-width: 0; }
.dst-nom { display: block; font-size: .84rem; font-weight: 800; color: var(--ds-text-dim); line-height: 1.25; overflow-wrap: anywhere; }
.dst-cond { display: block; margin: 3px 0 0; font-size: .72rem; line-height: 1.35; color: var(--ds-text-dim); overflow-wrap: anywhere; }
.dst-val { font-size: .72rem; font-weight: 800; white-space: nowrap; color: var(--ds-good); font-variant-numeric: tabular-nums; padding-top: 1px; }
.dst-val.off { color: var(--ds-text-faint); font-weight: 700; }

/* ==========================================================================
   LA VITRINE DE FIN DE CARRIERE — case « Distinctions »          (2026-07-31)

   La case ne melange plus ecussons et listes de texte : elle ne montre QUE les
   badges, tous ceux qui sont obtenus, sans plafond ni case « +N » (on est en fin
   de carriere, le defilement y est normal).

   TROIS CHOIX DE MISE EN PAGE QUI SE TIENNENT ENSEMBLE :
     1. les cellules font EXACTEMENT 25 % de largeur, donc quatre par ligne, quel
        que soit le nombre d'ecussons de la derniere rangee ;
     2. tous les ecussons ont la MEME TAILLE (58 px) — le metal se lit a la
        couleur, jamais a la taille, sans quoi la grille se deformerait ;
     3. le nom sous l'ecusson a une HAUTEUR FIXE. C'est lui qui garantit
        l'alignement au pixel des rangees : sans hauteur fixe, un nom sur deux
        lignes decalerait toute la rangee suivante.
   ========================================================================== */
.fcv {
  position: relative; overflow: hidden;
  margin: 0 0 4px; padding: 18px 14px 14px;
  border-radius: 22px;
  background: linear-gradient(168deg, var(--ds-accent-wash-1) 0%, var(--ds-accent-wash-2) 52%, var(--ds-accent-wash-3) 100%);
  box-shadow: 0 14px 34px rgba(170, 125, 25, .26);
}
/* Liseré interieur blanc translucide : pose en `inset` pour ne pas manger de
   place et ne jamais decaler la grille d'un demi-pixel. */
.fcv::before {
  content: ""; position: absolute; inset: 0; border-radius: 22px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .62);
  pointer-events: none; z-index: 2;
}
/* REFLET : il traverse LA CARTE ENTIERE en diagonale, pas chaque ecusson (ceux-ci
   ont deja le leur, plus court). Purement decoratif, il n'intercepte aucun tap. */
.fcv::after {
  content: ""; position: absolute; top: -60%; bottom: -60%; left: -60%; width: 55%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .58) 50%, rgba(255, 255, 255, 0) 100%);
  transform: rotate(18deg); pointer-events: none; z-index: 1;
  animation: fcv-reflet 7s ease-in-out infinite;
}
@keyframes fcv-reflet {
  0%, 74% { left: -60%; }
  100% { left: 125%; }
}
@media (prefers-reduced-motion: reduce) {
  .fcv::after { animation: none; display: none; }
}
.fcv-head { position: relative; z-index: 3; text-align: center; }
.fcv-sur {
  margin: 0; font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .2em; color: var(--ds-accent-ink);
}
/* LE COMPTEUR EN TRES GROS : c'est le sujet de la case. Le denominateur est plus
   petit et plus clair — on veut lire « 16 » d'abord, « sur 30 » ensuite. */
.fcv-cnt {
  margin: 6px 0 0; font-size: 34px; font-weight: 800; line-height: 1;
  color: var(--ds-accent-ink); font-variant-numeric: tabular-nums;
}
.fcv-den { font-size: 19px; font-weight: 700; color: var(--ds-accent-deep); }
.fcv-piste {
  margin: 11px auto 0; width: 74%; height: 6px; border-radius: 999px;
  background: rgba(150, 110, 30, .18); overflow: hidden;
}
.fcv-piste > i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--ds-fill-1), var(--ds-fill-2)); }
/* Filet dore pale PLEINE LARGEUR : il separe l'en-tete de la grille. */
.fcv-filet {
  position: relative; z-index: 3; height: 1px; margin: 14px 0 13px;
  background: linear-gradient(90deg, rgba(176, 133, 34, .05), rgba(176, 133, 34, .38), rgba(176, 133, 34, .05));
}
.fcv-grille {
  position: relative; z-index: 3;
  display: flex; flex-wrap: wrap; align-items: flex-start; row-gap: 12px;
}
.fcv-cell {
  width: 25%; box-sizing: border-box; padding: 0 2px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  min-width: 0;
}
/* LE CONTENEUR QUI EPOUSE LE SVG. La pastille de compte est en position absolue
   par rapport a LUI, et non a la cellule : elle reste donc collee a son ecusson
   quelle que soit la largeur de la cellule. `line-height: 0` supprime la
   gouttiere de ligne sous le SVG, sans quoi le conteneur serait plus haut que le
   dessin et la pastille flotterait au-dessus. */
.fcv-ec { position: relative; display: inline-block; line-height: 0; }
/* HAUTEUR FIXE : deux lignes de 8 px au maximum. C'est ce qui aligne les rangees
   au pixel meme quand un nom est long. Au-dela, le nom est coupe — le libelle
   complet reste lisible dans la bulle de l'ecran Distinctions. */
.fcv-nom {
  font-size: 8px; font-weight: 700; line-height: 1.25; text-align: center;
  height: 20px; overflow: hidden; width: 100%;
  color: var(--ds-accent-ink); overflow-wrap: anywhere;
}
/* SEPARATEUR DE METAL : un filet tres pale, transparent aux extremites, qui prend
   toute la largeur de la grille et force donc un retour a la ligne. */
.fcv-sep {
  width: 100%; height: 1px; margin: 2px 0;
  background: linear-gradient(90deg, rgba(176, 133, 34, 0) 0%, rgba(176, 133, 34, .22) 22px,
              rgba(176, 133, 34, .22) calc(100% - 22px), rgba(176, 133, 34, 0) 100%);
}
.fcv-vide {
  position: relative; z-index: 3; margin: 0; text-align: center;
  font-size: .82rem; color: var(--ds-accent-ink);
}

/* ==========================================================================
   BULLE DE DETAIL D'UN ECUSSON                                   (2026-07-31)
   Elle vit hors des ecrans et se superpose a celui qui est affiche. Un ecusson
   verrouille ouvre exactement la meme bulle : « Pas encore obtenu » en gris
   remplace la pastille doree, et rien d'autre ne change.
   ========================================================================== */
.dse-bulle { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; padding: 20px; }
.dse-bulle[hidden] { display: none; }
.dse-bulle-fond { position: absolute; inset: 0; background: rgba(18, 28, 45, .52); }
.dse-bulle-carte {
  position: relative; width: 100%; max-width: 320px; box-sizing: border-box;
  padding: 20px 20px 16px; text-align: center;
  background: var(--ds-card); border-radius: 18px;
  box-shadow: 0 18px 44px rgba(20, 35, 60, .32);
}
.dse-b-fam { margin: 0 0 12px; font-size: .64rem; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ds-accent-deep); }
.dse-b-ec { display: flex; justify-content: center; margin: 0 0 12px; }
.dse-b-nom { margin: 0; font-size: 1.06rem; font-weight: 800; color: var(--ds-text); line-height: 1.25; }
.dse-b-txt { margin: 7px 0 13px; font-size: .8rem; line-height: 1.4; color: var(--ds-text-dim); }
/* La valeur en PASTILLE DOREE : la date, ou le nombre d'obtentions. */
.dse-b-val {
  display: inline-block; margin: 0 0 4px; padding: 5px 13px;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border-radius: 999px; font-size: .78rem; font-weight: 800;
}
.dse-b-val.off { background: var(--ds-field-bg); color: var(--ds-text-dim); }
.dse-bulle-ok { margin-top: 14px; width: 100%; }

/* ==========================================================================
   LIGNE D'ACCES « MES DISTINCTIONS » — en tete du detail de la tuile Palmares
   du Profil joueur. Deuxieme porte vers le meme ecran ; le reste de la tuile
   est inchange.
   ========================================================================== */
.dst-acces {
  display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box;
  margin: 0 0 12px; padding: 10px 12px;
  border: 1px solid var(--ds-line); border-radius: var(--ds-radius-tile);
  background: var(--ds-card); color: var(--ds-text);
  font: inherit; text-align: left; cursor: pointer;
}
.dst-acces:hover { background: var(--ds-field-bg); }
.dst-acces-lab { flex: 1 1 auto; min-width: 0; font-size: .84rem; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dst-acces-n { flex: 0 0 auto; font-size: .78rem; font-weight: 800; color: var(--ds-accent-deep); font-variant-numeric: tabular-nums; }
.dst-acces-ch { flex: 0 0 auto; color: var(--ds-text-faint); font-size: .9rem; line-height: 1; }

/* ==========================================================================
   BLOC COMPACT « NOUVEAUX BADGES » — ecran de fin de saison
   Pas une carte plein ecran par badge : trente-quatre interruptions ruineraient
   le rythme. Une seule carte, la liste des ecussons gagnes dans la saison, et
   rien du tout si la saison n'en a rapporte aucun.
   ========================================================================== */
.dsn { margin: 16px 0 0; padding: 13px 15px; }
.dsn-sur { font-size: .68rem; font-weight: 800; letter-spacing: 1.1px; text-transform: uppercase; color: var(--ds-text-dim); margin: 0 0 9px; }
.dsn-l { display: flex; align-items: center; gap: 11px; padding: 7px 0; }
.dsn-l + .dsn-l { border-top: 1px solid var(--ds-line); }
.dsn-nom { font-size: .84rem; font-weight: 800; color: var(--ds-text); min-width: 0; overflow-wrap: anywhere; }

/* ==========================================================================
   ECRAN COMPACT DU CALENDRIER DE SAISON                        (2026-07-31)
   Il tient sur UNE hauteur de telephone a 390 px, calendrier le plus charge
   compris (16 tournois). Trois arbitrages lisibles d'un coup d'oeil : les jours
   passes dehors, la Forme qu'il en restera, ce que les organisateurs tolerent.

   ⚠️ AUCUNE COULEUR EN DUR ICI : tout passe par les jetons de role poses le
   2026-07-31 (socle des themes). Les quatre surfaces d'etat et le rail de
   l'interrupteur sont declares dans les deux `:root`.
   ========================================================================== */
/* `cal-mode` : les deux marges mortes de la page, resserrees le temps de cette
   etape seulement. Le blanc sous l'en-tete de saison et le blanc sous le bouton
   valent a eux deux 70 px, soit trois lignes de tournoi. Rien n'est masque. */
#screen-season.cal-mode { padding-top: 10px; padding-bottom: 12px; }
#screen-season.cal-mode .hud { margin-bottom: 8px; }

.cal2-head {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px 10px;
}
/* --- 1. tournois retenus --- */
.c2-l1 { display: flex; align-items: baseline; gap: 6px; }
.c2-big { font-size: 21px; font-weight: 800; color: var(--txt); font-variant-numeric: tabular-nums; line-height: 1; }
.c2-sub { font-size: .72rem; color: var(--txt-dim); min-width: 0; }
.c2-min { margin-left: auto; font-size: .58rem; color: var(--txt-faint); flex: 0 0 auto; white-space: nowrap; }
/* --- 2. les deux compteurs --- */
.c2-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 6px; }
.c2-cnt { background: var(--bg-3); border-radius: 9px; padding: 3px 8px; min-width: 0; }
.c2-cl { display: block; font-size: .56rem; letter-spacing: .4px; text-transform: uppercase; color: var(--txt-faint); }
.c2-cv { display: block; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.2; }
.c2-accent { color: var(--accent-2); }
.c2-bon { color: var(--good); }
.c2-mauvais { color: var(--bad); }
/* --- 3. et 4. les deux barres --- */
.c2-blk { margin-top: 6px; }
.c2-bl { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: .68rem; color: var(--txt-dim); }
.c2-bl strong { font-size: 13px; font-variant-numeric: tabular-nums; }
.c2-bar { position: relative; height: 6px; margin-top: 3px; border-radius: 3px; background: var(--bg-3); }
.c2-bar i { position: absolute; left: 0; top: 0; height: 100%; border-radius: 4px; transition: width .18s ease; }
.c2-f-bon { background: var(--good); }
.c2-f-mauvais { background: var(--bad); }
/* Segment de fraicheur GAGNEE (u) ou PERDUE (s) par rapport a la jauge de Forme. */
.c2-bar u { position: absolute; top: 0; height: 100%; background: var(--good); opacity: .55; border-radius: 0 4px 4px 0; }
.c2-bar s { position: absolute; top: 0; height: 100%; background: var(--bad); opacity: .55; }
/* Le TRAIT du seuil : il doit se lire par-dessus le remplissage, dans les deux sens. */
.c2-bar b { position: absolute; top: -3px; width: 2px; height: 13px; margin-left: -1px; border-radius: 1px; background: var(--txt); }
/* ⚠️ `.c2-ticks` (graduations 0 / seuil / 365) et `.c2-forme` (l'encadre a verdict
   vert/rouge) NE SONT PLUS EMPLOYES depuis le 2026-07-31 : la barre des jours hors de
   chez soi a ete retiree, et l'encadre de Forme remplace par `.c2-fr`. Regles laissees
   en place pour rollback, comme `.caltour` et consorts plus haut ; a retirer lors de la
   passe de nettoyage decidee a part. */
.c2-ticks { position: relative; height: 10px; margin-top: 4px; font-size: .55rem; line-height: 1; color: var(--txt-faint); }
.c2-ticks .c2-t0 { position: absolute; left: 0; }
.c2-ticks .c2-t1 { position: absolute; right: 0; }
.c2-ticks .c2-ts { position: absolute; transform: translateX(-50%); white-space: nowrap; color: var(--txt-dim); }
.c2-forme { padding: 4px 8px 4px; border-radius: 10px; border: 1px solid transparent; }
.c2-forme.ok { background: var(--c2-ok-bg); border-color: var(--c2-ok-line); }
.c2-forme.ko { background: var(--c2-ko-bg); border-color: var(--c2-ko-line); }
/* --- 3. JOURS HORS DE CHEZ SOI : une simple ligne d'information (2026-07-31) ---
   Ni couleur d'alerte, ni repere de seuil, ni barre. L'audit du 2026-07-31 a mesure
   que le depassement est l'etat NORMAL du haut du circuit (97,9 % des saisons de
   tier 0) et qu'il coute 0,02 point de jauge d'une saison a la suivante. */
.c2-info { display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 5px 0 0; font-size: .64rem; line-height: 1.2; color: var(--txt-dim); }
.c2-info strong { font-size: 12px; font-weight: 700; color: var(--txt-dim); font-variant-numeric: tabular-nums; }
/* --- 4. FORME AUX GRANDS RENDEZ-VOUS : l'encadre qui REAGIT --- */
/* La teinte suit la FRAICHEUR — la seule grandeur de cet encadre qui bouge quand le
   joueur bascule un tournoi. A zero l'encadre est neutre : il n'y a rien a feter et
   rien a craindre, c'est le calendrier par defaut. */
/* ⚠️ CHAQUE PIXEL EST COMPTE ICI. L'encadre a quatre lignes la ou l'ancien en avait
   deux ; sans ce resserrage l'ecran repassait a 857 px et se remettait a defiler de
   13 px, ce que la refonte du df75f37 avait justement supprime. Aucune information
   n'est retiree : seuls les interlignes et deux tailles de police bougent. */
.c2-fr { padding: 3px 8px; border-radius: 10px; border: 1px solid var(--line); background: var(--bg-3); }
.c2-fr.plus { background: var(--c2-ok-bg); border-color: var(--c2-ok-line); }
.c2-fr.moins { background: var(--c2-ko-bg); border-color: var(--c2-ko-line); }
.c2-fv { font-size: 17px; font-weight: 800; color: var(--txt); line-height: 1.15; }
/* La decomposition « 81 de base + 3.5 de fraicheur » : c'est elle qui rend le grand
   nombre lisible, donc elle reste au-dessus de la taille des mentions. */
.c2-fd { margin: 0; font-size: .58rem; line-height: 1.2; color: var(--txt-dim); font-variant-numeric: tabular-nums; }
.c2-frl { margin-top: 2px; }
.c2-frl strong { font-size: 12px; }
/* Le rail de la barre de fraicheur porte `--bg-3`, la MEME couleur que le fond de
   l'encadre au repos : a fraicheur nulle, la barre disparaissait purement et
   simplement et laissait un blanc inexplique. Ici le rail est celui des
   interrupteurs, visible sur les trois teintes de l'encadre. */
.c2-fr .c2-bar { background: var(--c2-rail); }
.c2-fp { margin: 2px 0 0; font-size: .56rem; line-height: 1.2; color: var(--txt-dim); overflow-wrap: anywhere; }
/* --- 5. programme de fidelite : un point par invitation toleree --- */
/* Titre et pastilles sur la MEME ligne : le titre seul coutait une ligne. */
.c2-fid { margin-top: 5px; display: flex; align-items: center; gap: 8px; }
.c2-fidt { flex: 0 0 auto; max-width: 92px; margin: 0; font-size: .5rem; font-weight: 800; letter-spacing: .7px; line-height: 1.15; text-transform: uppercase; color: var(--txt-faint); }
/* gap 3 et rembourrage 5 px : MESURE, pas gout. A 390 px, avec deux mentions
   affichees, les quatre pastilles totalisaient 346 px pour 342 disponibles et
   passaient sur une seconde rangee — 25 px de page pour 4 px de trop. */
.c2-pastilles { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; gap: 3px; }
.c2-past { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0;
  background: var(--bg-3); border-radius: 8px; padding: 2px 5px; }
/* 52 px et non 66 : la mention (« quota », « -1 invit ») s'ajoute SUR LA MEME LIGNE,
   et a 390 px les pastilles passaient sur une seconde rangee des que plusieurs
   organisateurs etaient au quota. Valeur MESUREE, pas choisie. */
.c2-pn { font-size: .55rem; color: var(--txt-dim); max-width: 52px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c2-pd { display: flex; gap: 3px; }
.c2-pd i { width: 6px; height: 6px; border-radius: 50%; background: var(--c2-rail); }
.c2-pd i.use { background: var(--bad); }
/* TROIS ETATS, TROIS TEINTES (limite SOUPLE, 2026-07-31) : neutre tant qu'il reste des
   refus toleres, ACCENT au quota pile — c'est une annonce, pas une interdiction : le
   refus suivant reste possible et se paiera — et ALERTE au-dela, avec le cout chiffre. */
.c2-past.quota { background: var(--c2-ac-bg); }
.c2-past.quota .c2-pn, .c2-past.quota .c2-pm { color: var(--accent-2); font-weight: 700; }
.c2-past.depasse { background: var(--c2-ko-bg); }
.c2-past.depasse .c2-pn, .c2-past.depasse .c2-pm { color: var(--bad); font-weight: 700; }
.c2-ph { display: flex; align-items: baseline; gap: 3px; max-width: 100%; min-width: 0; }
.c2-pm { flex: 0 0 auto; font-size: .5rem; letter-spacing: .2px; line-height: 1.1; white-space: nowrap; }
/* La ligne de cout, sous les pastilles : le prix exact, ou l'absence de prix. */
.c2-fmsg { margin: 3px 0 0; font-size: .54rem; line-height: 1.2; color: var(--txt-faint); overflow-wrap: anywhere; }
.c2-fmsg.ko { color: var(--bad); font-weight: 600; }
/* --- 6. notes d'une ligne (sanction, coupure, Grand Slam) --- */
.c2-note { margin: 6px 0 0; font-size: .56rem; line-height: 1.25; color: var(--txt-faint); overflow-wrap: anywhere; }
.c2-nk { color: var(--bad); font-weight: 700; }
.c2-no { color: var(--good); font-weight: 700; }
.c2-ng { color: var(--accent-2); font-weight: 700; }

/* --- LA LISTE : une ligne par tournoi ------------------------------------- */
.cal2-list { margin-top: 6px; background: var(--bg-card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1px 5px; }
/* 20 px par ligne : c'est le pas qui fait tenir SEIZE tournois sous la hauteur d'un
   telephone. L'interrupteur (16 px) reste l'ancre visuelle et la LIGNE ENTIERE est
   la cible du tap, jamais le seul texte. */
.c2-row { display: flex; align-items: center; gap: 6px; padding: 0 3px; min-height: 20px;
  border-radius: 6px; cursor: pointer; }
.c2-row + .c2-row, .c2-det + .c2-row { border-top: 1px solid var(--line); }
.c2-row.ouvert { background: var(--bg-3); }
.c2-m { flex: 0 0 auto; width: 24px; font-size: .55rem; letter-spacing: .4px; color: var(--txt-faint); }
.c2-n { flex: 1 1 auto; min-width: 0; font-size: .74rem; font-weight: 600; color: var(--txt);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Incontournable : nom en dore, jamais d'interrupteur. */
.c2-row.oblig .c2-n { color: var(--accent-2); font-weight: 800; }
/* Saute : gris clair, jamais illisible. */
.c2-row.saute .c2-n { color: var(--txt-faint); font-weight: 500; text-decoration: line-through;
  text-decoration-color: var(--txt-faint); }
.c2-org { flex: 0 0 auto; max-width: 54px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: .53rem; letter-spacing: .2px; color: var(--txt-dim); background: var(--bg-3);
  border-radius: 5px; padding: 1px 4px; }
/* ⚠️ `.c2-org.plein` n'est plus employe depuis le 2026-07-31 : un organisateur au
   quota ne fige plus rien, c'est l'etiquette de cout `.c2-cout` qui porte le signal.
   Regle laissee pour rollback. */
.c2-org.plein { background: var(--c2-ko-bg); color: var(--bad); font-weight: 700; }
.c2-org-vide { color: var(--txt-faint); }
/* ETIQUETTE DE COUT d'une ligne declinee AU-DELA du quota de son organisateur. La
   variante `.nul` marque un refus hors quota qui ne coute plus rien : la sanction est
   forfaitaire par organisateur, le premier depassement l'a deja declenchee. */
.c2-cout { flex: 0 0 auto; white-space: nowrap; font-size: .5rem; font-weight: 700; letter-spacing: .2px;
  border-radius: 5px; padding: 1px 4px; background: var(--c2-ko-bg); color: var(--bad); }
.c2-cout.nul { background: var(--bg-3); color: var(--txt-faint); font-weight: 600; }
.c2-j { flex: 0 0 auto; width: 24px; text-align: right; font-size: .6rem; color: var(--txt-faint);
  font-variant-numeric: tabular-nums; }
/* L'INTERRUPTEUR remplace l'ancien bouton pleine largeur « Sauter ce tournoi ». */
.c2-sw { flex: 0 0 auto; position: relative; width: 28px; height: 16px; padding: 0; border: 0;
  border-radius: 8px; background: var(--c2-rail); cursor: pointer; transition: background .18s ease; }
.c2-sw i { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--c2-knob); transition: left .18s ease; }
.c2-sw.on { background: var(--good); }
.c2-sw.on i { left: 14px; }
/* ⚠️ `.c2-sw.fige` n'est plus employe depuis le 2026-07-31 : le quota de fidelite est
   redevenu une limite SOUPLE, l'interrupteur n'est JAMAIS fige. Seuls les cinq
   incontournables echappent au choix, et eux portent un cadenas au lieu d'un
   interrupteur. Regle laissee en place pour rollback. */
.c2-sw.fige, .c2-sw.on.fige { background: var(--c2-rail); cursor: not-allowed; }
.c2-lock { flex: 0 0 auto; width: 28px; display: flex; align-items: center; justify-content: center;
  color: var(--accent-2); }
.c2-lockico { display: block; }
/* --- LE DETAIL d'un tournoi (un seul deplie a la fois) --- */
/* LE DETAIL sur DEUX COLONNES : huit lignes empilees ajoutaient 110 px et faisaient
   defiler la page ; en deux colonnes elles en ajoutent la moitie. C'est le seul etat
   de l'ecran qui puisse depasser une hauteur, et seulement le temps d'un depliage. */
.c2-det { padding: 3px 4px 5px; }
.c2-det dl { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; }
.c2-det dl > div { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; padding: 0; min-width: 0; }
.c2-det dt { flex: 0 0 auto; font-size: .56rem; line-height: 1.5; color: var(--txt-faint); }
.c2-det dd { margin: 0; min-width: 0; text-align: right; font-size: .58rem; line-height: 1.5; color: var(--txt);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Bouton de validation RESSERRE : le bouton standard fait 76 px de haut avec sa
   marge, soit trois lignes de tournoi, pour un libelle d'une ligne. */
.c2-go { margin-top: 7px; padding: 10px 16px; font-size: .92rem; }

/* ⚠️ LES REGLES `.caltour`, `.ct-*`, `.pchip*`, `.cal-liste`, `.cal-lead`,
   `.cal-compteur`, `.cal-jours`, `.cal-coupure`, `.cal-recap`, `.cj-gain` PLUS
   HAUT NE SONT PLUS UTILISEES depuis cette refonte : plus aucune ne figure dans
   js/main.js. Elles sont CONSERVEES telles quelles pour rollback (l'ancien ecran
   se retrouve tel quel dans git), et parce que `.chg-*` reste employe ailleurs.
   A retirer lors d'une passe de nettoyage decidee a part. */

/* ===========================================================================
   ECRAN PROGRESSION — REFONTE DE PRESENTATION  (2026-07-31)

   L'ecran etait le dernier gros ecran encore en THEME SOMBRE avec le Palmares
   et « Comment ca marche ». Il passe au theme clair (`screen-progress` entre
   dans ECRANS_CLAIRS, js/ui.js) et toute son apparence est reecrite ici.

   AUCUNE COULEUR EN DUR dans ce bloc : tout vient des jetons du socle
   (`--ds-accent`, `--ds-info`, `--ds-good`, `--ds-bad`, surfaces et textes).
   Les SEULES couleurs qui n'en viennent pas sont celles des METAUX, et elles
   ne sont pas ecrites ici non plus : elles arrivent en ligne, depuis la table
   unique `DSE_METAUX` de js/ui.js (degrades SVG des medaillons, degrade des
   barres de progression via `UI.metalDegrade`). Une couleur qui porte un sens
   ne suit pas le theme, et ne se recopie pas.

   ⚠️ LES ANCIENNES REGLES `.jetons-head`, `.jh-*`, `.defi-neutral`, `.tabs`,
   `.tab`, `.quest-*`, `.perk-row`, `.perk-top`, `.perk-nom`, `.perk-state`,
   `.perk-cost`, `.perk-desc`, `.perk-actions`, `.perk-org`, `.equip-head` PLUS
   HAUT ne sont plus employees par cet ecran. `.perk-org-sel` l'est encore (le
   selecteur d'organisation est conserve tel quel), `.tabs`/`.tab` le sont
   ailleurs. Le reste est CONSERVE pour rollback, a retirer lors d'une passe de
   nettoyage decidee a part.
   =========================================================================== */

/* ------------------------------------------------------------ Le medaillon
   Un DISQUE, et le seul du jeu : la forme en ECU (`.dse`) reste strictement
   reservee aux 34 badges de distinction. Meme echelle de metaux, formes
   distinctes — c'est ce qui empeche de confondre les deux collections.
   Ombre portee LEGERE (la meme que les emblemes du theme clair), pas de
   biseau, pas de gravure, pas de ruban : tous testes et ecartes sur les ecus. */
.dsm { display: inline-block; flex: 0 0 auto; line-height: 0; }
.dsm svg { display: block; filter: drop-shadow(0 1px 2px rgba(30, 45, 80, .22)); }

/* ---------------------------------------------------------------- En-tete */
html.theme-clair #screen-progress .screen-title { margin-bottom: 12px; }
.pg-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 14px 16px; margin: 0 0 14px;
}
.pg-jet { display: flex; flex-direction: column; min-width: 0; }
.pg-jn { font-size: 2.1rem; font-weight: 800; line-height: 1; letter-spacing: -1px; color: var(--ds-accent-deep); }
.pg-jk { margin-top: 3px; font-size: .62rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
/* Le compteur de collection est un BLOC DE TEXTE aligne a droite, SUIVI de
   l'anneau. Le libelle est toujours a l'exterieur : pose au centre d'un anneau
   de 42 px il deborde des trois caracteres et se fait couper. */
.pg-col { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pg-ct { display: flex; flex-direction: column; align-items: flex-end; min-width: 0; }
.pg-ctn { font-size: 1rem; font-weight: 800; line-height: 1.1; color: var(--ds-text);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.pg-ctk { margin-top: 3px; font-size: .62rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.pg-anneau { display: block; flex: 0 0 auto; }

/* ------------------------------------------------- Le segmenteur d'onglets
   Fond gris pale, onglet actif en carte blanche. La barre est ecrite pour
   TROIS onglets : `grid-auto-flow: column` repartit a parts egales ce qui est
   rendu, deux aujourd'hui, trois le jour ou « Themes » existera — sans qu'une
   seule regle d'ici ait a changer. */
/* ⚠️ LA RANGEE DEFILE HORIZONTALEMENT DEPUIS LE CINQUIEME ONGLET (2026-08-12).
   Elle etait en colonnes EGALES (`grid-auto-columns: 1fr`), ce qui a suffi
   jusqu'a quatre. Mesure a 390 px : la rangee offre 350 px utiles, cinq colonnes
   egales font 66 px chacune, et « Avantages » (.86 rem) en demande 79 — le
   libelle se faisait couper, exactement le defaut qu'un quatrieme onglet avait
   deja fait apparaitre a la taille de police. Les colonnes passent donc en
   `auto` et la rangee defile : chaque libelle garde sa largeur naturelle, aucun
   n'est tronque, et un sixieme onglet s'y rangerait sans une ligne de code.
   `scrollbar-width: none` : la barre est inutile sur un ecran tactile et volerait
   6 px de hauteur a la rangee. */
.pg-tabs {
  display: grid; grid-auto-flow: column; grid-auto-columns: auto; gap: 4px;
  justify-content: start;
  background: var(--ds-field-bg); border-radius: var(--ds-radius-btn);
  padding: 4px; margin: 0 0 14px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.pg-tabs::-webkit-scrollbar { display: none; }
/* ⚠️ `min-width: 0` A ETE RETIRE, ET C'EST LUI QUI ECRASAIT LES LIBELLES. Sur un
   element de grille, la taille minimale automatique vaut le CONTENU MINIMAL :
   c'est elle qui empeche une piste de descendre sous la largeur du libelle.
   `min-width: 0` la desactivait — les cinq pistes tombaient a 67 px et les
   libelles debordaient de leur bouton en silence, sans que rien ne defile. */
.pg-tab {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: none; border: 0; border-radius: 11px; padding: 7px 9px;
  font: inherit; color: var(--ds-text-dim); cursor: pointer;
  white-space: nowrap;
}
.pg-tab.on { background: var(--ds-card); box-shadow: var(--ds-shadow-tile); color: var(--ds-text); }
.pg-tn { font-size: .86rem; font-weight: 700; line-height: 1.1; }
.pg-tc { font-size: .66rem; line-height: 1.1; color: var(--ds-text-faint); font-variant-numeric: tabular-nums; }
.pg-tab.on .pg-tc { color: var(--ds-accent-deep); font-weight: 700; }

/* ------------------------------------------------------- Cartes et sections */
.pg-sec { display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 2px 7px; font-size: .66rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.pg-sec b { font-size: .8rem; letter-spacing: 0; color: var(--ds-text-dim); font-variant-numeric: tabular-nums; }
.pg-card { background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 6px 12px; margin: 0 0 16px; }
.pg-vide { padding: 16px 14px; text-align: center; font-size: .84rem; color: var(--ds-text-dim); }

/* ------------------------------------------------ Une quete qui reste a faire
   UNE LIGNE, pas une carte : c'est ce qui fait tenir tout l'onglet sur une
   hauteur au lieu de neuf. La description n'apparait qu'au depliage. */
.pg-liste { padding: 4px 12px; }
.pg-q { display: flex; align-items: center; gap: 10px; padding: 7px 0; cursor: pointer;
  border-top: 1px solid var(--ds-line); min-width: 0; }
.pg-liste .pg-q:first-child { border-top: 0; }
.pg-q-c { display: flex; flex-direction: column; gap: 4px; flex: 1 1 auto; min-width: 0; }
.pg-q-n { font-size: .87rem; font-weight: 600; color: var(--ds-text); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* La barre reprend le degrade du METAL de la quete (pose en ligne depuis la
   table unique) : la couleur du medaillon se prolonge dans l'avancement. */
.pg-q-b { display: block; height: 5px; border-radius: var(--ds-radius-pill);
  background: var(--ds-track); overflow: hidden; }
.pg-q-b > i { display: block; height: 100%; border-radius: var(--ds-radius-pill); transition: width .3s ease; }
.pg-q-p { font-size: .7rem; color: var(--ds-text-faint); line-height: 1.2; }
.pg-q-r { flex: 0 0 auto; font-size: .76rem; font-weight: 700; color: var(--ds-text-dim);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.pg-q-d { margin: 0 0 7px 44px; font-size: .78rem; line-height: 1.35; color: var(--ds-text-dim); }
.pg-q-pt { color: var(--ds-accent-deep); font-weight: 600; }

/* ---------------------------------------------- Le mur des quetes accomplies
   Des medaillons, rien d'autre : aucun nom, aucune ligne de texte. Le nom
   s'obtient en touchant un medaillon, et s'affiche dans la legende. */
.pg-mur { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px; padding: 10px 0 4px; }
.pg-m { background: none; border: 0; padding: 0; line-height: 0; cursor: pointer; border-radius: 50%; }
.pg-m.on { box-shadow: 0 0 0 3px var(--ds-accent-soft-bg); }
.pg-filet { height: 1px; background: var(--ds-line); margin: 10px 0 0; }
.pg-leg { margin: 8px 0 10px; text-align: center; font-size: .78rem; color: var(--ds-text-faint); }
.pg-leg.on { color: var(--ds-text); font-weight: 700; }

/* -------------------------------------------------------- Onglet Avantages
   UNE SEULE grille de tuiles a deux colonnes — la meme forme que celle qui
   servira aux themes. Le liseré superieur de 3 px code l'etat. */
.pg-eq { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; margin: 0 2px 10px; }
.pg-eq-n { font-size: .8rem; font-weight: 700; color: var(--ds-text); }
.pg-eq-d { font-size: .7rem; color: var(--ds-text-faint); line-height: 1.25; }
.pg-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px; }
.pg-t {
  display: flex; flex-direction: column; gap: 5px; min-width: 0; cursor: pointer;
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); padding: 9px 11px 10px;
  border-top: 3px solid var(--ds-line);
}
.pg-t-eq { border-top-color: var(--ds-good); }
.pg-t-eu { border-top-color: var(--ds-text-faint); }
.pg-t-ac { border-top-color: var(--ds-accent); }
/* A MERITER : le lisere prend la couleur d'information, jamais celle de l'accent
   (qui dit « achetable ») ni celle d'un etat negatif (ce n'est pas un refus). */
.pg-t-lock { border-top-color: var(--ds-info); }

/* TITRE DE SECTION de l'onglet Themes. Douze tuiles a deux colonnes font six
   rangees : la liste est coupee en trois sections courtes plutot que de
   rapetisser les tuiles. Le titre est discret — c'est un reperage, pas un
   niveau de lecture supplementaire. */
.pg-sec {
  display: flex; align-items: baseline; gap: 6px;
  margin: 2px 2px 6px; font-size: .68rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .08em; color: var(--ds-text-dim);
}
.pg-sec-n { font-size: .66rem; font-weight: 700; color: var(--ds-text-faint);
  font-variant-numeric: tabular-nums; }
.pg-sec + .pg-grille { margin-bottom: 12px; }

/* ------------------------------------------------------------- Onglet Themes
   L'APERCU D'UN THEME. Un rectangle qui montre ses couleurs REELLES : le degrade
   de fond, une carte posee dessus, une pastille d'accent. Les trois valeurs
   viennent du catalogue et sont posees en attribut `style` par js/main.js — ces
   regles ne fixent donc QUE des formes, jamais une couleur de theme. Le seul
   ton ecrit ici est un gris NEUTRE a faible opacite : il creuse le contour et
   l'ombre de la carte, et il tient aussi bien sur un theme clair que sombre. */
.pg-ap {
  display: block; position: relative; height: 42px; border-radius: 10px;
  overflow: hidden; box-shadow: inset 0 0 0 1px rgba(128,128,128,.28);
}
.pg-ap-c {
  position: absolute; left: 7px; right: 7px; bottom: 7px; height: 17px;
  border-radius: 6px; box-shadow: 0 1px 3px rgba(128,128,128,.35);
}
.pg-ap-a {
  position: absolute; left: 7px; top: 7px; width: 12px; height: 12px;
  border-radius: var(--ds-radius-pill);
}
/* Une tuile DEPLIEE prend la largeur entiere : a 165 px de large, une
   description et un bouton ne sont pas lisibles. */
.pg-t.open { grid-column: 1 / -1; }
.pg-t-n { font-size: .84rem; font-weight: 700; color: var(--ds-text); line-height: 1.2; }
.pg-t-s { align-self: flex-start; font-size: .64rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; padding: 2px 7px; border-radius: var(--ds-radius-pill);
  background: var(--ds-field-bg); color: var(--ds-text-dim); }
.pg-t-s.bon { background: var(--ds-good); color: var(--ds-on-solid); }
/* CONDITION D'UN THEME A MERITER, ecrite a la place du prix. Elle n'est pas mise
   en capitales : « Passe par la FPL » se lit mieux tel quel, et la pastille est
   deja distinguee par son fond. */
.pg-t-s.lock { background: var(--ds-info-soft-bg); color: var(--ds-info-ink);
  text-transform: none; letter-spacing: 0; }
.pg-t-c { font-size: .8rem; font-weight: 700; color: var(--ds-accent-deep); font-variant-numeric: tabular-nums; }
/* HORS DE PORTEE : le prix passe en gris pale. On lit d'un coup d'oeil ce qui
   est atteignable, sans avoir a comparer chaque prix au solde. */
.pg-t-c.cher { color: var(--ds-text-faint); font-weight: 600; }
.pg-t-d { font-size: .8rem; line-height: 1.35; color: var(--ds-text-dim); }
.pg-t-a { display: flex; flex-wrap: wrap; gap: 8px; }
.pg-t-org { display: block; font-size: .78rem; color: var(--ds-text-dim); }
.pg-t-org .perk-org-sel { width: 100%; margin-top: 2px; }
.pg-t-warn { display: block; margin-top: 4px; color: var(--ds-accent-ink); }
/* ⚠️ LE BOUTON SECONDAIRE D'UNE TUILE DEPLIEE — defaut vu SUR UNE CAPTURE, pas
   par un test. `btn-ghost` vaut, en theme clair, `rgba(255,255,255,.72)` : sur
   la carte BLANCHE d'une tuile il devient invisible et « Retirer » se lit comme
   un libelle, pas comme une action. Meme defaut, meme famille et meme remede
   que le bouton « Sauter ce tournoi » du calendrier (`.ct-skip`) : fond
   gris-bleu clair et contour marque (jetons `--ds-btn-soft-*`), qui se voit sur
   du blanc SANS employer le dore, reserve a l'action principale (Acheter,
   Equiper). Un bouton desactive garde ce fond et perd son contraste de texte :
   il reste lisible, il ne se clique pas. */
html.theme-clair .pg-t-a .btn-ghost {
  background: var(--ds-btn-soft-bg);
  border: 1px solid var(--ds-btn-soft-line);
  color: var(--ds-btn-soft-txt);
  box-shadow: none;
}
html.theme-clair .pg-t-a .btn-ghost:hover { background: var(--ds-btn-soft-bg-h); color: var(--ds-text); }
html.theme-clair .pg-t-a .btn[disabled] { color: var(--ds-text-faint); cursor: default; }
html.theme-clair .pg-t-a .btn[disabled]:hover { background: var(--ds-btn-soft-bg); color: var(--ds-text-faint); }
.pg-t-a .btn { padding: 8px 14px; font-size: .82rem; }

/* ===========================================================================
   PALMARES ET « COMMENT CA MARCHE » — THEME CLAIR ET DEUX NIVEAUX (2026-08-01)

   Les deux derniers ecrans encore sombres. Leur conversion cloture le passage
   au theme clair : les DIX ecrans y sont, ce qui leve le prerequis de l'etape 2
   du moteur de themes (plus aucun ecran ne vit hors du socle de jetons).

   REGLES SUIVIES ICI, ET VERIFIEES PAR UN INVARIANT :
     1. AUCUNE COULEUR EN DUR. Tout vient des jetons `--ds-*` du socle. Les
        seules couleurs qui restent en dur dans ces deux ecrans sont celles qui
        PORTENT UN SENS et qui ne suivent aucun theme : les quatre metaux des
        ecussons (poses en ligne par `js/ui.js`), les couleurs de tier, les
        drapeaux et les blasons.
     2. TOUT EST SCOPE a `#screen-palmares` / `#screen-howto`. Ces deux ecrans
        reutilisent des composants partages (`.pstat`, `.award`, `.minitab`,
        `.list-line`, `.howto-table`, `.leg-row`, `.tshow-*`) dont certains
        gardent des couleurs sombres ecrites en dur pour les ecrans qui n'ont
        pas ete repris. Les corriger globalement toucherait ces ecrans-la ; on
        ne corrige donc QUE dans ces deux sections.
     3. AUCUN BOUTON INVISIBLE. `html.theme-clair .btn-ghost` vaut
        `rgba(255,255,255,.72)` : sur une carte blanche, il se lit comme un
        libelle et non comme une action. Le defaut a deja ete rencontre deux
        fois sur ce projet (« Sauter ce tournoi », puis « Retirer »). Meme
        remede ici, et pour TOUS les boutons de ces deux ecrans : fond gris-bleu
        clair et contour marque (jetons `--ds-btn-soft-*`).
   =========================================================================== */

/* Un element masque le reste MEME quand une regle ci-dessous lui donne un
   `display`. Sans cette ligne, un panneau d'onglet ou un chapitre replie
   resterait affiche et la hauteur mesuree n'aurait aucun sens. */
#screen-palmares [hidden], #screen-howto [hidden] { display: none !important; }

/* ---------------------------------------------------- EN-TETE : FLECHE + TITRE
   Le bouton « Retour » pleine largeur du bas disparait au profit de cette
   fleche : elle economise une hauteur de bouton ET rend le second niveau de
   navigation lisible (depuis un chapitre, elle ramene a la liste). */
.ecr-tete { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; min-width: 0; }
.ecr-tete .screen-title { margin: 0; font-size: 1.32rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.btn-retour {
  flex: 0 0 auto; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--ds-radius-btn); cursor: pointer; padding: 0;
  background: var(--ds-btn-soft-bg); border: 1px solid var(--ds-btn-soft-line); color: var(--ds-btn-soft-txt);
}
.btn-retour:hover { background: var(--ds-btn-soft-bg-h); color: var(--ds-text); }
.btn-retour:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }

/* -------------------------------------------- BOUTONS DES DEUX ECRANS (regle 3) */
#screen-palmares .btn-ghost, #screen-howto .btn-ghost {
  background: var(--ds-btn-soft-bg); border: 1px solid var(--ds-btn-soft-line);
  color: var(--ds-btn-soft-txt); box-shadow: none;
}
#screen-palmares .btn-ghost:hover, #screen-howto .btn-ghost:hover {
  background: var(--ds-btn-soft-bg-h); color: var(--ds-text); border-color: var(--ds-btn-soft-line);
}

/* ================= PALMARES : PLUS AUCUN SEGMENTEUR (2026-08-15) ===========
   Les quatre onglets et leur segmenteur (`.pl-tabs`, `.pl-tab`, `.pl-tn`) ont
   ete RETIRES avec la refonte : l'ecran est un seul ecran, et sa sous-page se
   rejoint par une ligne, pas par une piste d'onglets. Les regles ne sont pas
   gardees « au cas ou » — plus aucun element ne les porte, et une piste
   d'onglets morte dans la feuille aurait fait croire a un ecran qui n'existe
   plus. Les trois blocs ont leur propre bloc de regles, plus bas, apres celui
   de la ligne de classement dont ils doivent l'emporter sur les reprises.  */

/* ------------------------- PALMARES : LES DIX NOMBRES (sous-page) ---------- */
#screen-palmares .pstat-grid { gap: 8px; }
#screen-palmares .pstat {
  background: var(--ds-card); border: 0; box-shadow: var(--ds-shadow-tile);
  border-radius: var(--ds-radius-tile); padding: 9px 8px;
}
#screen-palmares .ps-val { font-size: 1.02rem; font-weight: 800; color: var(--ds-text); line-height: 1.15; }
#screen-palmares .ps-lab { font-size: .66rem; color: var(--ds-text-faint); line-height: 1.2; margin-top: 2px; }
#screen-palmares .est-note { margin: 8px 2px 0; color: var(--ds-text-faint); }

/* Ligne compacte depliable (roles joues, defis du jour). */
.pl-l { background: var(--ds-card); border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile); margin-top: 8px; }
.pl-l-t {
  display: flex; align-items: center; gap: 8px; width: 100%; border: 0; background: none;
  padding: 10px 12px; cursor: pointer; text-align: left; color: var(--ds-text);
}
.pl-l-n { flex: 1 1 auto; min-width: 0; font-size: .87rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-l-v { flex: 0 0 auto; font-size: .92rem; font-weight: 800; color: var(--ds-accent-deep); font-variant-numeric: tabular-nums; }
.pl-l-x, .tg-x, .ht-chap-x, .ht-sec-x {
  flex: 0 0 auto; width: 8px; height: 8px; border-right: 2px solid var(--ds-text-faint);
  border-bottom: 2px solid var(--ds-text-faint); transform: rotate(-45deg); transition: transform .18s ease;
}
.pl-l.on .pl-l-x, .tshow-group.on .tg-x, .ht-sec.on .ht-sec-x { transform: rotate(45deg); }
.pl-l-d { padding: 0 12px 10px; }
#screen-palmares .award-list { margin: 0; gap: 6px; }
#screen-palmares .award {
  background: var(--ds-accent-soft-bg); border: 0; color: var(--ds-accent-deep);
  padding: 4px 10px; font-size: .76rem;
}
#screen-palmares .list-line { border-bottom: 1px solid var(--ds-line); font-size: .84rem; padding: 6px 0; }
#screen-palmares .list-line .l-r { color: var(--ds-text-dim); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------- PALMARES : ONGLET « TROPHEES »
   UNE LIGNE PAR ORGANISATEUR, total a droite, detail au tap. Les classes
   `tshow`, `tshow-group` et `grandslam` sont conservees : un controle existant
   exige de trouver `.tshow-group.grandslam` porteur d'un `svg` dans cet ecran. */
#screen-palmares .tshow { margin-top: 0; }
#screen-palmares .tshow-group {
  background: var(--ds-card); border: 0; box-shadow: var(--ds-shadow-tile);
  border-radius: var(--ds-radius-tile); padding: 0; margin-bottom: 7px;
}
#screen-palmares .tshow-group.grandslam { background: var(--ds-accent-soft-bg); box-shadow: none; }
#screen-palmares .tshow-group.grandslam .tshow-fam { color: var(--ds-accent-deep); }
#screen-palmares .tshow-group.grandslam .tg-n { color: var(--ds-accent-ink); }
.tg-l {
  display: flex; align-items: center; gap: 9px; width: 100%; border: 0; background: none;
  padding: 9px 12px; cursor: pointer; text-align: left;
}
.tg-ic { flex: 0 0 auto; display: inline-flex; line-height: 0; }
#screen-palmares .tshow-fam { flex: 1 1 auto; min-width: 0; font-size: .87rem; font-weight: 600; color: var(--ds-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-n { flex: 0 0 auto; font-size: .92rem; font-weight: 800; color: var(--ds-text-dim); font-variant-numeric: tabular-nums; }
#screen-palmares .tshow-items { display: block; padding: 0 12px 9px; }
#screen-palmares .tshow-item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 5px 0; border-top: 1px solid var(--ds-line); font-size: .8rem;
}
#screen-palmares .tshow-lab { color: var(--ds-text-dim); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
#screen-palmares .tshow-c { flex: 0 0 auto; color: var(--ds-text-faint); font-variant-numeric: tabular-nums; }
#screen-palmares .tshow-anterieur {
  margin-top: 8px; font-size: .78rem; line-height: 1.4; color: var(--ds-text-dim);
  background: var(--ds-field-bg); border-radius: var(--ds-radius-tile); padding: 8px 11px;
}

/* ------------------------------------------ PALMARES : ONGLET « MES LEGENDES »
   C'est le HALL OF FAME de la feuille de route : le classement des carrieres
   terminees, chacune avec son meilleur badge et la couleur de pseudo de son
   palier. Une carriere = UNE ligne ; les descriptifs vivent dans le detail. */
#screen-palmares .sort-row { margin: 0 2px 9px; color: var(--ds-text-faint); font-size: .78rem; }
#screen-palmares .minitab {
  background: var(--ds-field-bg); border: 1px solid var(--ds-line); color: var(--ds-text-dim);
  padding: 4px 10px; font-size: .76rem;
}
#screen-palmares .minitab.on { background: var(--ds-accent-soft-bg); border-color: transparent; color: var(--ds-accent-deep); font-weight: 700; }
#screen-palmares .leg-row, .pa-hof .leg-row {
  background: var(--ds-card); border: 0; box-shadow: var(--ds-shadow-tile);
  border-radius: var(--ds-radius-tile); padding: 0; margin-bottom: 7px;
}
#screen-palmares .leg-top, .pa-hof .leg-top { display: flex; align-items: center; gap: 8px; padding: 8px 11px; }
.leg-rang {
  flex: 0 0 auto; min-width: 17px; text-align: center; font-size: .78rem; font-weight: 800;
  color: var(--ds-text-faint); font-variant-numeric: tabular-nums;
}
.leg-ec { flex: 0 0 auto; display: inline-flex; align-items: center; line-height: 0; }
/* Emplacement VIDE : meme gabarit qu'un ecusson de 24 px, pour qu'une carriere
   sans badge exploitable dans son archive ne decale pas la ligne. */
.leg-ec-vide {
  display: inline-block; width: 24px; height: 28px; border-radius: 4px;
  background: var(--ds-field-bg); box-shadow: inset 0 0 0 1px var(--ds-line);
}
.leg-c { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.leg-l1 { display: flex; align-items: center; gap: 5px; min-width: 0; }
#screen-palmares .leg-nom, .pa-hof .leg-nom { font-size: .92rem; font-weight: 700; color: var(--ds-text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leg-sub { font-size: .7rem; color: var(--ds-text-faint); line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#screen-palmares .leg-right, .pa-hof .leg-right { flex: 0 0 auto; display: flex; align-items: center; gap: 5px; }
#screen-palmares .leg-right strong, .pa-hof .leg-right strong { font-size: .98rem; font-weight: 800; color: var(--ds-accent-deep); font-variant-numeric: tabular-nums; }
#screen-palmares .badge-defi, .pa-hof .badge-defi { background: var(--ds-field-bg); color: var(--ds-text-dim); font-size: .6rem; padding: 2px 5px; }
#screen-palmares .avant-badge, .pa-hof .avant-badge {
  background: var(--ds-accent-soft-bg); border: 0; color: var(--ds-accent-deep);
  font-size: .68rem; padding: 1px 6px; flex: 0 0 auto;
}
#screen-palmares .leg-detail { padding: 0 11px 10px; border-top: 1px solid var(--ds-line); margin-top: 2px; }
#screen-palmares .leg-meta { font-size: .76rem; line-height: 1.45; color: var(--ds-text-dim); padding: 8px 0 2px; }
#screen-palmares .leg-palier { color: var(--ds-accent-ink); font-weight: 700; }
#screen-palmares .est { color: var(--ds-text-faint); }
#screen-palmares .copybox { background: var(--ds-field-bg); border-color: var(--ds-line); color: var(--ds-text-dim); }
#screen-palmares .leg-actions { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
#screen-palmares .leg-actions .btn { margin-top: 0; }

/* ======================= PALMARES : LES TROIS BLOCS ========================
                                                                  (2026-08-15)
   L'ecran portait quatre onglets qui ne parlaient pas de la meme chose. Il
   porte desormais LE HEROS (une carriere), LA FORME (toutes les carrieres) et
   LA LISTE (une carte, une ligne par carriere), dans cet ordre — le changement
   d'echelle est ecrit a l'ecran au lieu d'etre subi.

   ⚠️ CES REGLES SONT POSEES APRES CELLES DE `.leg-*`, ET C'EST DELIBERE. La
   ligne de classement porte les DEUX jeux de classes (les nouvelles pour le
   dessin, les anciennes parce que des controles exterieurs la designent par
   elles). Dans `#screen-palmares` les nouvelles l'emportent par la specificite
   (`#id .pal-liste .pal-li` bat `#id .leg-row`) ; dans le cadre d'apercu du
   palier 6 du passe, les deux ont la MEME specificite et c'est l'ORDRE DE LA
   FEUILLE qui tranche. Remonter ce bloc rendrait au cadre d'apercu les cartes
   empilees que la refonte vient de retirer.

   ⚠️ AUCUNE COULEUR EN DUR ICI, ET LES CINQ SEGMENTS N'EN PORTENT AUCUNE : les
   quatre metaux arrivent EN LIGNE depuis `UI.DSE_METAUX` (la table unique du
   jeu, hors de portee des themes par construction) et le cinquieme prend le
   jeton `--ds-text-faint`. La feuille ne connait aucune de ces valeurs.  */

/* --------------------------------------------------------- BLOC 1 · LE HEROS */
#screen-palmares .pal-hero {
  display: flex; align-items: center; gap: 11px;
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); padding: 12px 13px; margin-bottom: 10px;
}
#screen-palmares .pal-hero-l { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
#screen-palmares .pal-hero-e {
  font-size: .62rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ds-text-faint); line-height: 1.2;
}
#screen-palmares .pal-hero-n {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  font-size: 1.22rem; font-weight: 800; line-height: 1.2; overflow: hidden;
}
#screen-palmares .pal-hero-s {
  font-size: .73rem; color: var(--ds-text-dim); line-height: 1.32;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#screen-palmares .pal-hero-t {
  align-self: flex-start; margin-top: 5px; padding: 3px 9px;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  border-radius: var(--ds-radius-pill); font-size: .71rem; font-weight: 800; line-height: 1.25;
}
#screen-palmares .pal-hero-r { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 3px; }
#screen-palmares .pal-hero-v {
  font-size: 1.04rem; font-weight: 800; color: var(--ds-accent-deep); font-variant-numeric: tabular-nums;
}
/* L'emplacement vide de l'ecu, au gabarit de l'ecu de 46 px : le bloc ne se
   deforme pas quand l'archive ne permet aucun badge. */
#screen-palmares .pal-hero-r .leg-ec-vide { width: 46px; height: 53px; border-radius: 6px; }

/* --------------------------------------------------------- BLOC 2 · LA FORME */
#screen-palmares .pal-forme {
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); padding: 11px 13px 12px; margin-bottom: 11px;
}
#screen-palmares .pal-forme-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: .78rem; font-weight: 600; color: var(--ds-text-dim);
}
#screen-palmares .pal-forme-h b { font-size: 1.02rem; font-weight: 800; color: var(--ds-text); font-variant-numeric: tabular-nums; }
#screen-palmares .pal-forme-bar {
  display: flex; height: 10px; margin: 9px 0; overflow: hidden;
  border-radius: var(--ds-radius-pill); background: var(--ds-track);
}
/* Un segment garde une largeur minimale : a une carriere sur cent vingt-sept,
   une part exacte ne se verrait pas du tout, et la barre mentirait par omission. */
#screen-palmares .pal-forme-bar > i { display: block; min-width: 4px; }
#screen-palmares .pal-forme-key { display: flex; flex-wrap: wrap; gap: 4px 11px; }
#screen-palmares .pal-forme-key > span {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  font-size: .68rem; color: var(--ds-text-dim); line-height: 1.3;
}
#screen-palmares .pal-forme-key s { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 2px; text-decoration: none; }
#screen-palmares .pal-forme-key b { font-weight: 800; color: var(--ds-text); font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------- LE TRI */
#screen-palmares .pal-tri { margin: 0 2px 8px; }

/* --------------------------------------------------------- BLOC 3 · LA LISTE
   UNE carte, des lignes separees par un filet — jamais une carte par carriere. */
#screen-palmares .pal-liste {
  display: block; background: var(--ds-card); border-radius: var(--ds-radius-tile);
  box-shadow: var(--ds-shadow-tile); overflow: hidden;
}
#screen-palmares .pal-liste .pal-li, .pa-hof .pal-li {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  border: 0; border-radius: 0; background: none; box-shadow: none; margin: 0;
  padding: 9px 12px; cursor: pointer; font: inherit; color: var(--ds-text);
}
#screen-palmares .pal-liste .pal-li + .pal-li, .pa-hof .pal-li + .pal-li { border-top: 1px solid var(--ds-line); }
#screen-palmares .pal-liste .pal-li:hover { background: var(--ds-field-bg); }
#screen-palmares .pal-liste .pal-li:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: -2px; }
#screen-palmares .pal-rk, .pa-hof .pal-rk {
  flex: 0 0 auto; min-width: 20px; text-align: right; font-size: .78rem; font-weight: 800;
  color: var(--ds-text-faint); font-variant-numeric: tabular-nums;
}
#screen-palmares .pal-mid, .pa-hof .pal-mid { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
#screen-palmares .pal-l1, .pa-hof .pal-l1 { display: flex; align-items: center; gap: 5px; min-width: 0; }
#screen-palmares .pal-f, .pa-hof .pal-f {
  font-size: .69rem; color: var(--ds-text-faint); line-height: 1.3;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#screen-palmares .pal-v, .pa-hof .pal-v { flex: 0 0 auto; display: flex; align-items: center; }

/* ------------------------------------------- LA LIGNE « TOUS LES CHIFFRES » */
#screen-palmares .pal-chiffres {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  margin-top: 12px; padding: 11px 13px; cursor: pointer; font: inherit;
  border: 0; border-radius: var(--ds-radius-tile);
  background: var(--ds-card); box-shadow: var(--ds-shadow-tile);
  color: var(--ds-text); font-size: .84rem; font-weight: 700; text-align: left;
}
#screen-palmares .pal-chiffres:hover { box-shadow: var(--ds-shadow); }

/* ------------------------------------------- LA SOUS-PAGE « TOUS LES CHIFFRES »
   `.pal-porte` dit SUR QUOI porte le bloc qui la suit, en toutes lettres : c'est
   la seule chose que les quatre onglets ne faisaient pas, et c'est ce qui
   permet aux deux comptes de Majors de coexister sans se corriger l'un l'autre. */
#screen-palmares .pal-sous-nav { margin-bottom: 10px; }
#screen-palmares .pal-porte {
  margin: 14px 2px 8px; font-size: .74rem; line-height: 1.45; color: var(--ds-text-dim);
}
#screen-palmares .pal-porte:first-of-type { margin-top: 0; }
#screen-palmares .pal-porte b { color: var(--ds-text); font-weight: 700; }

/* ------------------------------------------------------- PALMARES : LE PIED
   Hors des onglets, donc visible sur les trois. L'export est une action
   ordinaire ; la reinitialisation est DESTRUCTIVE — elle est reduite a une
   icone en teinte d'alerte, a l'ecart, et garde sa double confirmation. */
.pl-pied { display: flex; align-items: center; gap: 9px; margin-top: 14px; }
.pl-pied .btn { margin-top: 0; flex: 1 1 auto; }
.pl-raz {
  flex: 0 0 auto; width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--ds-radius-btn); cursor: pointer; padding: 0;
  background: var(--ds-card); border: 1px solid var(--ds-line); color: var(--ds-bad);
}
.pl-raz:hover { background: var(--c2-ko-bg); border-color: var(--c2-ko-line); }
.pl-raz:focus-visible { outline: 2px solid var(--ds-bad); outline-offset: 2px; }
#screen-palmares .export-box { margin-top: 10px; }

/* ===================== COMMENT CA MARCHE : LES SEPT CHAPITRES ==============
   Niveau 1 : l'introduction et la liste. Niveau 2 : un chapitre en pleine page.
   Ce n'est pas un accordeon — la liste disparait quand un chapitre s'ouvre, et
   la fleche de l'en-tete ramene a elle. */
.ht-intro { font-size: .84rem; line-height: 1.45; color: var(--ds-text-dim); margin: 0 2px 12px; }
.ht-chap-lien {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; cursor: pointer;
  background: var(--ds-card); border: 0; box-shadow: var(--ds-shadow-tile);
  border-radius: var(--ds-radius-tile); padding: 10px 12px; margin-bottom: 7px;
}
.ht-chap-num {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  background: var(--ds-accent-soft-bg); color: var(--ds-accent-deep);
  font-size: .72rem; font-weight: 800; display: inline-flex; align-items: center; justify-content: center;
}
.ht-chap-c { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ht-chap-t { font-size: .89rem; font-weight: 700; color: var(--ds-text); line-height: 1.2; }
.ht-chap-s { font-size: .72rem; color: var(--ds-text-faint); line-height: 1.3; }
.ht-chap-x { border-color: var(--ds-text-faint); transform: rotate(-45deg); }

/* Sous-sections d'un chapitre : le principe directeur applique a l'interieur du
   chapitre — ce qui ne tient pas se replie, rien n'est supprime. */
.ht-preambule { margin-bottom: 6px; }
.ht-sec { background: var(--ds-card); border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile); margin-bottom: 7px; }
.ht-sec-t {
  display: flex; align-items: center; gap: 9px; width: 100%; border: 0; background: none;
  padding: 10px 12px; cursor: pointer; text-align: left;
}
.ht-sec-n { flex: 1 1 auto; min-width: 0; font-size: .87rem; font-weight: 700; color: var(--ds-text); line-height: 1.25; }
.ht-sec-c { padding: 0 12px 8px; }
.ht-sec-c > :first-child { margin-top: 0; }
#screen-howto .howto-note { color: var(--ds-text-dim); font-size: .84rem; margin: 6px 0 10px; }
#screen-howto .howto-note strong { color: var(--ds-text); }
#screen-howto .section-label { color: var(--ds-text-faint); margin: 14px 0 6px; }
#screen-howto .group-title { color: var(--ds-text); font-size: .88rem; margin: 12px 0 6px; }
#screen-howto .howto-table th { color: var(--ds-text-faint); border-bottom-color: var(--ds-line); }
#screen-howto .howto-table td { border-bottom-color: var(--ds-line); color: var(--ds-text); }
#screen-howto .howto-table td:not(:first-child) { color: var(--ds-text-dim); }
#screen-howto .howto-scroll { margin: 6px 0 10px; }
#screen-howto .val-row { margin-bottom: 8px; }
#screen-howto .fisc-cat, #screen-howto .howto-def { background: var(--ds-field-bg); border: 0; border-radius: var(--ds-radius-tile); }
#screen-howto .nat-groupe-t { color: var(--ds-text-dim); }
#screen-howto .nat-groupe-t strong { color: var(--ds-text); }

/* L'ENCADRE DE LA PRIORITE DE SELECTION (volet 5). Distinct du reste de la
   page — c'est une regle qui contredit ce que le classement par prestige laisse
   croire — mais dans le meme vocabulaire : pas de couleur d'alerte, un fond
   d'accent pale et un filet, comme les autres encadres du theme. */
.ht-encadre {
  background: var(--ds-accent-soft-bg); border-radius: var(--ds-radius-tile);
  padding: 9px 12px 2px; margin: 10px 0 12px;
}
.ht-enc-t { font-size: .78rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ds-accent-deep); }
.ht-encadre .howto-note { margin: 5px 0 8px; }
.ht-encadre .howto-note strong { color: var(--ds-accent-ink); }

/* LES CELLULES DES TABLEAUX PEUVENT REVENIR A LA LIGNE, DANS CET ECRAN SEUL.
   La regle generale interdit le retour a la ligne des colonnes de valeurs
   (`.howto-table td:not(:first-child)`), ce qui convient a des nombres mais fait
   defiler le tableau de fidelite a 390 px : sa derniere colonne porte une phrase
   (« 1 invitation de moins »). Les valeurs ne sont pas raccourcies — elles se
   replient. Les nombres, eux, sont trop courts pour que cela change quoi que ce
   soit a leur affichage. */
#screen-howto .howto-table td:not(:first-child) { white-space: normal; }

/* ==========================================================================
   MODE AUTOMATIQUE — BLOC DE LANCEMENT, BARRE DE CONTROLE, MARQUAGE
   (2026-08-01)

   AUCUNE COULEUR EN DUR ici : tout vient des jetons du socle. Les deux modes se
   distinguent par une TEINTE, posee une seule fois dans `--auto-teinte` — hasard
   sur `--ds-info`, optimal sur `--ds-accent-deep`. Changer de theme change les
   deux teintes du meme coup, sans toucher a une regle de ce bloc.

   `html.auto-on` RESERVE la hauteur de la barre sous les ecrans : ils ont tous
   ete cales sans elle, et sans cette reserve le dernier bouton d'un ecran
   passerait dessous.
   ========================================================================== */
/* ⚠️ LES TROIS FAMILLES DE SELECTEURS SONT INDISPENSABLES, et l'oubli de la
   troisieme a ete attrape par le controle navigateur, pas par la relecture : les
   boutons de lancement portent `.auto-hasard` / `.auto-optimal` et n'heritaient
   donc d'AUCUNE teinte — `var(--auto-teinte)` retombait sur la couleur de texte
   heritee, et les deux boutons sortaient identiques. */
.am-hasard,  .auto-hasard,  [data-auto-mode="hasard"]  { --auto-teinte: var(--ds-info);        --auto-teinte-bg: var(--ds-field-bg); }
.am-optimal, .auto-optimal, [data-auto-mode="optimal"] { --auto-teinte: var(--ds-accent-deep); --auto-teinte-bg: var(--ds-accent-soft-bg); }

/* ---- Bloc de lancement, sous les boutons de l'ecran de creation ---- */
.auto-bloc { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--ds-line); }
.auto-note { margin: 0 0 10px; font-size: .8rem; color: var(--ds-text-dim); }
.auto-lance { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.auto-b {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 11px 12px; border-radius: var(--ds-radius-tile);
  background: var(--ds-card); border: 1px solid var(--ds-line);
  box-shadow: var(--ds-shadow-tile); color: var(--ds-text);
  font-family: inherit;
}
.auto-b:active { background: var(--ds-btn-soft-bg-h); }
.auto-b .auto-ic { display: block; font-size: 1.15rem; line-height: 1.1; }
.auto-b .auto-bt { display: block; margin-top: 3px; font-weight: 700; font-size: .95rem; color: var(--auto-teinte); }
.auto-b .auto-bs { display: block; margin-top: 2px; font-size: .7rem; line-height: 1.25; color: var(--ds-text-dim); }
/* Le lisere gauche porte la teinte du mode : c'est ce qui distingue les deux
   boutons au premier coup d'oeil, avant meme de lire leur nom. */
.auto-hasard, .auto-optimal { border-left: 3px solid var(--auto-teinte); }

/* ---- Barre de controle ---- */
.auto-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--ds-card); border-top: 1px solid var(--ds-line);
  box-shadow: 0 -2px 14px rgba(30, 45, 80, .12);
  font-family: var(--ds-font); color: var(--ds-text);
}
.auto-bar.hidden { display: none; }
.ab-in { max-width: 560px; margin: 0 auto; padding: 6px 12px calc(6px + env(safe-area-inset-bottom, 0px)); }
.ab-l1 { display: flex; align-items: center; gap: 6px; }
.ab-b {
  flex: 0 0 auto; cursor: pointer; font-family: inherit; font-size: .74rem; font-weight: 700;
  padding: 6px 9px; border-radius: var(--ds-radius-pill);
  background: var(--ds-btn-soft-bg); border: 1px solid var(--ds-btn-soft-line); color: var(--ds-btn-soft-txt);
}
.ab-b:active { background: var(--ds-btn-soft-bg-h); }
.ab-main { margin-left: auto; color: var(--ds-bad); border-color: var(--ds-bad); }
/* Segmenteur de mode : la piste est neutre, l'onglet actif se detache en carte
   blanche et prend la teinte de SON mode — c'est le meme patron que les onglets
   de l'ecran Progression. */
.ab-modes { display: flex; gap: 2px; padding: 2px; border-radius: var(--ds-radius-pill); background: var(--ds-track); }
.ab-m {
  cursor: pointer; font-family: inherit; font-size: .72rem; font-weight: 700;
  padding: 4px 9px; border-radius: var(--ds-radius-pill);
  background: transparent; border: 0; color: var(--ds-text-dim);
}
.ab-m.on { background: var(--ds-card); color: var(--auto-teinte); box-shadow: var(--ds-shadow-tile); }
/* Decision en cours */
.ab-l2 { display: flex; align-items: center; gap: 7px; margin-top: 6px; font-size: .76rem; }
/* L'age est pose SUR la ligne de la decision, a droite : la barre occupe le bas de
   l'ecran, chaque ligne economisee est une ligne rendue au jeu. */
.ab-l2 .ab-age { margin: 0 0 0 auto; flex: 0 0 auto; }
.ab-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--auto-teinte); flex: 0 0 auto; animation: ab-bat 1.4s ease-in-out infinite; }
.auto-bar.en-pause .ab-dot { animation: none; opacity: .45; }
.ab-dec { color: var(--ds-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes ab-bat { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
/* Avancement de la carriere (age courant sur plafond du poste) */
.ab-prog { height: 4px; margin-top: 5px; border-radius: var(--ds-radius-pill); background: var(--ds-track); overflow: hidden; }
.ab-prog-f { height: 100%; background: var(--auto-teinte); border-radius: inherit; transition: width .25s ease; }
.ab-age { margin-top: 3px; font-size: .66rem; color: var(--ds-text-faint); }
/* Journal des choix — jamais sauvegarde, il meurt avec la page. */
/* 3 lignes a ~16,6 px : 52 px. Mesure faite, 46 px rognait la troisieme — defaut
   vu sur une CAPTURE, pas dans un test. */
.ab-journal { list-style: none; margin: 4px 0 0; padding: 0; max-height: 52px; overflow: hidden; }
.aj-l { display: flex; align-items: baseline; gap: 6px; font-size: .69rem; line-height: 1.5; }
.aj-tag {
  flex: 0 0 auto; font-weight: 700; font-size: .6rem; letter-spacing: .02em;
  padding: 1px 6px; border-radius: var(--ds-radius-pill);
  background: var(--auto-teinte-bg); color: var(--auto-teinte);
}
.aj-t { color: var(--ds-text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aj-vide { margin: 7px 0 0; font-size: .69rem; color: var(--ds-text-faint); }

/* ---- L'option retenue, allumee AVANT que son resultat s'affiche ---- */
.auto-pick {
  position: relative;
  outline: 2px solid var(--auto-teinte) !important;
  outline-offset: 1px;
  background-color: var(--auto-teinte-bg) !important;
  border-radius: var(--ds-radius-btn);
  animation: auto-pulse .7s ease-out;
}
@keyframes auto-pulse { from { outline-offset: 6px; } to { outline-offset: 1px; } }

/* ---- Reserve de hauteur : la barre occupe le bas de l'ecran ---- */
/* `--auto-h` est pose par js/main.js sur la hauteur REELLEMENT mesuree de la
   barre, plus 8 px de respiration. La valeur de repli ne sert qu'au premier rendu. */
html.auto-on #app { padding-bottom: var(--auto-h, 136px); }

@media (prefers-reduced-motion: reduce) {
  .ab-dot, .auto-pick { animation: none; }
}

/* ============================ STICKERS DE MAJOR (album, 4e onglet du Palmares) ============================
   LA TROISIEME FORME. L'ecu est aux badges, le disque aux quetes, la VIGNETTE aux
   stickers : un carre a coins arrondis, a finition brillante. Aucune couleur de
   metal n'est ecrite ici — elles sont posees EN LIGNE depuis `DSE_METAUX`
   (js/ui.js, `metalVignette`), source unique du projet. Tout le reste est en
   jetons de role `--ds-*`, donc suit les douze themes.
   ========================================================================== */
.st-tete { display: flex; gap: 8px; margin: 2px 0 12px; }
.st-c {
  flex: 1 1 0; min-width: 0; text-align: center;
  padding: 9px 6px 10px; border-radius: var(--ds-radius-card);
  background: var(--ds-card); border: 1px solid var(--ds-line);
}
.st-c-v { display: block; font-size: 1.12rem; font-weight: 800; color: var(--ds-text);
  line-height: 1.1; font-variant-numeric: tabular-nums; }
.st-c-n { display: block; margin-top: 3px; font-size: .64rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ds-text-faint); line-height: 1.25; }
/* La carriere que l'album montre : une seule ligne, jamais un titre de section. */
.st-qui { margin: 0 2px 10px; font-size: .74rem; color: var(--ds-text-dim); line-height: 1.35; }
.st-qui b { color: var(--ds-text); font-weight: 700; }

/* ---- La grille de l'album ----
   3 colonnes a 390 px, 4 des que la largeur le permet. `auto-fill` garde des
   colonnes de largeur egale meme sur une derniere rangee incomplete. */
.st-grille { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (min-width: 420px) { .st-grille { grid-template-columns: repeat(4, 1fr); } }
.st-case { display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit; color: inherit; }
.st-case[disabled] { cursor: default; }
.st-leg { font-size: .62rem; font-weight: 700; color: var(--ds-text-faint);
  line-height: 1.2; text-align: center; font-variant-numeric: tabular-nums; }
.st-case.on .st-leg { color: var(--ds-accent-deep); }

/* ---- LA VIGNETTE ---- */
/* ⚠️ LE RAYON EST EN POURCENTAGE, ET C'EST NECESSAIRE. Le cadre metallique est
   dessine dans le repere 0 0 200 200 (rx 15), donc son arrondi SUIT la taille de
   la vignette. Un rayon en pixels ici couperait les coins du cadre sur les
   grandes vignettes et les arrondirait trop sur les petites : 15/200 = 7,5 %
   est le meme arrondi, a toutes les tailles. */
.stv {
  position: relative; display: block; overflow: hidden;
  border-radius: 7.5%;
  box-shadow: var(--ds-shadow-tile);
}
.st-case.on .stv { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
/* LE DESSIN LUI-MEME. La vignette est un SVG depuis le 2026-08-09 : c'est ce qui
   permet au motif de la ville d'exister (des chemins, une decoupe et trois
   degrades ne peuvent pas vivre dans un fond CSS). Cette feuille de style ne
   connait donc AUCUNE couleur de sticker — ni de finition, ni de ville : toutes
   sont posees en ligne, depuis `DSS_FINITIONS` (js/ui.js) pour le metal et
   depuis js/villes.js pour le verre. */
.stv-svg { display: block; width: 100%; height: 100%; }
/* LA SIGNATURE. Police manuscrite EMBARQUEE (« DS Signature » = Dancing Script,
   SIL OFL 1.1, declaree dans index.html, fichier dans fonts/), suivie de la pile
   cursive du systeme puis de l'italique penche : trois niveaux de repli, la
   signature se degrade mais ne redevient jamais une etiquette sans caractere.
   La famille est portee par le GROUPE, pour que les trois passes du relief
   (ombre, corps, rehaut) partagent forcement la meme police : trois declarations
   separees finiraient par diverger.
   ⚠️ NI TRONCATURE NI ELLIPSE ICI, et c'est voulu : la taille est calculee par
   `UI.sigTaille` d'apres la LONGUEUR du pseudo, et `textLength` resserre le trace
   si les glyphes sont plus larges que la moyenne. Une ellipse masquerait le
   debordement au lieu de l'empecher. */
.stv-sigg {
  font-family: "DS Signature", "Segoe Script", "Bradley Hand", "Snell Roundhand", "URW Chancery L", cursive;
  font-style: italic; font-weight: 600;
}
/* Le CORPS de la signature — la passe qui porte le nom lisible. `paint-order`
   fait passer le contour sombre SOUS le remplissage metallique : sans lui, le
   cerne mange le trace au lieu de le detacher. */
.stv-sig { paint-order: stroke; }
/* LA PASTILLE D'APERCU d'une ligne de legende : un carre a coins arrondis
   minuscule, sans texte. Meme forme que la vignette, reduite — jamais un disque,
   qui appartient aux quetes. Couleur posee en ligne depuis js/ui.js. */
.st-past { display: inline-block; border-radius: 3px; border: 1px solid transparent;
  flex: 0 0 auto; }
/* Emplacement VIDE (« a venir ») et emplacement INCONNU (« parcours non
   conserve ») : ni l'un ni l'autre n'emprunte une finition, justement pour qu'on
   ne les prenne pas pour un sticker papier. */
/* ⚠️ LA LARGEUR DU FILET EST ICI, PLUS SUR `.stv`. La vignette pleine n'a plus
   de bordure CSS du tout — son cadre est dessine dans le SVG. Les deux
   emplacements creux, eux, n'ont pas de dessin : sans cette largeur, leur
   `border-style` retomberait sur la valeur par defaut (`medium`, 3 px) et le
   pointille doublerait d'epaisseur. */
.stv-off { border-width: 1.5px; border-style: dashed; border-color: var(--ds-line-hover);
  background: var(--ds-track); box-shadow: none;
  display: flex; align-items: center; justify-content: center; }
.stv-inc { border-style: solid; background: var(--ds-btn-soft-bg); }
.stv-mot { font-size: 1.2rem; font-weight: 800; color: var(--ds-text-faint); }

/* ---- La fiche depliee d'un sticker ---- */
.st-fiche {
  margin: 12px 0 2px; padding: 12px 13px 13px;
  border-radius: var(--ds-radius-card); background: var(--ds-card);
  border: 1px solid var(--ds-line); border-top: 3px solid var(--ds-accent);
}
.st-f-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
.st-f-n { font-size: .95rem; font-weight: 800; color: var(--ds-text); line-height: 1.2; }
.st-f-a { margin-left: auto; font-size: .78rem; font-weight: 700; color: var(--ds-text-dim);
  font-variant-numeric: tabular-nums; }
.st-f-p { display: flex; align-items: center; gap: 7px; margin: 7px 0 8px; }
.st-f-m { font-size: .66rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  padding: 3px 8px; border-radius: var(--ds-radius-pill); }
.st-f-pc { font-size: .8rem; font-weight: 600; color: var(--ds-text); }
.st-f-t { margin: 0 0 8px; font-size: .8rem; line-height: 1.4; color: var(--ds-text-dim); }
.st-f-l { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0;
  border-top: 1px solid var(--ds-line); font-size: .78rem; }
.st-f-l dt { color: var(--ds-text-faint); }
.st-f-l dd { margin: 0; color: var(--ds-text); font-weight: 600; text-align: right; }
.st-f-fait { margin: 8px 0 0; padding: 7px 9px; border-radius: var(--ds-radius-btn);
  background: var(--ds-accent-wash-2); font-size: .78rem; line-height: 1.35; color: var(--ds-accent-ink-fort); }
/* Note de bas d'album : ce que l'archive ne conserve pas. Jamais une alerte —
   c'est une precision, pas une erreur. */
.st-note { margin: 12px 2px 0; font-size: .72rem; line-height: 1.4; color: var(--ds-text-faint); }

/* ============================ LA FICHE DE LEGENDE (Hall of Fame, 2 niveaux) ============================
   LA REGLE DE CET ECRAN, et elle explique toutes les valeurs qui suivent :
       LE FOND PORTE LES COLLECTIONS, LE BLANC PORTE CE SUR QUOI ON VIENT DE TAPER.
   L'album de Majors et le mur de medailles sont donc poses DIRECTEMENT sur le
   fond de page — aucune carte, aucun cadre autour d'eux. La seule carte claire
   de la partie basse est l'encadre de detail (`.st-fiche`, deja defini plus
   haut et REUTILISE ici : un seul encadre dans tout le projet).

   ⚠️ AUCUNE COULEUR DE METAL NI DE FINITION N'EST ECRITE ICI. Les ecus tirent
   leurs teintes de `DSE_METAUX` et les vignettes de `DSS_FINITIONS`, toutes deux
   dans js/ui.js et posees en ligne. Cette feuille ne connait que des jetons.
   ========================================================================== */
.lf-nav { margin: 0 0 10px; }
.lf-back {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--ds-btn-soft-bg); border: 1px solid var(--ds-btn-soft-line);
  border-radius: var(--ds-radius-pill); padding: 6px 12px 6px 9px;
  font: inherit; font-size: .78rem; font-weight: 700; color: var(--ds-btn-soft-txt);
  cursor: pointer;
}
.lf-back:hover { background: var(--ds-btn-soft-bg-h); }

/* ---- EN-TETE : une CARTE CLAIRE, jamais un bandeau sombre ---- */
.lf-head {
  background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow); padding: 13px 14px 14px; margin: 0 0 16px;
}
.lf-id { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lf-nom { font-size: 1.32rem; font-weight: 800; line-height: 1.15; }
/* ⚠️ `.lf-fl` A ETE RETIREE ICI : c'etait l'enveloppe du drapeau que la fiche
   dessinait elle-meme, en DOUBLON de `natLabel`. Le drapeau porte deja sa
   propre regle `.flagico` (taille et marge), la meme que dans la LISTE des
   legendes — un seul dessin, une seule regle. Ne pas la remettre. */
.lf-meta { margin: 5px 0 0; font-size: .78rem; color: var(--ds-text-dim); line-height: 1.35; }
.lf-pal { margin: 2px 0 0; font-size: .74rem; color: var(--ds-text-dim); line-height: 1.35; }
/* SIX COMPTEURS, DEUX RANGEES DE TROIS. C'est la seule disposition qui tienne a
   390 px sans reduire les nombres au point de les rendre illisibles. */
.lf-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; margin-top: 12px; }
.lf-p {
  display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0;
  padding: 8px 4px 7px; border-radius: var(--ds-radius-btn);
  background: var(--ds-field-bg); border: 1px solid var(--ds-line);
}
.lf-pv { font-size: 1.02rem; font-weight: 800; color: var(--ds-text); line-height: 1.1;
  font-variant-numeric: tabular-nums; }
.lf-pn { font-size: .58rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ds-text-faint); line-height: 1.2; text-align: center; }

/* ---- Titres de section. Ils sont POSES SUR LE FOND, sans cadre : ils annoncent
   une collection, ils ne l'encadrent pas. ---- */
.lf-sec { display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 2px 8px; font-size: .66rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.lf-sec b { font-size: .8rem; letter-spacing: 0; color: var(--ds-text-dim);
  font-variant-numeric: tabular-nums; }
.lf-vide { margin: 0 2px 16px; font-size: .78rem; color: var(--ds-text-faint); line-height: 1.4; }
.lf-abs { margin: 0 2px 16px; padding: 11px 12px; border-radius: var(--ds-radius-card);
  background: var(--ds-accent-wash-1); border: 1px solid var(--ds-line);
  font-size: .78rem; line-height: 1.45; color: var(--ds-text-dim); }
/* L'album reutilise `.st-grille` : une seule definition de grille de vignettes
   dans tout le projet, donc aucune divergence possible entre les deux ecrans. */
#ppan-legendes .st-grille { margin-bottom: 18px; }

/* ---- LE MUR DE MEDAILLES : des ECUS, poses eux aussi sur le fond ----
   ⚠️ AUCUNE VIGNETTE ICI, ET AUCUN ECU DANS L'ALBUM. Trois collections, trois
   formes : les melanger dans une meme grille rendrait les deux illisibles. */
.lf-grp { display: flex; align-items: baseline; gap: 7px; margin: 0 2px 6px; }
.lf-grp-n { font-size: .64rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.lf-grp-c { font-size: .72rem; font-weight: 700; color: var(--ds-text-dim);
  font-variant-numeric: tabular-nums; }
.lf-ecus { display: flex; flex-wrap: wrap; gap: 9px; margin: 0 0 10px; }
.lf-ecu { background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  line-height: 0; border-radius: 8px; }
.lf-ecu.on { outline: 2px solid var(--ds-accent); outline-offset: 3px; }
/* Le filet entre deux groupes de metal : TRANSLUCIDE, il separe sans decouper. */
.lf-fil { border: 0; height: 1px; margin: 4px 2px 12px;
  background: var(--ds-line); opacity: .55; }
.lf-astuce { margin: 14px 2px 0; font-size: .74rem; color: var(--ds-text-faint);
  line-height: 1.4; text-align: center; }
.lf-bas { margin-top: 18px; }
.lf-bas .copybox { margin-top: 10px; }

/* ---- L'APERCU D'ALBUM SUR UNE LIGNE DE LA LISTE ----
   Une pastille par Major dispute : la signature visuelle de la carriere, lisible
   sans ouvrir sa fiche. La rangee entiere est cliquable, comme l'en-tete. */
.leg-ap-row { display: flex; align-items: center; padding: 0 12px 9px 44px; cursor: pointer; }
.leg-ap { display: flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.leg-ap-abs { font-size: .72rem; color: var(--ds-text-faint); letter-spacing: .1em; }
.leg-ap-p { font-size: .6rem; font-weight: 700; color: var(--ds-text-faint);
  margin-left: 2px; font-variant-numeric: tabular-nums; }
/* La chevron de fin de ligne : la ligne MENE quelque part, elle ne deplie plus. */
.leg-fl { width: 7px; height: 7px; margin-left: 8px; flex: 0 0 auto;
  border-right: 2px solid var(--ds-text-faint); border-top: 2px solid var(--ds-text-faint);
  transform: rotate(45deg); }

/* ============================ MON ARME (4e onglet de Progression) ============================
   ⚠️ CE BLOC PASSE PAR LES JETONS DU SOCLE `--ds-*`, A DEUX EXCEPTIONS PRES, et
   les deux sont des valeurs de MATIERE, pas de decor :
     1. LA VITRINE (`.ar-vit`) est un fond de NUIT en dur. Les armes sont
        dessinees claires ; posees sur un aplat clair elles disparaissent. La
        vitrine montre l'arme comme le kill feed la montre : claire sur sombre.
     2. les cinq FINITIONS de sticker, qui viennent de `DSS_FINITIONS`
        (js/ui.js) et sont posees en ligne dans le SVG — un theme ne doit pas
        pouvoir les repeindre, sinon un sticker de poules ressemblerait a un
        sticker de titre.
   Tout le RESTE de l'ecran (selecteurs, apercu du feed, notes) suit les themes.
   ========================================================================== */
/* LA VITRINE. ⚠️ FOND SOMBRE, ET IL NE SUIT PAS LES THEMES — c'est le seul
   endroit de l'ecran dans ce cas, et c'est deliberе : les armes sont dessinees
   CLAIRES (acier, reflets), une arme claire posee sur un aplat clair ne se voit
   pas. La vitrine doit montrer l'arme telle qu'elle apparait dans le kill feed,
   sur du sombre. Degrade de nuit + halo radial derriere l'arme, pour la detacher
   sans l'eclairer. Les quatre valeurs ci-dessous sont des valeurs de MATIERE, du
   meme ordre que les metaux et les finitions : rien a repeindre pour un theme. */
.ar-vit {
  background:
    radial-gradient(78% 62% at 50% 40%, rgba(146, 174, 232, .26), rgba(0, 0, 0, 0) 72%),
    linear-gradient(165deg, #2A3350, #131828);
  border-radius: var(--ds-radius-card); box-shadow: var(--ds-shadow);
  padding: 16px 12px 12px; margin: 0 0 16px; text-align: center;
}
.ar-vit-g { display: flex; align-items: center; justify-content: center; min-height: 118px; }
.ar-vit-g svg { max-width: 100%; height: auto; display: block; }
.ar-vit-n { margin: 8px 0 0; font-size: .74rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: #E8EDF7; opacity: .9; }

/* LE SELECTEUR D'ARMES : cinq colonnes egales, une silhouette et un nom court. */
.ar-sel { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin: 0 0 16px; }
.ar-a {
  display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0;
  padding: 7px 2px 6px; border-radius: var(--ds-radius-btn); cursor: pointer; font: inherit;
  background: var(--ds-field-bg); border: 1px solid var(--ds-line); color: var(--ds-text-dim);
}
.ar-a.on { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent);
  color: var(--ds-accent-ink-fort); }
.ar-a-i { display: block; line-height: 0; }
.ar-a-i svg { display: block; width: 100%; height: auto; }
.ar-a-n { font-size: .56rem; font-weight: 700; letter-spacing: .02em; line-height: 1.1;
  text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 100%; }

/* LA RANGEE DES MODELES DE COUTEAU — trois par ligne, six modeles, deux rangees.
   Elle n'apparait que pour le couteau : les quatre autres armes n'ont qu'un
   dessin, et leur ecran ne change pas d'un pixel.
   ⚠️ LA VIGNETTE REUTILISE `.ar-vit`, elle n'en recopie pas les valeurs. Le fond
   de nuit est l'exception DECLAREE de cet ecran (les armes sont dessinees
   claires, un aplat clair les efface) ; en ouvrir une seconde serait refuse par
   les quatre controles « aucun hexadecimal hors des jetons ». `.ar-mo-v` ne
   change donc que la GEOMETRIE — pas une couleur. */
.ar-mo { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin: 0 0 10px; }
.ar-mo-t {
  display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0;
  padding: 6px 5px 7px; border-radius: var(--ds-radius-btn); cursor: pointer; font: inherit;
  background: var(--ds-field-bg); border: 1px solid var(--ds-line); color: var(--ds-text-dim);
}
.ar-mo-t.on { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent);
  color: var(--ds-accent-ink-fort); }
.ar-mo-t.sel { outline: 2px solid var(--ds-line-hover); outline-offset: 1px; }
.ar-mo-t.on.sel { outline-color: var(--ds-accent); }
/* Un modele non obtenu reste VISIBLE mais eteint : voir ce qu'on peut gagner
   fait partie de la recompense — c'est deja le choix fait pour les skins. */
.ar-mo-t.lock { cursor: default; }
.ar-mo-t.lock .ar-mo-v { opacity: .34; filter: grayscale(1); }
.ar-mo-v { display: block; width: 100%; min-height: 0; line-height: 0;
  padding: 5px 3px; margin: 0; border-radius: var(--ds-radius-btn); box-shadow: none; }
.ar-mo-v svg { display: block; width: 100%; height: auto; }
.ar-mo-n { display: flex; align-items: center; justify-content: center; gap: 4px;
  font-size: .58rem; font-weight: 700; letter-spacing: .02em; line-height: 1.1;
  text-align: center; max-width: 100%; }
.ar-mo-l { display: flex; color: var(--ds-text-faint); }
/* LA CARTE : le modele designe, son etiquette, sa condition. */
.ar-mo-c { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px;
  margin: 0 2px 16px; padding: 9px 11px; border-radius: var(--ds-radius-card);
  background: var(--ds-accent-wash-1); border: 1px solid var(--ds-line); }
.ar-mo-cn { font-size: .82rem; font-weight: 700; color: var(--ds-text); }
.ar-mo-cb { font-size: .6rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px; background: var(--ds-track); color: var(--ds-text-faint); }
.ar-mo-cb.bon { background: var(--ds-good-soft-bg); color: var(--ds-good-ink); }
.ar-mo-cd { flex: 1 1 100%; font-size: .74rem; line-height: 1.4; color: var(--ds-text-dim); }

/* LE SELECTEUR DE STICKER. Que des VIGNETTES — jamais un ecu a cote : trois
   collections, trois formes, et elles ne partagent aucune grille. */
.ar-st { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; }
.ar-s { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; line-height: 0;
  border-radius: 12px; }
.ar-s.on { outline: 2px solid var(--ds-accent); outline-offset: 3px; }
/* Le couteau : les vignettes restent VISIBLES mais eteintes et inertes — on voit
   ce qu'on ne peut pas coller, ce qui explique mieux qu'une grille vide. */
.ar-st-off { opacity: .38; filter: grayscale(1); pointer-events: none; }
.ar-s-nul { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; width: 54px; height: 54px; border-radius: 12px;
  background: var(--ds-track); border: 1.5px dashed var(--ds-line-hover); }
.ar-s-x { width: 15px; height: 15px; position: relative; }
.ar-s-x::before, .ar-s-x::after { content: ""; position: absolute; left: 0; top: 6px;
  width: 15px; height: 2px; background: var(--ds-text-faint); }
.ar-s-x::before { transform: rotate(45deg); }
.ar-s-x::after { transform: rotate(-45deg); }
.ar-s-l { font-size: .58rem; font-weight: 700; color: var(--ds-text-faint); line-height: 1; }
.ar-non { margin: 0 2px 16px; padding: 11px 12px; border-radius: var(--ds-radius-card);
  background: var(--ds-accent-wash-1); border: 1px solid var(--ds-line);
  font-size: .78rem; line-height: 1.45; color: var(--ds-text-dim); }
.ar-non b { color: var(--ds-text); }

/* LA RANGEE DES EMPLACEMENTS DE STICKER                        (2026-08-13)
   ⚠️ UN EMPLACEMENT SE DESIGNE, IL NE SE COLLE PAS : ces boutons disent OU la
   grille du dessous va poser. Ils reprennent donc le marquage des cinq vignettes
   d'arme (`.ar-a`) — meme carte, meme lisere d'accent quand elle est choisie —
   et surtout pas celui d'une tuile de sticker, qui, elle, designe un OBJET.
   ⚠️ AUCUNE LARGEUR FIXE, ET AUCUN COMPTE DE COLONNES : le nombre d'emplacements
   vient de `data/emplacements.json` et vaut 2 ou 3 selon l'arme. Une grille a
   trois colonnes aurait laissé un trou sur le pistolet. */
.ar-emp { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.ar-e { display: flex; flex-direction: column; align-items: center; gap: 4px;
  cursor: pointer; font: inherit; padding: 6px 7px 5px; border-radius: 12px;
  background: var(--ds-card); border: 1.5px solid var(--ds-line);
  box-shadow: var(--ds-shadow-tile); }
.ar-e.on { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent); }
.ar-e-v { display: block; line-height: 0; }
/* La case libre : le meme pointille que « Aucun » et que « Nouvelle carriere » —
   dans le jeu, un pointille veut dire « rien encore, et c'est a toi de poser ». */
.ar-e-vide { display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 10px;
  background: var(--ds-track); border: 1.5px dashed var(--ds-line-hover);
  font-size: 1.05rem; font-weight: 800; line-height: 1; color: var(--ds-text-faint); }
.ar-e-n { font-size: .56rem; font-weight: 800; letter-spacing: .04em;
  line-height: 1; color: var(--ds-text-faint); }
.ar-e.on .ar-e-n { color: var(--ds-accent-ink); }

/* ------------------------------------------- LA GRILLE DES SKINS D'ARMES
   ⚠️ TROIS COLONNES, ET C'EST LA RAISON D'ETRE DE CETTE REGLE. Les themes
   tiennent a deux colonnes parce qu'ils sont douze ; les revetements sont
   CINQUANTE-DEUX, et deux colonnes feraient vingt-six rangees. La tuile, son
   lisere d'etat, son prix et son bouton restent EXACTEMENT ceux des themes et
   des avantages (`.pg-t`, `.pg-t-eq/-eu/-ac/-lock`, `.pg-t-c.cher`) : rien n'est
   redefini ici, seule la largeur de colonne change.
   ⚠️ AUCUNE COULEUR DE SKIN N'EST ECRITE DANS CETTE FEUILLE. Les trois arrets
   de l'acier, le polymere et la veine sont poses en style EN LIGNE par
   js/main.js, depuis les valeurs derivees du catalogue. Ces regles ne fixent que
   des FORMES — c'est la meme discipline que l'apercu des themes. */
.pg-grille-3 { grid-template-columns: repeat(3, 1fr); gap: 7px; }
/* Une tuile depliee prend la largeur entiere : a 110 px, une phrase et un bouton
   ne sont pas lisibles. (Meme regle que `.pg-t.open`, redite pour la grille a
   trois colonnes.) */
.pg-grille-3 .pg-t.open { grid-column: 1 / -1; }
.pg-grille-3 .pg-t { padding: 7px 8px 8px; gap: 4px; }
.pg-grille-3 .pg-t-n { font-size: .74rem; }
.pg-grille-3 .pg-t-c { font-size: .74rem; }
.pg-grille-3 .pg-t-s { font-size: .56rem; padding: 2px 5px; }
/* L'APERCU D'UN SKIN : la carcasse en degrade, une bande de polymere en bas, et
   la veine lumineuse en travers quand le skin en a une. Plus court que l'apercu
   d'un theme — il y en a 52 a l'ecran. */
.sk-ap { height: 34px; }
.sk-ap-p { position: absolute; left: 6px; right: 6px; bottom: 5px; height: 7px;
  border-radius: 4px; box-shadow: 0 1px 2px rgba(0,0,0,.25); }
.sk-ap-v { position: absolute; left: 5px; right: 5px; top: 13px; height: 2px;
  border-radius: var(--ds-radius-pill); opacity: .95; }

/* LA RANGEE DE FILTRES PAR FAMILLE. Sans elle, une collection de 52 est
   inutilisable : c'est la porte d'entree de la grille.
   ⚠️ ELLE PASSE A LA LIGNE, ELLE NE DEFILE PAS. Un defilement horizontal
   coupait « Neons », « Motifs » et « Prestige » hors de l'ecran a 390 px, sans
   le moindre indice qu'il y avait quelque chose de plus : un filtre dont on ne
   voit pas les options rate exactement ce pour quoi il existe. Deux lignes
   coutent 30 px sur un onglet qui en fait plus de trois mille. */
.sk-fil { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; padding: 1px 2px 2px; }
.sk-f { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 5px;
  padding: 5px 10px; border-radius: var(--ds-radius-pill); cursor: pointer;
  background: var(--ds-field-bg); border: 1px solid var(--ds-line);
  color: var(--ds-text-dim); }
.sk-f.on { background: var(--ds-accent-soft-bg); border-color: var(--ds-accent);
  color: var(--ds-accent-ink-fort); }
.sk-f-n { font-size: .72rem; font-weight: 700; letter-spacing: .01em; }
.sk-f-c { font-size: .62rem; font-weight: 700; color: var(--ds-text-faint);
  font-variant-numeric: tabular-nums; }
.sk-f.on .sk-f-c { color: var(--ds-accent-ink-fort); }
.sk-sec { margin-top: 10px; }

/* L'APERCU DU KILL FEED, A TAILLE REELLE.
   ⚠️ EXACTEMENT la meme grille que `.kf-line` du vrai feed : 58 px de pseudo,
   92 px d'arme, 58 px de pseudo, ecart de 11 px de part et d'autre. Les deux
   colonnes de pseudo ont donc la meme largeur, le trio est groupe au centre, et
   sur un multi-frag les armes s'alignent a la verticale. */
.ar-kf { display: flex; flex-direction: column; gap: 5px; margin: 0 0 14px;
  padding: 10px 8px; border-radius: var(--ds-radius-card);
  background: var(--ds-track); border: 1px solid var(--ds-line); }
.ar-kf-l { display: grid; grid-template-columns: 58px 92px 58px; column-gap: 11px;
  justify-content: center; align-items: center; font-size: .78rem; }
.ar-kf-k { text-align: right; font-weight: 700; color: var(--ds-accent-ink-fort);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ar-kf-w { display: inline-flex; align-items: center; justify-content: center; color: var(--ds-text-dim); }
.ar-kf-w svg { display: block; width: 92px; height: auto; }
.ar-kf-v { text-align: left; color: var(--ds-text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ar-note { margin: 0 2px; font-size: .72rem; line-height: 1.4; color: var(--ds-text-faint); }

/* ============================================================================
   PASSE DE SAISON                                              (2026-08-02)

   ⚠️ TOUT PASSE PAR LES JETONS DE ROLE `--ds-*` DU SOCLE, donc tout suit les
   douze themes sans une ligne de cas particulier. Le defaut inverse a deja ete
   corrige deux fois dans ce fichier : il n'est pas recree ici.

   UNE SEULE EXCEPTION, ET C'EST LA MEME QUE CELLE DE LA VITRINE « Mon arme » :
   `.pa-ap-nuit`, le fond des apercus qui portent une ARME ou un KILL FEED. Les
   armes sont dessinees CLAIRES ; un aplat clair les ferait disparaitre. Elle est
   BORNEE (une seule regle, deux valeurs) et DECLAREE dans `VITRINE_REGLES` de
   suite.js, comme la vitrine, pour que les controles « zero hexadecimal » la
   retirent nommement au lieu de l'ignorer par hasard.
   ============================================================================ */

/* ---- Bouton d'accueil. MEME FORME que les autres cases du menu : la hauteur,
   le rayon et la taille de texte viennent de `.btn.big`, rien n'est redeclare.
   DEUX differences, pas une de plus : un or plus PROFOND (`--ds-accent-deep`,
   la nuance sombre de l'accent, contre `--ds-btn-1` pour les deux boutons
   au-dessus) et un reflet clair qui balaie la case en diagonale. */
.btn-passe {
  background: linear-gradient(180deg, var(--ds-accent-deep), var(--ds-accent-solid-2));
  color: var(--ds-btn-txt); border-color: transparent;
  position: relative; overflow: hidden;
}
.btn-passe > * { position: relative; z-index: 1; }
/* LE BALAYAGE DIAGONAL DES CASES DOREES, toutes les 4,5 s. `pointer-events:
   none` : le reflet ne doit jamais intercepter le clic.
   ⚠️ CE COMMENTAIRE ANNONCAIT « le SEUL element anime de l'accueil ». C'est faux
   depuis le 2026-08-06 : la case « Carriere Coach » reprend `.btn-passe` a l'identique
   — memes classes, meme degrade, comme sa consigne l'exigeait — donc le meme
   reflet. Deux cases animees sur l'accueil, et rien d'autre. */
.btn-passe::after {
  content: ""; position: absolute; top: -60%; bottom: -60%; left: -40%; width: 32%;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .38) 50%, rgba(255, 255, 255, 0) 100%);
  transform: rotate(18deg); pointer-events: none;
  animation: pa-sheen 4.5s ease-in-out infinite;
}
@keyframes pa-sheen {
  0%, 72% { left: -40%; }
  100% { left: 108%; }
}
@media (prefers-reduced-motion: reduce) {
  .btn-passe::after { animation: none; opacity: 0; }
}

/* ---- LA BANNIERE DE L'ECRAN — ELLE PREND LES COULEURS DU THEME DE SA SAISON,
   POUSSEES AU SOMBRE.                                            (2026-08-18)
   ⚠️ AUCUNE COULEUR N'EST ECRITE ICI, ET C'EST LA REGLE DE TOUT L'ECRAN : la
   GEOMETRIE est dans cette feuille, les VALEURS viennent des jetons du theme de
   la saison (`data/saisons.json` -> `theme.jetons`) et sont posees EN LIGNE par
   `passeTeinte` — meme partage que la table `UI.PVM` des miniatures et que les
   quatre metaux.
   ⚠️ LES ENCRES DE LA BANNIERE SONT DES `currentColor`, PAS DES JETONS DU THEME
   EQUIPE, et ce n'est pas un raccourci : `screen-passe` est un ECRAN CLAIR
   (`UI.ECRANS_CLAIRS`), donc `--ds-text-faint` y est une encre SOMBRE. Posee sur
   une banniere sombre elle serait illisible. Le seul reglage est une OPACITE,
   qui ne peut pas se tromper de theme.
   ⚠️ LA SURFACE CI-DESSOUS EST UN REPLI, PAS LE RENDU NORMAL : elle ne se voit
   que si la saison n'a pas de theme lisible. L'ecran ne disparait pas pour
   autant — mais il ne porte alors aucune couleur de saison, et c'est voulu. */
.pa-head {
  position: relative; overflow: hidden;
  background: var(--ds-card); color: var(--ds-text);
  border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-tile); padding: 13px 15px 14px; margin: 0 0 12px;
}
.pa-h1 { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pa-num { font-size: .74rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: inherit; opacity: .68; }
.pa-nom { font-size: 1.16rem; font-weight: 800; color: inherit; }
/* ⚠️ `.pa-h2`, `.pa-date` ET `.pa-etat` ONT ETE RETIRES LE 2026-08-17 (soir), en
   meme temps que le rendu qui les portait. Une saison ne se ferme jamais :
   annoncer « En cours - sans fin annoncee » a chaque ouverture etait du bruit, et
   la date de debut ne dit rien au joueur. ⚠️ ON NE LES GARDE PAS « au cas ou » :
   du style que plus rien ne rend se relit six mois plus tard comme une
   possibilite du jeu, et g80 §4d exige leur absence. Rollback : la sauvegarde
   du jour dans /root/backups/, ou l historique git. */
.pa-h3 { display: flex; align-items: center; justify-content: space-between; margin-top: 11px; }
/* ⚠️ LA PASTILLE A PERDU SON APLAT (2026-08-18) : il venait de
   `--ds-accent-soft-bg` / `--ds-accent-ink-fort`, deux jetons du theme EQUIPE,
   donc clairs sur cet ecran clair — illisibles sur la banniere sombre. Elle est
   desormais un contour dans l'encre de la banniere : meme plancher de contraste
   que le reste du texte, et rien de plus a mesurer. */
.pa-pal {
  font-size: .8rem; font-weight: 800; padding: 4px 11px; border-radius: 999px;
  background: transparent; color: inherit; border: 1px solid; opacity: .92;
}
.pa-pts { font-size: .84rem; font-weight: 800; color: inherit; }
/* ---- LA BARRE A DIX CRANS — UN PAR PALIER.                     (2026-08-18)
   ⚠️ ELLE A REMPLACE UN POURCENTAGE (`.pa-bar`, retiree avec son rendu). Un
   pourcentage vers le palier suivant ne disait pas OU l'on en est : il repartait
   de zero a chaque palier franchi. Dix crans le disent d'un coup d'oeil.
   ⚠️ LE NOMBRE DE CRANS N'EST PAS ECRIT ICI NON PLUS : `grid-auto-flow` les
   repartit, quel qu'en soit le nombre. Le rendu en pose autant que la saison
   declare de paliers.
   ⚠️ ON NE GARDE PAS `.pa-bar` « au cas ou » : du style que plus rien ne rend se
   relit six mois plus tard comme une possibilite du jeu. Rollback : la
   sauvegarde du jour dans /root/backups/, ou l'historique git. */
.pa-crans { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 3px; margin-top: 9px; }
.pa-crans > i { display: block; height: 7px; border-radius: 999px; background: currentColor; }
.pa-crans > i.on { opacity: 1; }
.pa-crans > i.next { opacity: .46; }
.pa-crans > i.off { opacity: .17; }
/* ---- LA BANDE DE L'EVENEMENT, SOUS LA BARRE A CRANS.          (2026-08-21)
   ⚠️ AUCUNE COULEUR ICI, ET C'EST LA REGLE DU BLOC : le creme, l'or du lisere et
   l'encre sont poses EN LIGNE depuis `UI.PVM.bonus` — la meme paire que le
   bandeau du surnom. Quatre controles exigent qu'aucun hexadecimal n'entre dans
   ce bloc, et la banniere prend les couleurs du theme de SA saison : une bande
   qui suivrait le theme y deviendrait sombre sur sombre.
   ⚠️ ELLE N'EXISTE PAS HORS FENETRE — le rendu ne produit alors aucun element,
   donc il n'y a rien a masquer et aucune marge a rattraper. */
.pa-bonus {
  display: flex; align-items: center; gap: 10px;
  margin-top: 10px; padding: 8px 11px;
  border: 1px solid; border-radius: var(--ds-radius-tile);
}
.pa-bonus-x { flex: 0 0 auto; font-size: 1.15rem; font-weight: 900; letter-spacing: -.02em; }
.pa-bonus-t { font-size: .72rem; font-weight: 700; line-height: 1.35; }
.pa-next { font-size: .74rem; color: inherit; opacity: .72; margin-top: 7px; }
/* ---- LA PIECE D'UNE SAISON FINIE — la banniere devient un trophee.
   ⚠️ ELLE PREND LA PLACE DE « dernier palier atteint », rien de plus : la piece
   SOUS la grille n'a pas bouge. Aucune couleur ici — le dore de la piece est
   dans son SVG, il vient de `UI.DSE_METAUX` et ne suit pas le theme. */
.pa-fin { display: flex; align-items: center; gap: 11px; margin-top: 9px; }
.pa-fin-v { flex: 0 0 auto; display: inline-flex; }
.pa-fin-c { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pa-fin-t { font-size: .88rem; font-weight: 800; color: inherit; }
.pa-fin-d { font-size: .74rem; color: inherit; opacity: .72; }

/* ---- LE VERROU D'UNE SAISON PAYANTE.                          (2026-08-17)
   Un bloc qui n'existe dans la page que pour une saison VERROUILLEE : une
   saison gratuite ou deja payee ne le rend pas du tout, l'en-tete est alors
   celui d'avant au caractere pres. ⚠️ AUCUNE COULEUR EN DUR, comme partout
   ailleurs sur cet ecran : tout vient des jetons du theme. */
/* ⚠️ SES COULEURS ONT ETE RE-SOURCEES LE 2026-08-18, ET SON RENDU N'A PAS BOUGE
   D'UN CARACTERE : `passeVerrouHTML` est intacte, ses trois cas et ses trois
   messages aussi (g81 §4 les EXECUTE). Seules les encres changent — elles
   venaient de `--ds-text-dim` / `--ds-text-faint` / `--ds-accent-ink-fort`,
   jetons du theme EQUIPE donc SOMBRES sur cet ecran clair, et ce bloc vit
   desormais sur une banniere sombre. Elles sont l'encre de la banniere, a trois
   opacites. Le plateau est un voile de cette meme encre : aucune couleur ecrite. */
.pa-head.verr { border: 1px solid; }
.pa-verr {
  margin-top: 11px; padding: 10px 11px; border-radius: 12px;
  background: color-mix(in srgb, currentColor 9%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
}
.pa-verr-h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pa-verr-t { font-size: .78rem; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: inherit; opacity: .74; }
.pa-verr-p { font-size: .96rem; font-weight: 800; color: inherit; }
.pa-verr-d { font-size: .74rem; line-height: 1.45; color: inherit; opacity: .74; margin-top: 6px; }
.pa-verr-a { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 9px; }
.pa-verr-s { font-size: .74rem; color: inherit; opacity: .78; }
.pa-verr-a .btn[disabled] { opacity: .5; pointer-events: none; }
/* LA LIGNE DE LA DEVANCIERE — le cas ou ce qui manque n'est pas des jetons mais
   une saison a finir. Elle remplace le bloc bouton+solde, elle ne s'y ajoute
   jamais : les deux ne coexistent dans aucun etat. */
.pa-verr-pre { font-size: .76rem; line-height: 1.45; color: inherit; opacity: .86; margin-top: 9px; }

/* ---- LE RAIL DES SAISONS — DES CARTES QUI GLISSENT.            (2026-08-18)
   ⚠️ C'ETAIENT DEUX RECTANGLES QUI SE PARTAGEAIENT LA LARGEUR. A neuf saisons
   ils seraient illisibles : les cartes ont donc une largeur PROPRE et le rail
   defile, avec l'inertie du doigt et un pas d'arret sur chaque carte.
   ⚠️ IL N'EXISTE DANS LA PAGE QU'A PARTIR DE DEUX SAISONS : avec une seule, le
   rendu ne produit pas ce bloc du tout — ce n'est pas un masquage CSS.
   ⚠️ AUCUNE COULEUR ECRITE ICI. Chaque carte porte le fond et l'encre du theme
   de SA saison, poses en ligne par `passeTeinte` ; la surface ci-dessous n'est
   qu'un repli, pour une saison sans theme lisible. */
.pa-sais {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 4px; margin: 0 0 7px;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
/* ⚠️ LES DEUX TEXTES D'UNE CARTE REVIENNENT A LA LIGNE, ILS NE SONT PAS COUPES.
   Une premiere prise les tronquait a l'ellipse : la carte disait « A ouvrir
   pour 200 j… » et « Fin… », c'est-a-dire RIEN de ce qu'il faut faire — le
   defaut meme que ce libelle existe pour corriger. Les cartes ayant la meme
   hauteur (`align-items: stretch` sur le rail), la plus bavarde donne sa
   hauteur aux autres, et aucune ne perd un mot. */
.pa-sc {
  flex: 0 0 auto; width: 10.5rem; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: stretch; gap: 3px;
  font: inherit; text-align: left; padding: 9px 11px 10px; border-radius: 13px; cursor: pointer;
  background: var(--ds-card); color: var(--ds-text);
  border: 0; box-shadow: var(--ds-shadow-tile); overflow: hidden;
}
.pa-sc-n { font-size: .66rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: inherit; opacity: .66; }
.pa-sc-t { font-size: .92rem; font-weight: 800; color: inherit;
  line-height: 1.2; overflow-wrap: anywhere; }
.pa-sc .pa-crans { margin-top: 5px; gap: 2px; }
.pa-sc .pa-crans > i { height: 5px; }
.pa-sc-p { font-size: .7rem; line-height: 1.3; color: inherit; opacity: .82;
  margin-top: 4px; overflow-wrap: anywhere; }
/* ⚠️ TROIS ETATS DE CARTE, ET ILS NE DISENT PAS LA MEME CHOSE (2026-08-17) :
   `on` = la saison ACTIVE, celle qui recoit les points · `vue` = celle que
   l'ecran montre sans qu'elle recoive rien (le seul cas est une saison
   verrouillee) · `verr` = elle a un prix et il n'est pas paye. Une carte peut
   etre `vue` ET `verr` ; elle ne peut jamais etre `on` ET `verr`.
   ⚠️ L'ANNEAU D'OR DE L'ACTIVE EST POSE EN LIGNE, jamais ici : il vient de
   `UI.DSE_METAUX`, la table unique des metaux, et le dore ne suit pas le theme.
   ⚠️ `vue` RESTE UN LISERE, PAS UNE COULEUR : la carte porte deja celle de sa
   saison, un second aplat aurait efface la premiere. */
.pa-sc.vue { outline: 2px solid currentColor; outline-offset: -2px; }
/* ⚠️ UNE SAISON VERROUILLEE EST GRISE, ET SON GRIS EST DERIVE, PAS POSE ICI :
   `passeTeinte(s, true)` rend le NEUTRE DE MEME LUMINANCE que sa couleur, donc
   la carte perd sa teinte sans perdre un point de contraste. La feuille ne fait
   qu'en assourdir le relief. */
.pa-sc.verr { box-shadow: none; }
.pa-sc.verr .pa-sc-p { font-weight: 800; opacity: .92; }
.pa-sais-d { font-size: .72rem; color: var(--ds-text-faint); margin: 0 0 12px; }

/* ---- Les deux onglets. Grille a colonnes egales, comme la barre du Palmares. */
.pa-tabs { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px;
  background: var(--ds-track); padding: 3px; border-radius: 12px; margin-bottom: 12px; }
.pa-tab { font: inherit; font-size: .82rem; font-weight: 700; padding: 8px 4px;
  border: 0; border-radius: 9px; background: transparent; color: var(--ds-text-dim); cursor: pointer; }
.pa-tab.on { background: var(--ds-card); color: var(--ds-text); box-shadow: var(--ds-shadow-tile); }

/* ---- La grille des dix paliers : CINQ par rangee, deux rangees.
   ⚠️ LES DIX TUILES ONT LA MEME STRUCTURE ET LA MEME HAUTEUR. La hauteur est
   posee ici une seule fois ; aucun type de recompense ne l'allonge. */
.pa-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin-bottom: 12px; }
.pa-t {
  display: flex; flex-direction: column; align-items: stretch; gap: 3px;
  /* 78 px = 5 (marge) + 11,8 (numero) + 3 + 4 + 32 (bandeau) + 4 + 3 + 9,6
     (etat) + 4. Le bandeau a grandi de 4 px avec ses marges propres : la tuile
     suit, sinon le numero ou l'etat se ferait rogner. */
  height: 78px; padding: 5px 3px 4px; cursor: pointer;
  border: 1px solid var(--ds-line); border-radius: 10px;
  background: var(--ds-card); box-shadow: var(--ds-shadow-tile);
  font: inherit; color: var(--ds-text); overflow: hidden;
}
.pa-t.sel { border-color: var(--ds-accent); box-shadow: 0 0 0 2px var(--ds-accent-dim); }
.pa-t.todo { opacity: .62; }
.pa-t-n { font-size: .74rem; font-weight: 800; line-height: 1; color: var(--ds-text-dim); }
.pa-t-e { font-size: .6rem; font-weight: 700; line-height: 1;
  text-transform: uppercase; letter-spacing: .02em; color: var(--ds-text-faint); }
.pa-t.ok .pa-t-e { color: var(--ds-good-ink); }
.pa-t.next .pa-t-e { color: var(--ds-accent-ink); }

/* ---- LE BANDEAU DE MINIATURE : la recompense montree, pas suggeree.
   ⚠️ LES DIX ONT EXACTEMENT LA MEME FORME — 32 px de haut, 8 px de rayon, un
   lisere interne discret. Seuls le FOND et le CONTENU changent, et TOUS DEUX
   sont poses EN LIGNE par js/main.js depuis la table unique `UI.PVM` (ou, pour
   le skin, le sticker et le theme de saison, depuis leur propre definition).
   AUCUNE couleur de recompense n'est ecrite ici : ce bloc n'a que la geometrie.
   C'est la meme regle que pour les cinq finitions et les quatre metaux — une
   miniature MONTRE la recompense, un theme n'a rien a y repeindre. */
.pvm { height: 32px; flex: none; border-radius: 8px; margin: 4px 0; position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(35, 55, 95, .07); }
.pvm .tx { font-size: 12px; font-weight: 800; line-height: 1; }
/* ⚠️ LA POLICE EMBARQUEE S'APPELLE « DS Signature », PAS « DancingScript ».
   C'est le nom declare par le `@font-face` de index.html ; se tromper de nom ne
   provoque aucune erreur — on retombe silencieusement sur une cursive systeme,
   qui n'a ni le meme dessin ni la meme chasse. La pile de repli est celle de
   `.stv-sig`, pour que le pseudo se lise pareil sur un sticker et dans sa
   miniature. */
.pvm .cur { font-family: "DS Signature", "Segoe Script", "Bradley Hand", "Snell Roundhand", "URW Chancery L", cursive;
  font-size: 15px; font-weight: 800; line-height: 1; }
.pvm .surm { font-size: 6.4px; font-weight: 800; font-style: italic; line-height: 1.35;
  text-align: center; padding: 0 3px; }
.pvm .ln { position: absolute; left: 22%; right: 22%; height: 2.4px; border-radius: 2px; }
.pvm .pill { font-size: 7px; font-weight: 800; border-radius: 4px; padding: 2px 5px; }
/* Les deux textes MESURES apres rendu (`UI.ajusterQuandPrete`). Leur boite est
   bornee ici : sans borne, `scrollWidth > clientWidth` ne serait jamais vrai et
   la reduction ne se declencherait pas. Le surnom tient sur DEUX lignes au
   plus — 2 x 1,35 em —, le pseudo sur une seule. */
.pvm .cur.pvm-fit { max-width: 100%; white-space: nowrap; overflow: hidden; }
.pvm .surm.pvm-fit { display: block; width: 100%; max-height: 2.7em; overflow: hidden; }
/* Un type de recompense sans miniature doit SE VOIR, pas passer inapercu. */
.pvm-inconnu { background: var(--ds-bad-soft-bg); color: var(--ds-bad-ink);
  font-size: .7rem; font-weight: 800; }

/* ---- LA PIECE DE SAISON, SOUS LA GRILLE.                      (2026-08-18)
   ⚠️ ELLE N'EST PAS UNE ONZIEME CASE : elle vit HORS de `.pa-grid`, dans son
   propre bloc, precede d'un separateur discret. Le compteur « Palier 3 / 10 »
   doit rester vrai a l'oeil, et un quadrillage de onze cases l'aurait dementi.
   ⚠️ AUCUNE COULEUR EN DUR, comme partout ailleurs sur cet ecran : les jetons du
   theme pour le bloc, et — pour le cadre dore de la piece GAGNEE — la table
   unique `UI.DSE_METAUX`, posee EN LIGNE par js/main.js. Le metal du jeu ne suit
   pas les themes ; il n'a donc rien a faire ici.
   ⚠️ « EN VEILLEUSE » EST UN ETAT DU CADRE, PAS DU DESSIN : `UI.pieceHTML` rend
   la meme chaine gagnee ou non (g86). Ce qui se voit ici est une opacite et une
   desaturation posees sur le porte-dessin, jamais une seconde gravure. */
.pa-pc-sep { display: flex; align-items: center; gap: 9px; margin: 2px 0 9px; }
.pa-pc-sep::before, .pa-pc-sep::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--ds-line);
}
.pa-pc-sep > span {
  flex: 0 0 auto; font-size: .64rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint);
}
.pa-pc {
  display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
  padding: 10px 12px; border-radius: var(--ds-radius-card);
  background: var(--ds-card); border: 1px solid var(--ds-line);
  box-shadow: var(--ds-shadow-tile);
}
.pa-pc-v { flex: 0 0 auto; display: inline-flex; opacity: .34; filter: grayscale(.6); }
.pa-pc.on .pa-pc-v { opacity: 1; filter: none; }
.pa-pc-c { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.pa-pc-n { font-size: .95rem; font-weight: 800; color: var(--ds-text-dim); }
.pa-pc.on .pa-pc-n { color: var(--ds-text); }
.pa-pc-d { font-size: .74rem; line-height: 1.4; color: var(--ds-text-faint); }
/* SA PROPRE barre, et elle compte en POINTS — celle de l'en-tete compte vers le
   palier suivant, ce n'est pas la meme mesure. Elle disparait une fois la piece
   gagnee : il n'y a plus rien a parcourir. */
.pa-pc-b { height: 6px; border-radius: 999px; background: var(--ds-track);
  overflow: hidden; margin-top: 3px; }
.pa-pc-b > i { display: block; height: 100%; border-radius: 999px; background: var(--ds-accent); }
.pa-pc-f { font-size: .72rem; font-weight: 700; color: var(--ds-text-faint); }
.pa-pc.on .pa-pc-f { color: var(--ds-accent-ink-fort); }

/* ---- L'ENCADRE DE DETAIL, UNIQUE et en bas. */
.pa-det { background: var(--ds-card); border-radius: var(--ds-radius-card);
  box-shadow: var(--ds-shadow-tile); padding: 11px 13px; }
.pa-det-vide { font-size: .82rem; color: var(--ds-text-faint); text-align: center; padding: 14px 0; }
.pa-det-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pa-det-t { font-size: 1rem; font-weight: 800; color: var(--ds-text); }
.pa-excl { font-size: .6rem; font-weight: 800; letter-spacing: .09em; padding: 2px 7px;
  border-radius: 999px; background: var(--ds-accent-soft-bg-2); color: var(--ds-accent-ink-fort); }
.pa-det-m { font-size: .72rem; color: var(--ds-text-faint); margin-top: 2px; }
.pa-det-d { font-size: .8rem; line-height: 1.4; color: var(--ds-text-dim); margin: 7px 0 9px; }

/* ---- L'APERCU. ⚠️ MEME CADRE POUR LES DIX : meme rayon, meme marge interne,
   meme hauteur minimale, contenu centre. C'est ce qui permet de comparer dix
   recompenses tres differentes.
   ⚠️ HAUTEUR *MINIMALE*, ET NON FIXE. A 150 px fixes, un kill feed de cinq
   lignes se retrouvait rogne en haut ET en bas : l'ecran annoncait « 5 frags »
   au-dessus de trois lignes et demie. Le cadre prend maintenant la hauteur
   qu'il faut, sans jamais descendre sous 86 px — c'est le plancher qui garde
   les dix apercus comparables.
   ⚠️ LE FOND CLAIR N'EST PAS ICI : il est pose EN LIGNE depuis `UI.PVM.cadre`,
   avec l'encre qui va avec, parce que cette surface NE SUIT PAS LES THEMES —
   elle porte des recompenses dessinees dans leurs vraies couleurs. Le fond de
   nuit, lui, reste declare une seule fois dans `.pa-ap-nuit` ci-dessous. */
.pa-ap {
  min-height: 86px; border-radius: 11px; overflow: hidden;
  display: flex; align-items: center; justify-content: center; flex-direction: column;
  gap: 5px; padding: 13px; text-align: center;
  border: 1px solid var(--ds-line);
}
/* LA LEGENDE, SOUS LE CADRE. Elle en est sortie a dessein : dedans, elle
   concurrencait la recompense et decalait le contenu centre d'un palier a
   l'autre. Dessous, elle est du texte de page — elle suit donc les themes,
   contrairement au cadre. */
.pa-leg { font-size: .68rem; line-height: 1.35; color: var(--ds-text-faint);
  margin-top: 6px; text-align: center; }
/* L'EXCEPTION BORNEE : fond de nuit pour ce qui vit sur fond sombre (arme, kill
   feed). Declaree dans `VITRINE_REGLES` de suite.js, exactement comme `.ar-vit`. */
.pa-ap-nuit {
  background:
    radial-gradient(78% 62% at 50% 40%, rgba(146, 174, 232, .26), rgba(0, 0, 0, 0) 72%),
    linear-gradient(165deg, #2A3350, #131828);
  border-color: transparent;
}
.pa-ap svg { max-width: 100%; height: auto; display: block; }
/* ⚠️ `color: inherit` PARTOUT DANS LE CADRE. Le cadre porte son encre en ligne ;
   un jeton `--ds-*` pose ici la reprendrait au theme, et le texte deviendrait
   blanc sur blanc au premier theme sombre. Seules les encres qui DISENT quelque
   chose (dore du surnom, des jetons, de la pastille) sont posees en ligne. */
.pa-vide { font-size: .78rem; color: inherit; opacity: .78; line-height: 1.4; padding: 0 6px; }
.pa-ap-nuit .pa-vide { color: rgba(255, 255, 255, .72); opacity: 1; }

/* La signature : police manuscrite deja embarquee, taille ET encre posees en
   ligne — jamais figees ici, sans quoi un nom long deborderait et l'encre
   suivrait le theme sur une surface qui, elle, ne le suit pas. */
.pa-sig { font-family: "DS Signature", "Segoe Script", "Bradley Hand", "Snell Roundhand", "URW Chancery L", cursive;
  display: inline-block; line-height: 1.1; white-space: nowrap; }
.pa-trace { width: 100%; height: 96px; }
.pa-jetons { font-size: 2.4rem; font-weight: 800; line-height: 1; }
.pa-jetons span { font-size: 1.4rem; }
.pa-evl { list-style: none; margin: 0; padding: 0; text-align: left; overflow: hidden;
  font-size: .68rem; line-height: 1.35; color: inherit; opacity: .82; }
.pa-evl li { margin-bottom: 3px; }

/* ---- LE CARTOUCHE des apercus 1 et 2 : une carte posee sur le cadre clair.
   Fond et contour viennent de `UI.PVM.cartouche`, en ligne. */
.pa-cart { width: 100%; border: 1px solid; border-radius: 9px; padding: 10px 12px;
  display: flex; flex-direction: column; align-items: center; gap: 4px; }
.pa-cart-l { display: block; width: 72%; height: 2px; border-radius: 2px; margin-top: 6px; }
.pa-cart-n { font-size: .84rem; font-weight: 800; }
.pa-cart-s { font-size: .82rem; font-style: italic; font-weight: 700; line-height: 1.3; }

/* ---- TROIS LIGNES DE HALL OF FAME (apercu du palier 6).
   ⚠️ CE CONTENEUR N'HABILLE PLUS RIEN LUI-MEME : les lignes qu'il porte sont
   celles du Hall of Fame, rendues par `legendeLigneHTML` et habillees par les
   regles `#screen-palmares .leg-*, .pa-hof .leg-*` plus haut dans ce fichier.
   Les anciennes classes `.pa-hof-l/-n/-s` ont disparu AVEC le second rendu
   qu'elles habillaient : une ligne d'apercu redessinee a la main.
   ⚠️ `pointer-events: none` EST LA GARDE D'INERTIE. Une ligne de Hall of Fame
   porte `data-idx` et un `cursor: pointer` : dans un apercu, elle ne doit ni
   s'ouvrir ni faire croire qu'elle s'ouvre. La seconde garde est cote code
   (le branchement des clics est borne a `#screen-palmares`). */
.pa-hof { width: 100%; display: flex; flex-direction: column; gap: 5px; pointer-events: none; }
.pa-hof .leg-row { margin-bottom: 0; }
.pa-hof .leg-top { cursor: default; }
.pa-hof .leg-ap-row { cursor: default; }

/* ---- L'APERCU DU THEME (palier 10) : celui de l'onglet « Themes », AGRANDI.
   ⚠️ AUCUNE COULEUR ICI, et c'est le point : `themeApercuHTML` pose les siennes
   en ligne depuis `THEMES.apercu()`. Ce conteneur ne fait que donner au meme
   apercu la hauteur d'un cadre de palier — les deux rendus restent la meme
   chaine, ce qu'un invariant verifie. */
.pa-thap { width: 100%; }
.pa-thap .pg-ap { height: 76px; border-radius: 12px; }
.pa-thap .pg-ap-c { left: 12px; right: 12px; bottom: 12px; height: 30px; border-radius: 9px; }
.pa-thap .pg-ap-a { left: 12px; top: 12px; width: 20px; height: 20px; }

/* La rediffusion : le vrai kill feed, joue LIGNE PAR LIGNE. Le rythme est ici,
   le contenu vient de `killfeedHTML` — une seule implementation du feed. */
.pa-rd { width: 100%; }
.pa-rd-t { font-size: .68rem; color: rgba(255, 255, 255, .8); margin-bottom: 4px; }
/* ⚠️ PLUS DE PLAFOND ICI. Il valait 108 px tant que `.pa-ap` faisait 150 px
   fixes ; le cadre prend desormais la hauteur qu'il faut, et couper le feed
   ferait mentir l'apercu (« 5 frags » au-dessus de trois lignes et demie). */
.pa-rd-f { max-height: none; }
.pa-rd-f .kf-cap { color: rgba(255, 255, 255, .66); }
.pa-rd-f .kf-line { opacity: 0; animation: pa-rd-in .45s ease-out forwards;
  animation-delay: calc(var(--kf-i, 0) * .85s); }
@keyframes pa-rd-in { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pa-rd-f .kf-line { opacity: 1; animation: none; }
}

/* ---- LA REDIFFUSION VUE DU PALMARES (palier 8), en tete de « Mes legendes ».
   Le cadre est en jetons de role, comme tout le socle ; seul l'interieur est
   sombre, parce qu'il porte un kill feed — et un kill feed est toujours sur
   fond de nuit, ici comme dans l'ecran du passe et dans le recit de saison. */
.pa-rdp { margin: 0 0 12px; border: 1px solid var(--ds-line); border-radius: 12px;
  background: var(--ds-card); padding: 10px; }
.pa-rdp-t { display: flex; justify-content: space-between; align-items: baseline;
  gap: 8px; font-size: .78rem; font-weight: 700; color: var(--ds-text);
  margin-bottom: 8px; }
.pa-rdp-t span { font-size: .68rem; font-weight: 500; color: var(--ds-text-dim); }
/* ⚠️ AU PALMARES COMME DANS L APERCU, LE FEED N'EST PLUS COUPE. Il l'etait tant
   que `.pa-ap` faisait 150 px fixes et `.pa-rd-f` 108 px, pour que les dix
   tuiles gardent la meme hauteur : le palmares devait alors relever le plafond
   lui-meme. Depuis que le cadre d apercu a une hauteur MINIMALE et non fixe, les
   deux montrent le feed entier — couper afficherait « 4 frags » au-dessus de
   trois lignes, ce qui ferait mentir l ecran sur ce que le moment a produit.
   Seul le FOND de nuit est repris de l apercu (un kill feed se lit toujours sur
   fond sombre, ici comme dans le recit de saison). */
   ⚠️ ET LE FOND DE NUIT N'EST PAS REECRIT ICI : la classe `.pa-ap-nuit` porte
   deja exactement ce fond, et c'est la SEULE declaration qui doit le contenir.
   En recopier les valeurs ouvrirait une deuxieme exception a la regle « aucun
   hexadecimal hors des jetons `--ds-*` », que quatre controles font respecter et
   qui ne tolere nommement que la vitrine des armes. */
.pa-rdp-c { border-radius: 12px; padding: 9px; text-align: center; }

/* ---- Le cadre de signature (palier 1). */
.pa-sig-o { margin-top: 10px; }
.pa-sig-r { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.pa-gr { font: inherit; font-size: .74rem; font-weight: 700; padding: 6px 10px;
  border-radius: 999px; cursor: pointer;
  border: 1px solid var(--ds-line); background: var(--ds-field-bg); color: var(--ds-text-dim); }
.pa-gr.on { border-color: var(--ds-accent); background: var(--ds-accent-soft-bg);
  color: var(--ds-accent-ink-fort); }
.pa-cadre { position: relative; height: 110px; border-radius: 12px;
  border: 1px dashed var(--ds-line-hover); background: var(--ds-field-bg);
  touch-action: none; cursor: crosshair; overflow: hidden; }
.pa-cadre svg { width: 100%; height: 100%; display: block; }
.pa-cadre-h { position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; font-size: .76rem; color: var(--ds-text-faint); pointer-events: none; }
.pa-sig-a { display: flex; gap: 8px; margin-top: 8px; }
.pa-sig-a .btn { width: auto; margin-top: 0; }

/* ---- Onglet Missions. Cet onglet PEUT defiler, contrairement a l'autre. */
.pa-mis { display: flex; flex-direction: column; gap: 8px; }
.pa-m { background: var(--ds-card); border-radius: 12px; box-shadow: var(--ds-shadow-tile);
  padding: 9px 11px; border-left: 3px solid var(--ds-line); }
.pa-m.ok { border-left-color: var(--ds-good); }
.pa-m.ko { opacity: .6; }
.pa-m-h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pa-m-t { font-size: .86rem; font-weight: 700; color: var(--ds-text); }
.pa-m-p { font-size: .74rem; font-weight: 800; color: var(--ds-accent-ink); white-space: nowrap; }
.pa-m-a { font-size: .72rem; color: var(--ds-text-faint); margin: 2px 0 6px; line-height: 1.35; }
.pa-m-b { height: 6px; border-radius: 999px; background: var(--ds-track); overflow: hidden; }
.pa-m-b > i { display: block; height: 100%; border-radius: 999px; background: var(--ds-accent); }
.pa-m.ok .pa-m-b > i { background: var(--ds-good); }
.pa-m-f { display: flex; align-items: center; justify-content: space-between;
  font-size: .72rem; color: var(--ds-text-dim); margin-top: 4px; }
.pa-m-ok { font-weight: 800; color: var(--ds-good-ink); }
.pa-mis-p { font-size: .74rem; color: var(--ds-text-faint); text-align: center; margin-top: 10px; }

/* ---- La marque de saison, posee sur une ligne du Hall of Fame (palier 6).
   ⚠️ SA VARIANTE DOREE — `.pa-marque.or`, quand la saison est menee a son dernier
   palier — N'A AUCUNE REGLE ICI, ET C'EST VOULU : ses deux couleurs viennent de
   `UI.DSE_METAUX`, la table unique des metaux, et sont posees EN LIGNE par
   `passeMarqueHTML`. Un metal encode un accomplissement : il reste donc hors de
   portee de tout theme, comme les quatre segments de la barre de la FORME.
   Ecrire l'or ici en ferait une seconde source, et un theme pourrait le
   redefinir. La regle ci-dessous porte la forme, jamais la distinction. */
.pa-marque { display: inline-block; font-size: .62rem; font-weight: 800;
  padding: 1px 6px; border-radius: 999px; margin-left: 6px;
  background: var(--ds-accent-soft-bg-2); color: var(--ds-accent-ink-fort); }

/* ==========================================================================
   CARRIERE COACH — MODE ISOLE                                  (2026-08-06)
   (le mode s'appelait « Le match » jusqu'au 2026-08-10 ; dossier, conteneur,
   sous-domaine, classes `.mt-*` et cle de stockage restent inchanges)

   ⚠️ AUCUN HEXADECIMAL ICI, ET C'EST UNE CONTRAINTE VERIFIEE. Le controle
   « aucune couleur en dur » de g32 lit styles.css depuis son marqueur JUSQU'A
   LA FIN DU FICHIER : tout ce bloc en fait partie. Les seules couleurs du mode
   qui ne viennent pas des jetons `--ds-*` sont celles du PLAN, des POINTS et
   des SURIMPRESSIONS, et elles sont posees en ATTRIBUTS SVG ou en STYLE EN
   LIGNE par js/match-cartes.js et js/match.js — jamais ici. C'est ce qui evite
   d'avoir a declarer une exception a `sansVitrine`.

   ⚠️ L'ECRAN NE PEUT PLUS DEBORDER, ET C'EST STRUCTUREL. Il ne se mesure plus
   apres coup : `.mt-plein` est une COLONNE DE HAUTEUR BORNEE dont TOUS les
   blocs sont soit a hauteur FIXE declaree, soit RETRECISSABLES. La somme des
   minimums (les cinq hauteurs ci-dessous, plus zero pour le plan) vaut 300 px :
   elle ne peut donc pas depasser une fenetre de telephone, a n'importe quelle
   largeur. Avant la refonte du 2026-08-10, chaque bloc empilait sa hauteur
   propre, il fallait defiler, et les deux colonnes de joueurs se chevauchaient
   (844 px pour 844 a 390, 870 pour 844 a 430).
   ⚠️ ET DEPUIS LE 2026-08-10 (SECONDE PASSE), CE N'EST PLUS LE PLAN QUI ABSORBE
   LE RESTE, C'EST LA COLONNE DES JOUEURS. Le plan prend EXACTEMENT la hauteur
   que le rapport de la carte reclame (`aspect-ratio: var(--mt-ar)`, valeur
   posee en ligne par js/match.js) : c'est la seule facon de n'avoir aucune
   bande vide ni au-dessus ni en dessous de la carte. La place qu'il ne reclame
   pas ne peut donc pas lui rester — elle va aux dix joueurs, qui etaient
   justement le bloc le plus a l'etroit. Pendant un choix, ou les colonnes
   s'effacent, c'est l'encart de decision qui la prend.
   ⚠️ LES CINQ HAUTEURS VIVENT DANS CES CINQ VARIABLES, ET NULLE PART AILLEURS.
   Un invariant les relit et verifie qu'elles laissent au plan de quoi exister ;
   ecrire une hauteur en dur dans une regle la rendrait invisible a ce controle.
   ========================================================================== */
/* ⚠️ CET ECRAN NE GLISSE PAS A L ENTREE, ET C EST UNE CONSEQUENCE DIRECTE DU
   « SANS DEFILEMENT ». `.screen` porte depuis toujours un fondu d entree qui
   translate le bloc de 6 px vers le haut (`@keyframes fade`). Sur les onze
   autres ecrans il ne se voit pas : leur contenu ne remplit pas la fenetre, et
   les 6 px tombent dans la marge. Celui-ci la remplit EXACTEMENT — le fondu
   rendait donc la page haute de 850 px pendant un quart de seconde, et elle
   defilait. Mesure : 850 px pendant le fondu, 844 apres, aux deux largeurs. Le
   fondu est retire pour ce seul ecran ; les onze autres le gardent. */
#screen-match {
  animation: none;
  /* Le budget de hauteur du HUD. Le plan prend TOUT le reste. */
  --mt-h-bar: 42px;      /* 1. la barre : retour, equipes, score, horloge */
  --mt-h-frise: 22px;    /* 2. la frise des 24 manches et la vitesse       */
  --mt-h-eco: 30px;      /* 4. l economie des deux camps, sur une ligne    */
  /* ⚠️ 5. LES DIX JOUEURS — C EST DESORMAIS UN PLANCHER, PAS UNE HAUTEUR.
     C est le bloc ELASTIQUE de l ecran : il prend la place que le plan ne
     reclame pas. Sur Inferno (rapport 1,021) le plan demande 362 px des 544
     disponibles a 390 de large, et les 182 px restants viennent ici — les
     rangees passent de 25 a 61 px, ce qui est la hauteur d une ligne de liste
     sur telephone. En-dessous de ce plancher, il ne se laisse plus retrecir. */
  --mt-h-cols: 130px;    /* 5. les dix joueurs, deux colonnes de cinq      */
  --mt-h-acts: 44px;     /* 6. les boutons d action                        */
  --mt-h-gap: 4px;       /* l ecart entre deux blocs                       */
  --mt-h-pad: 6px;       /* le rembourrage vertical de l ecran             */
  padding: var(--mt-h-pad) 10px;
}
/* La page de fin de match, elle, DEFILE : c'est un compte rendu, pas un HUD. */
#screen-match .mt-wrap:not(.mt-plein) { padding-bottom: 34px; }

#screen-match .mt-wrap.mt-plein {
  display: flex; flex-direction: column; gap: var(--mt-h-gap);
  height: calc(100vh - 2 * var(--mt-h-pad));
  height: calc(100dvh - 2 * var(--mt-h-pad)
               - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  overflow: hidden;
}
/* ⚠️ CETTE TRIPLETTE EST LA GARANTIE DE NON-DEBORDEMENT, ET IL FAUT LES TROIS.
   Tout est fixe (1), SAUF le plan qui prend le rapport de sa carte et peut se
   retrecir jusqu a zero (2), et SAUF les joueurs qui prennent tout le reste
   sans jamais descendre sous leur plancher (3). La somme des minimums vaut
   300 px : le debordement est donc impossible, a n importe quelle largeur.
   ⚠️ ET C EST LA REGLE (2) QUI SUPPRIME LES DEUX BANDES NOIRES. Une hauteur
   figee laissait le SVG se centrer dans un bloc deux fois trop haut : la carte
   flottait au milieu de 272 px de plateau vide. `--mt-ar` est le rapport de la
   carte, pose EN LIGNE par js/match.js — un NOMBRE, jamais une couleur, meme
   geste que `--mt-ring-p`. Le repli 1.36 est celui du cadre d avant. */
.mt-plein > * { flex: 0 0 auto; }
.mt-plein > .mt-mapwrap { flex: 0 1 auto; min-height: 0; aspect-ratio: var(--mt-ar, 1.36); }
.mt-plein > .mt-cols { flex: 1 1 auto; min-height: var(--mt-h-cols); }

/* ---- 1. LA BARRE UNIQUE. Elle a remplace trois blocs : le bandeau de retour
     et de graine, le bandeau de score et ses trois pastilles, et l en-tete du
     plan qui portait l horloge. */
.mt-bar { height: var(--mt-h-bar); display: flex; align-items: center; gap: 6px;
  padding: 0 8px; background: var(--ds-card); border: 1px solid var(--ds-outline);
  border-radius: var(--ds-radius-card); box-shadow: var(--ds-shadow-tile); }
.mt-back { flex: 0 0 auto; padding: 4px 9px; font-size: .68rem; border-radius: 9px; }
.mt-tn { flex: 1 1 0; min-width: 0; font-size: .72rem; font-weight: 800; color: var(--ds-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mt-tn-r { text-align: right; }
.mt-sc { flex: 0 0 auto; font-size: 1rem; font-weight: 900; color: var(--ds-accent-ink);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.mt-chrono { flex: 0 0 auto; font-size: .84rem; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--ds-text); white-space: nowrap; }
/* ⚠️ DES QUE LA BOMBE EST POSEE, C'EST ELLE QUI COMPTE : le chrono de manche ne
   decide plus rien. Sa teinte et sa plaque sombre sont posees EN LIGNE par
   js/match.js — ici, seule la geometrie de la plaque. */
.mt-chrono-b { font-size: .9rem; letter-spacing: .01em;
  padding: 1px 6px; border-radius: var(--ds-radius-pill); }

/* ---- 2. LA FRISE DES 24 MANCHES ET LA COMMANDE DE VITESSE, MEME RANGEE.
     ⚠️ `flex-wrap: nowrap` EST UNE REGLE DE HAUTEUR, PAS DE STYLE : c'est cette
     rangee qui, en se dedoublant a 430 px, reprendrait au plan les 22 px qu'il
     vient de gagner. */
.mt-friserow { height: var(--mt-h-frise); display: flex; flex-wrap: nowrap;
  align-items: center; gap: 8px; }
.mt-frise { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 2px; }
.mt-fr { flex: 1 1 0; min-width: 0; height: 7px; border-radius: 2px; background: var(--ds-track); }
.mt-fr-g { background: var(--ds-good); }
.mt-fr-p { background: var(--ds-bad); }
.mt-fr-c { background: var(--ds-accent); }
.mt-fr-a { background: var(--ds-track); }
.mt-fr-sep { flex: 0 0 2px; width: 2px; height: 13px; border-radius: 1px;
  background: var(--ds-text-faint); margin: 0 3px; }
/* ⚠️ LA VITESSE NE CHANGE QUE LA DUREE REELLE : ni le moteur, ni un tirage, ni
   un enchainement n'en dependent. La seule chose qu'elle change a l'ECRAN est
   le vol des utilitaires, qui cesse d'etre anime au-dela du seuil — un objet
   qui glisse en 125 ms ne se lit pas. */
.mt-vit { flex: 0 0 auto; display: flex; align-items: center; gap: 3px; }
.mt-vb { font: inherit; font-size: .56rem; font-weight: 800; line-height: 1;
  padding: 3px 5px; border-radius: var(--ds-radius-pill); cursor: pointer;
  background: var(--ds-track); color: var(--ds-text-dim); border: 1px solid transparent; }
.mt-vb.on { background: var(--ds-accent-soft-bg); color: var(--ds-accent-ink-fort);
  border-color: var(--ds-accent-dim); }
/* Le bouton de pause porte deux barres, puis un triangle quand il est enfonce :
   aucun texte, donc aucune chaine a accentuer. */
.mt-vb-p { width: 21px; position: relative; }
.mt-vb-p::before, .mt-vb-p::after { content: ""; position: absolute; top: 4px; bottom: 4px;
  width: 2px; background: currentColor; }
.mt-vb-p::before { left: 7px; }
.mt-vb-p::after { left: 11px; }
.mt-vb-p.on::before { left: 7px; width: 0; top: 3px; bottom: 3px;
  border-left: 6px solid currentColor; border-top: 4px solid transparent;
  border-bottom: 4px solid transparent; background: none; }
.mt-vb-p.on::after { display: none; }

/* ---- 3. LE PLAN. Le SVG est rappele par <use>, jamais redessine.
   ⚠️ LA CARTE REMPLIT SON BLOC, ET C EST LE BLOC QUI PREND SA FORME. La largeur
   du cadre reste fixe (340), sa hauteur DERIVE du rapport de la carte, et le
   bloc adopte ce meme rapport : il n y a donc plus de letterbox nulle part — ni
   dans le SVG, ni autour de lui. Une carte plus haute que large donne un bloc
   plus haut, une carte large un bloc plus court, et aucune ne se deforme.
   ⚠️ LE FOND DU PLATEAU RESTE DECLARE : il ne se voit plus qu au retrecissement
   (une carte dont le rapport demanderait plus que la fenetre entiere), ou il
   laisse alors ses marges A GAUCHE ET A DROITE — jamais au-dessus ni en
   dessous, ce qui est exactement ce que la carte ne doit pas avoir. */
.mt-mapwrap { position: relative; overflow: hidden;
  background: var(--mt-plan-fond); border-radius: var(--ds-radius-tile); }
.mt-plan { display: block; width: 100%; height: 100%; }
/* Un point se deplace en ECRIVANT SON `transform` : on le declare au navigateur
   pour qu'il lui reserve sa propre couche. Aucune transition CSS ici — c'est la
   boucle d'images qui tient l'allure, et une transition la contredirait. */
.mt-pt { will-change: transform; }

/* ---- 3 bis. LES TROIS SURIMPRESSIONS DU PLATEAU.
   ⚠️ ELLES NE COUTENT AUCUNE HAUTEUR, ET C'EST TOUTE LEUR RAISON D'ETRE. Le
   repere (carte, manche, camp) remplace les trois pastilles supprimees ; la
   situation remplace la rangee qui la partageait avec la legende ; le kill feed
   remplace un bloc de l'empilement. Leurs couleurs — la plaque sombre et son
   encre — sont posees EN LIGNE par js/match.js, comme toutes celles du mode. */
.mt-ov { position: absolute; z-index: 2; max-width: 62%;
  font-size: .58rem; font-weight: 800; letter-spacing: .03em; line-height: 1.2;
  padding: 2px 6px; border-radius: var(--ds-radius-pill);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mt-ov-tl { top: 4px; left: 4px; text-transform: uppercase; }
.mt-ov-bl { bottom: 4px; left: 4px; }

/* ---- 3 ter. LE KILL FEED, EN HAUT A DROITE DU PLAN.
   ⚠️ IL NE PREND AUCUNE HAUTEUR A L'ECRAN, ET C'EST POUR CELA QU'IL MONTRE
   DESORMAIS CINQ LIGNES au lieu de trois. Tant qu'il etait un bloc empile,
   chaque ligne se payait en pixels.
   ⚠️ 58 % DE LA LARGEUR DU PLAN AU PLUS : au-dela il recouvrirait le nom de la
   carte, en haut a gauche.
   ⚠️ ET LA BOITE DE L'ICONE EST FIXEE ICI, EN CSS — C'EST LA REGLE QUI A COUTE
   LE PLUS CHER. Une icone dont la taille n'est donnee QU'EN ATTRIBUTS `width`
   et `height` est redimensionnee par le moteur de rendu dans un conteneur
   flex : elle s'etalait sur trois lignes. La boite fait donc 24 sur 14 px,
   `flex: 0 0 24px` l'empeche de s'etirer, et le SVG a l'interieur fait 100 %
   des deux cotes. Le cadrage serre du dessin, lui, vit dans son `viewBox`
   (js/match.js) : un motif qui n'occupe qu'un quart de sa boite devient
   invisible a cette taille, et c'est ce qui donnait l'impression que l'arme
   manquait.
   ⚠️ LES SELECTEURS PORTENT `#screen-match` A DESSEIN : les regles du feed de
   carriere sont ecrites `html.theme-clair .kf-line .kf-*`, donc plus specifiques
   qu'une simple imbrication de classes. Sans l'identifiant, la victime
   reprendrait l'encre sombre du theme clair sur la plaque sombre du plateau. */
.mt-kf { position: absolute; z-index: 2; top: 4px; right: 4px; max-width: 58%;
  display: flex; flex-direction: column; gap: 1px;
  padding: 3px 5px; border-radius: var(--ds-radius-tile); }
#screen-match .mt-kf .kf-line {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  background: none; border: 0; border-radius: 0; padding: 0;
  font-size: .58rem; line-height: 1.35; animation: none; }
#screen-match .mt-kf .kf-line .kf-a { flex: 0 1 auto; min-width: 0; font-weight: 800;
  text-align: left; color: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#screen-match .mt-kf .kf-line .kf-w { flex: 0 0 24px; width: 24px; height: 14px;
  display: flex; align-items: center; justify-content: center; color: inherit; }
#screen-match .mt-kf .kf-line .kf-w svg { display: block; width: 100%; height: 100%; }
#screen-match .mt-kf .kf-line .kf-v { flex: 0 1 auto; min-width: 0; text-align: left;
  color: inherit; opacity: .58; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Le brouillard : ni l auteur ni la victime n ont ete vus, on ne sait pas avec
   quoi. Un point d interrogation, jamais un trou. */
#screen-match .mt-kf .kf-nc { font-size: .74rem; font-weight: 900; opacity: .7; }

/* ---- 4. L ECONOMIE DES DEUX CAMPS, SUR UNE SEULE LIGNE.
   ⚠️ LES NOMS DES DEUX EQUIPES N'Y SONT PLUS : ils sont ecrits dans la barre,
   au-dessus du score, et une seconde fois sous le score ne disait rien de plus.
   ⚠️ LES DEUX TEINTES DE CAMP SONT POSEES EN LIGNE par js/match.js : elles
   S'ECHANGENT a la mi-temps, et une classe figee dirait le contraire de ce que
   montre le plan. Ce bloc ne decrit que la geometrie. */
.mt-eco { height: var(--mt-h-eco); display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.mt-eco-c { display: flex; align-items: center; justify-content: space-between; gap: 6px;
  min-width: 0; padding: 0 7px;
  background: var(--ds-card); border: 1px solid var(--ds-outline);
  border-radius: var(--ds-radius-tile); }
/* L etiquette porte le FOND du camp — pose en ligne — et son encre reste celle
   du theme (`--ds-on-solid`, le jeton « sur aplat colore »). */
.mt-eco-t { min-width: 0; font-size: .55rem; font-weight: 800; letter-spacing: .02em;
  border-radius: var(--ds-radius-pill); padding: 2px 7px; color: var(--ds-on-solid);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mt-eco-b { flex: 0 0 auto; font-size: .74rem; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--ds-text); white-space: nowrap; }

/* ---- 5. LES DIX JOUEURS — DEUX COLONNES DE CINQ, UNE LIGNE CHACUN.
   ⚠️ PLUS AUCUN DEFILEMENT ICI, ET C'EST LA LIGNE QUI L'A PERMIS. Elle portait
   une SECONDE rangee pour les quatre grenades a 36 px, ce qui la faisait passer
   de 18 a 53 px : 150 px pour dix joueurs. Les grenades sont devenues des
   PASTILLES de 4 px a la teinte de leur objet, la ligne tient sur une ligne, et
   les cinq rangees d une colonne se partagent exactement la hauteur declaree.
   ⚠️ SIX CHAMPS, DANS CET ORDRE, ET AUCUN NE PASSE A LA LIGNE : pastille de
   camp · pseudo · barre de vie · argent · icone d arme · grenades. */
.mt-cols { min-height: var(--mt-h-cols); display: grid; grid-template-columns: 1fr 1fr;
  gap: 6px; overflow: hidden; }
.mt-col { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-rows: repeat(5, 1fr); gap: 2px; min-width: 0; }
.mt-pl { display: grid; grid-template-columns: 7px minmax(0, 1fr) 18px auto 18px auto;
  gap: 3px; align-items: center; min-width: 0; padding: 0 5px; font-size: .6rem;
  background: var(--ds-card); border: 1px solid var(--ds-outline);
  border-radius: var(--ds-radius-tile); }
/* ⚠️ LA PASTILLE DE LA LIGNE SUIT LE CAMP, PAS L EQUIPE — meme regle que le
   plan, et sa couleur est posee en ligne pour la meme raison. */
.mt-pd { width: 7px; height: 7px; border-radius: 999px; display: block; }
.mt-pn { min-width: 0; font-weight: 800; color: var(--ds-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* LA BARRE DE VIE — meme lecture que l anneau du marqueur : c est la LONGUEUR
   qui porte l information, jamais la teinte. Le rail EST la plaque sombre, ce
   qui rend le vert lisible sur une carte claire ; les deux sont poses en ligne. */
.mt-pv { display: block; width: 18px; height: 5px; border-radius: 3px; overflow: hidden; }
.mt-pv > i { display: block; height: 100%; border-radius: 3px; }
.mt-pb { font-size: .56rem; font-weight: 700; text-align: right; white-space: nowrap;
  font-variant-numeric: tabular-nums; color: var(--ds-good-ink); }
.mt-pa { display: flex; align-items: center; justify-content: center; }
.mt-pai { display: block; width: 18px; height: 12px; line-height: 0; }
.mt-pai svg { display: block; width: 100%; height: 100%; }
/* ⚠️ UNE GRENADE LANCEE S ETEINT, ELLE NE DISPARAIT PAS : la difference entre
   ce qu on portait et ce qu on porte encore EST l information. */
.mt-pg { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }
.mt-pgi { display: block; height: 9px; border-radius: 2px; }
.mt-pgi-off { opacity: .26; filter: grayscale(1); }
/* Un mort : pseudo barre et grise, ligne en retrait. Ta ligne : surlignee. */
.mt-pl-mort { opacity: .55; }
.mt-pl-mort .mt-pn { text-decoration: line-through; color: var(--ds-text-faint); }
.mt-pl-moi { border-color: var(--ds-accent); background: var(--ds-accent-soft-bg); }

/* ---- 6. Moment de decision. L'anneau est une conique pilotee par --mt-ring-p,
     posee par js/main.js : la valeur est un NOMBRE, jamais une couleur. */
.mt-dec { background: var(--ds-accent-soft-bg); border: 1px solid var(--ds-accent-dim);
  border-radius: var(--ds-radius-card); padding: 9px 10px; }
/* Pendant un choix, l encart peut manquer de place sur un petit ecran : il peut
   se resserrer, et il peut defiler en dernier recours. Le plan, lui, se contente
   de retrecir.
   ⚠️ ET C EST LUI QUI ABSORBE LA PLACE QUE LE PLAN NE RECLAME PAS PENDANT UN
   CHOIX : les colonnes s effacent (regle 8), il n y aurait sinon plus aucun bloc
   elastique et le bas de l ecran resterait vide. Il n existe donc jamais qu UN
   SEUL bloc elastique a un instant donne — les colonnes pendant le jeu, l encart
   pendant un choix, et les deux ne coexistent jamais. */
.mt-plein > .mt-dec { flex: 0 1 auto; min-height: 0; overflow-y: auto; }
.mt-choix > .mt-dec { flex: 1 1 auto; }
.mt-dec-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.mt-dec-t { font-size: .84rem; font-weight: 900; color: var(--ds-accent-ink-fort); }
.mt-ring { --mt-ring-p: 1; position: relative; width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 999px; display: grid; place-items: center;
  background: conic-gradient(var(--ds-accent) calc(var(--mt-ring-p) * 360deg), var(--ds-track) 0); }
.mt-ring::after { content: ""; position: absolute; inset: 4px; border-radius: 999px;
  background: var(--ds-card); }
.mt-ring-n { position: relative; z-index: 1; font-size: .72rem; font-weight: 900; color: var(--ds-text); }
.mt-dec-l { font-size: .74rem; color: var(--ds-text); margin: 6px 0 0; line-height: 1.35; }
.mt-dec-l2 { color: var(--ds-text-dim); }
.mt-opts { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.mt-opt { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; text-align: left;
  padding: 6px 9px; height: auto; }
.mt-opt-n { font-size: .78rem; font-weight: 800; }
.mt-opt-s { font-size: .66rem; font-weight: 800; color: var(--ds-accent-ink); white-space: nowrap; }
.mt-opt-e { grid-column: 1 / -1; font-size: .66rem; font-weight: 500;
  color: var(--ds-text-dim); line-height: 1.3; }
.mt-dec-def { font-size: .66rem; color: var(--ds-text-faint); margin: 6px 0 0; text-align: center; }

/* ---- 7. Fin de manche, recapitulatif de fin de match, boutons. */
.mt-fin { font-size: .7rem; font-weight: 800; color: var(--ds-accent-ink);
  text-align: center; margin: 0; }
.mt-recap { background: var(--ds-card); border: 1px solid var(--ds-outline);
  border-radius: var(--ds-radius-card); box-shadow: var(--ds-shadow-tile);
  padding: 10px 12px; margin: 10px 0; }
.mt-recap-t { font-size: 1.02rem; font-weight: 900; color: var(--ds-accent-ink);
  margin: 0 0 8px; text-align: center; }
.mt-recap-l { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.mt-recap-l li { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: .74rem; color: var(--ds-text-dim); }
.mt-recap-l b { font-variant-numeric: tabular-nums; font-size: .86rem; color: var(--ds-text); }
/* ⚠️ LES BOUTONS SONT COTE A COTE, PAS EMPILES. Deux grandes cases l'une sous
   l'autre coutaient 60 px de hauteur pour rien, et la hauteur est justement ce
   qui manque sur cet ecran. */
.mt-acts { display: flex; flex-direction: row; gap: 7px; }
.mt-plein > .mt-acts { height: var(--mt-h-acts); }
/* ⚠️ ET LEUR LIBELLE TIENT SUR UNE LIGNE. A demi-largeur, « Phase suivante » et
   « Jouer la manche » repassaient a la ligne et la case doublait de hauteur. */
.mt-acts > .btn { flex: 1 1 0; font-size: .86rem; padding: 0 8px; height: 100%; min-height: 40px; }
.mt-wrap:not(.mt-plein) .mt-acts { margin-top: 10px; }
.mt-wrap:not(.mt-plein) .mt-acts > .btn { padding: 10px 8px; height: auto; }

/* ---- 8. PENDANT UN CHOIX : l'encart de decision coute plus de 200 px.
   ⚠️ LE PLAN N'EST PLUS BRIDE PAR UNE HAUTEUR ECRITE A LA MAIN : etant le seul
   bloc elastique, il se resserre tout seul de ce que l'encart prend. Ce qui
   reste un ARBITRAGE, c'est ce qu'on RETIRE : les colonnes et la bande
   d'economie, parce que la DEUXIEME ligne de la situation dit deja l'etat de
   tes coequipiers, et la banque ne bouge pas pendant les quatre secondes. Le
   plan, lui, RESTE : c'est sur lui qu'on decide. */
.mt-choix .mt-cols,
.mt-choix .mt-eco,
/* Pendant un choix rien ne bouge et le chrono est fige : la commande de vitesse
   n'a plus rien a commander, elle laisse sa place. */
.mt-choix .mt-vit,
/* Le feed recouvrirait un plan deja reduit de moitie. */
.mt-choix .mt-kf { display: none; }

/* ---- 9. LE TABLEAU DES DIX FICHES, en fin de match. Rating, ADR et KAST sont
   cumules manche par manche par le moteur ; ici on ne fait que les ranger. Il
   ne s'affiche qu'a la fin, ou la hauteur n'est plus contrainte par le plan. */
.mt-stats { width: 100%; border-collapse: collapse; margin-top: 9px;
            font-size: .72rem; font-variant-numeric: tabular-nums; }
.mt-stats th { text-align: right; font-weight: 700; padding: 3px 4px;
               color: var(--ds-muted); border-bottom: 1px solid var(--ds-outline); }
.mt-stats th:first-child { text-align: left; }
.mt-stats td { text-align: right; padding: 3px 4px; color: var(--ds-text);
               border-bottom: 1px solid var(--ds-outline-soft, var(--ds-outline)); }
.mt-stats td:first-child { text-align: left; overflow: hidden; text-overflow: ellipsis;
                           max-width: 9em; white-space: nowrap; }
.mt-stats tbody tr:last-child td { border-bottom: 0; }
/* TA LIGNE EST MISE EN AVANT PAR LE POIDS, pas par un aplat : le tableau reste
   lisible dans les dix themes du jeu. */
.mt-st-moi td { font-weight: 800; color: var(--ds-accent-ink); }

/* ---- 10. L ANNEAU DE VIE QUI BAT                              (2026-08-08)
   ⚠️ SOUS 30 POINTS DE VIE, C'EST LE RYTHME QUI ALERTE, JAMAIS LA TEINTE.
   L'anneau reste vert et se contente de battre : un anneau qui rougirait
   entrerait en collision avec l'ocre du camp T, et le joueur lirait un camp la
   ou on lui parle d'une blessure. Aucune couleur ici — l'arc, sa teinte et sa
   longueur sont poses par js/match.js. */
@keyframes mt-vie-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .34; } }
.mt-vie-bas { animation: mt-vie-pulse 1.05s ease-in-out infinite; }
/* Le battement est une INFORMATION, pas un ornement : quand le mouvement est
   refuse, l'anneau reste PLEINEMENT visible au lieu de disparaitre a moitie. */
@media (prefers-reduced-motion: reduce) {
  .mt-vie-bas { animation: none; opacity: 1; }
}

/* ---- 10 bis. LA JAUGE DE MUNITIONS QUI CLIGNOTE              (2026-08-10)
   ⚠️ SOUS UN QUART DE CHARGEUR, C'EST LE MOMENT DU CHOIX — recharger, ou changer
   d'arme — et c'est le RYTHME qui le dit. Meme regle que l'anneau de vie, et
   meme raison : la longueur et la teinte portent deja deux informations (ce qui
   reste, et le rechargement en cours), le battement en porte la troisieme sans
   entrer en collision avec elles.
   ⚠️ IL BAT PLUS VITE QUE L'ANNEAU DE VIE, ET C'EST DELIBERE : deux battements
   synchrones sur le meme marqueur se liraient comme UN seul signal. Aucune
   couleur ici non plus — le contour, sa teinte et sa longueur sont poses par
   js/match.js. */
@keyframes mt-jauge-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .28; } }
.mt-jt-bas { animation: mt-jauge-pulse .72s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .mt-jt-bas { animation: none; opacity: 1; }
}

/* ============================================================================
   LES UTILITAIRES DU MODE                                       (2026-08-10)

   ⚠️ AUCUN HEXADECIMAL ICI, ET C'EST LA MEME REGLE QUE POUR LE RESTE DU MODE.
   Les cinq dessins portent leurs propres teintes DANS leur `<symbol>` (js/
   match.js) ; la zone au sol, sa trainee, son arc et son decompte sont peints
   en attributs SVG par le module. Ce bloc ne fait que POSER et DIMENSIONNER.
   ============================================================================ */

/* ---- Le dessin lui-meme : trois tailles, un seul symbole. La largeur et la
     hauteur sont posees en attribut par `MATCH.utilHTML` — on ne les redit pas
     ici, sinon les trois tailles n'en feraient plus qu'une. La seule exception
     est la boite du kill feed, ou c'est le CSS qui commande (cf. 3 ter). */
.mt-u { display: block; }

/* ---- La vitrine des cinq utilitaires, sur l'ecran de fin de match. C'est le
     seul endroit du mode ou la hauteur ne se dispute pas avec le plan. */
.mt-uvit { margin-top: 12px; }
.mt-uvit-t { font-size: .74rem; font-weight: 900; color: var(--ds-text-dim);
  margin: 0 0 6px; text-transform: uppercase; letter-spacing: .04em; }
.mt-uvit-l { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap;
  gap: 6px; justify-content: space-between; }
.mt-uvit-i { flex: 1 1 56px; min-width: 56px; display: flex; flex-direction: column;
  align-items: center; gap: 1px; padding: 6px 2px; border-radius: var(--ds-radius-tile);
  background: var(--ds-track); }
/* Celui qui n'est pas de ton camp reste lisible, mais recule d'un plan. */
.mt-uvit-a { opacity: .5; }
.mt-uvit-n { font-size: .6rem; font-weight: 800; color: var(--ds-text); text-align: center; }
.mt-uvit-p { font-size: .58rem; font-weight: 700; color: var(--ds-text-faint);
  font-variant-numeric: tabular-nums; }

/* =============================================================================
   LA BANQUE HEBDOMADAIRE — LE COMPOSANT DE RENDU D'UN OBJET
                                       (2026-08-12, ecran refondu le 08-13)
   -----------------------------------------------------------------------------
   ⚠️ CE QUI VIVAIT ICI A CHANGE DE PLACE. Ce bloc portait les QUATRE blocs de
   l'ancien ecran du Defi — vitrine, echelle, rattrapage, boutique. Le rattrapage
   n'existe plus, et les trois autres sont refondus dans « L'ECRAN DU DEFI — LA
   SCENE », juste dessous. Ne reste ici que ce qui n'appartient a aucun ecran : le
   MINI ECRAN d'un theme, composant de `UI.miniEcranHTML`, que la scene, le sac et
   les aperçus du passe se partagent.

   ⚠️ AUCUNE COULEUR D'OBJET N'EST ECRITE ICI, et ce n'est pas un detail : les
   teintes d'un revetement viennent de `ARMES.svg`, celles d'un theme de la table de
   jetons resolue posee EN LIGNE par `UI.miniEcranHTML`. Ce bloc ne pose que des
   jetons de role `--ds-*` — donc il suit le theme equipe, comme le reste de la page.

   ⚠️ LA RANGEE DE FILTRES DES MANQUES N'A AUCUNE REGLE ICI : elle reprend
   `sk-fil` / `sk-f` / `sk-f-n` / `sk-f-c`, celles de la rangee des familles de
   « Mon arme » et du filtre par mode des themes. Trois ecrans, une seule rangee :
   c'est ce qui garantit qu'ils vieilliront ensemble.
   ============================================================================= */

/* ---- LE MINI ECRAN D'UN THEME (composant de js/ui.js, `UI.miniEcranHTML`) ----
     Une maquette d'ecran de jeu : un fond, une carte bordee, un titre, deux lignes
     de texte, une jauge et un bouton. Toutes ses couleurs arrivent en style en
     ligne ; ce bloc ne donne que les FORMES et les proportions. */
.mec { position: relative; display: block; width: 100%; aspect-ratio: 3 / 2;
  border-radius: 12px; overflow: hidden; box-shadow: var(--ds-shadow-tile); }
.mec-c { position: absolute; left: 10%; right: 10%; top: 14%; bottom: 14%;
  border-radius: 8px; border: 1px solid; display: flex; flex-direction: column;
  justify-content: center; gap: 7%; padding: 7% 8%; }
.mec-t { display: block; height: 9%; min-height: 3px; width: 52%; border-radius: 2px; }
.mec-l { display: block; height: 5%; min-height: 2px; width: 86%; border-radius: 2px; opacity: .72; }
.mec-l2 { width: 64%; }
.mec-j { position: relative; display: block; height: 7%; min-height: 3px; width: 100%;
  border-radius: 99px; overflow: hidden; }
.mec-j i { position: absolute; inset: 0 38% 0 0; border-radius: 99px; }
.mec-b { position: relative; display: block; height: 16%; min-height: 6px; width: 54%;
  border-radius: 6px; }
.mec-b i { position: absolute; left: 16%; right: 16%; top: 38%; height: 24%;
  min-height: 2px; border-radius: 2px; opacity: .85; }
/* ⚠️ LE VOILE EST UNE PRIVATION DE COULEUR, PAS UN AUTRE DESSIN : on voit la forme
     de l'objet, jamais sa teinte. Le meme filtre sert aux deux natures — d'ou la
     regle jumelle `.bq-voile` plus bas pour l'arme. */
.mec-voile { filter: grayscale(1) contrast(.72) brightness(.92); }

/* =============================================================================
   L'ECRAN DU DEFI — LA SCENE                            (refonte 2026-08-12)
   -----------------------------------------------------------------------------
   ⚠️ C'EST UNE RUPTURE ASSUMEE AVEC LE RESTE DU JEU, QUI EST CLAIR. Le Defi est
   un lieu a part : fond presque noir, deux halos flous aux couleurs de l'objet de
   la SEMAINE, une trame diagonale et un vignettage. L'ambiance change donc chaque
   semaine, toute seule.

   ⚠️ `screen-defi` RESTE DANS `ECRANS_CLAIRS` (js/ui.js), et ce n'est pas une
   contradiction : cette table dit quel THEME la racine porte, elle ne dit rien de
   l'apparence d'un ecran. En l'y laissant, aucun des 37 themes ne peut repeindre
   la scene — elle a sa palette, ecrite ici, et elle est la meme pour tout le
   monde. C'est exactement ce que fait le mode « Carriere Coach » (`.mt-*`).

   ⚠️ AUCUNE COULEUR N'EST ECRITE ICI, ET C'EST UNE REGLE DU PROJET, PAS UN STYLE.
   Cinq groupes d'invariants (g30, g32, g34, g35, g40) balaient la feuille depuis
   leur marqueur JUSQU'A LA FIN DU FICHIER et refusent tout hexadecimal : une
   section ajoutee apres eux tombe donc sous leur regle, quelle qu'elle soit. La
   scene a SA palette — elle ne suit aucun des 37 themes —, mais cette palette vit
   dans UNE TABLE de js/main.js (`DF_SCENE`) et arrive ici EN LIGNE, en jetons
   `--df-*`. C'est exactement ce que fait le mode « Carriere Coach » avec sa table
   `COUL`. Une couleur ecrite ici serait une seconde verite, et un invariant la
   verrait.
   ⚠️ LES DEUX TEINTES DE L'OBJET (`--df-a`, `--df-b`) ARRIVENT PAR LE MEME CHEMIN,
   mais elles, `defiTeintes` les DEMANDE aux catalogues — les arrets de degrade
   d'un revetement, la table de jetons resolue d'un theme.

   ⚠️ LA TENUE EN UNE PAGE EST STRUCTURELLE. `.df` fait exactement la hauteur de la
   fenetre ; les blocs 1, 2, 4 et 5 ont leur hauteur propre et `flex: 0 0 auto`, et
   le bloc 3 prend CE QUI RESTE (`flex: 1 1 auto; min-height: 0`). Un bloc ajoute
   prendrait donc sa place a l'objet, jamais a la page.
   ⚠️ `overflow: hidden` SUR `.df` NE SERT PAS A FAIRE TENIR L'ECRAN — il sert au
   panneau du sac, qui attend hors champ sous le bord bas. S'il masquait un bloc,
   la mesure de hauteur le verrait quand meme : elle compare la hauteur de chaque
   bloc a la place offerte, pas le seul `scrollHeight`.
   ============================================================================= */

/* La scene occupe la page : ni titre d'ecran, ni rangee d'actions, ni marge. */
#screen-defi.screen { padding: 0; }
.df { position: relative; display: flex; flex-direction: column;
  height: 100dvh; min-height: 480px; overflow: hidden;
  background: var(--df-fond); color: var(--df-encre); }
/* Les navigateurs sans `dvh` retombent sur `vh` : la regle precedente reste. */
@supports not (height: 100dvh) { .df { height: 100vh; } }

/* LE FOND, EN DEUX COUCHES ET TROIS EFFETS. Les halos d'abord (flous, en couleur
   de l'objet), puis la trame diagonale et le vignettage par-dessus — l'ordre
   compte : une trame sous un flou de 40 px n'existerait plus. */
.df-fond { position: absolute; inset: 0; pointer-events: none; }
.df-fond::before {
  content: ""; position: absolute; inset: -25%;
  background:
    radial-gradient(34% 24% at 24% 20%, var(--df-a) 0%, transparent 64%),
    radial-gradient(42% 30% at 80% 76%, var(--df-b) 0%, transparent 68%);
  filter: blur(40px); opacity: .58;
}
.df-fond::after {
  content: ""; position: absolute; inset: 0;
  background:
    repeating-linear-gradient(135deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 8px),
    radial-gradient(125% 82% at 50% 40%, transparent 34%, rgba(0, 0, 0, .78) 100%);
}
.df-in { position: relative; z-index: 1; display: flex; flex-direction: column;
  height: 100%; gap: 8px; padding: 10px 14px 12px; }

/* ---- BLOC 1 : la ligne de titre et la fermeture ---- */
.df-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.df-t { font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(237, 234, 242, .48); }
.df-t-d { color: rgba(237, 234, 242, .9); }
.df-x { flex: 0 0 auto; width: 32px; height: 32px; padding: 0; border-radius: 99px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .06);
  color: rgba(237, 234, 242, .82); }
.df-x:active { transform: scale(.94); }

/* ---- BLOC 2 : la semaine, le nom, la pastille d'etat ----
   Le NOM en 38 points et la SEMAINE en 10 au-dessus : c'est le nom que le joueur
   vient chercher. Un nom long passe sur deux lignes — la place vient alors de
   l'objet, jamais de la page, et c'est ce que la mesure de hauteur verifie. */
.df-id { flex: 0 0 auto; }
.df-sem { margin: 0; font-size: 10px; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(237, 234, 242, .42); }
.df-nom { margin: 1px 0 0; font-size: 38px; line-height: 1.04; font-weight: 900;
  letter-spacing: -.02em; color: var(--df-blanc); }
.df-nom-t { text-shadow: 0 2px 18px rgba(0, 0, 0, .55); }
.df-p { display: inline-flex; align-items: center; vertical-align: middle;
  margin-left: 9px; padding: 3px 10px; border-radius: 99px;
  font-size: .64rem; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; }
.df-p-or { background: linear-gradient(180deg, var(--df-or-1), var(--df-or-2)); color: var(--df-or-encre); }
.df-p-no { background: rgba(216, 72, 63, .18); color: var(--df-alerte); box-shadow: 0 0 0 1px rgba(216, 72, 63, .4) inset; }
.df-p-en { background: rgba(255, 255, 255, .08); color: rgba(237, 234, 242, .74);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .14) inset; font-variant-numeric: tabular-nums; }

/* ---- BLOC 3 : l'objet, sur toute la place restante ----
   ⚠️ NI FLOU NI CADENAS : aucune regle de voile ici, et aucun appelant ne pose
   plus `.bq-voile`. On voit l'objet dans ses vraies couleurs, gagne ou non. */
.df-obj { flex: 1 1 auto; min-height: 0; display: flex; align-items: center;
  justify-content: center; }
.df-obj .bq-rendu { display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; }
.df-obj .bq-arme svg { width: 100%; height: auto; max-height: 100%; filter: drop-shadow(0 10px 26px rgba(0, 0, 0, .6)); }
/* Le mini ecran d'un theme se cale sur la HAUTEUR disponible : son rapport 3/2 lui
   donne alors sa largeur. Cale sur la largeur, il laissait la moitie du bloc vide. */
.df-obj .mec { width: auto; height: 100%; max-width: 100%;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .55); }
/* Gagne : un filet dore autour de l'objet. C'est le SEUL signal de possession du
   bloc 3, et il ne peut pas se confondre avec un etat de progression. */
.df-obj-or { border-radius: 18px; box-shadow: 0 0 0 2px rgba(199, 154, 50, .75) inset; }
.df-obj-plein { flex-direction: column; gap: 6px; }
.df-plein { font-size: 3rem; font-weight: 900; line-height: 1;
  background: linear-gradient(180deg, var(--df-or-1), var(--df-or-2));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.df-plein span { font-size: 1.6rem; }
.df-plein-n { margin: 0; font-size: .8rem; color: rgba(237, 234, 242, .6); text-align: center; }

/* LA RANGEE DES QUATRE ARMES — un revetement s'applique aux cinq armes, l'ecran
   ne peut pas n'en montrer qu'une. Elle ne parait QUE pour un revetement : ni
   pour un theme, ni pour les jetons (invariant). */
.df-armes { flex: 0 0 auto; display: flex; gap: 6px; justify-content: center; }
.df-a { flex: 0 1 auto; padding: 6px 11px; border-radius: 99px; cursor: pointer;
  font: inherit; font-size: .7rem; font-weight: 800; letter-spacing: .02em;
  border: 1px solid rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .05);
  color: rgba(237, 234, 242, .66); white-space: nowrap; }
.df-a.on { background: rgba(255, 255, 255, .93); color: var(--df-sur-clair); border-color: transparent; }

/* ---- BLOC 4 : UNE ligne d'etat, une seule ---- */
.df-etat { flex: 0 0 auto; margin: 0; text-align: center; font-size: .78rem;
  line-height: 1.4; color: rgba(237, 234, 242, .66); }
.df-etat-or { color: var(--df-or-1); }
.df-etat-ok { color: var(--df-vert); }
.df-etat-no { color: var(--df-alerte); }
.df-etat-cours { color: var(--df-encre); }

/* ---- BLOC 5 : la frise, le bouton, le sac ---- */
.df-bas { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; }
.df-fr { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(7, 1fr); gap: 4px; }
.df-f { position: relative; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; height: 34px; border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, .12); background: rgba(255, 255, 255, .04); }
.df-f-j { font-size: .6rem; font-weight: 900; line-height: 1; color: rgba(237, 234, 242, .42); }
.df-f-m { font-size: .68rem; font-weight: 900; line-height: 1; height: .72em;
  display: flex; align-items: center; color: transparent; }
/* Un jour FAIT : coche verte. */
.df-f-ok { background: rgba(64, 190, 120, .16); border-color: rgba(64, 190, 120, .48); }
.df-f-ok .df-f-j { color: var(--df-vert-clair); }
.df-f-ok .df-f-m { color: var(--df-vert-vif); }
/* AUJOURD'HUI : dore. Il ne dit pas « fait », il dit « c'est maintenant ». */
.df-f-now { border-color: rgba(240, 208, 137, .7); background: rgba(240, 208, 137, .1); }
.df-f-now .df-f-j { color: var(--df-or-1); }
/* Un jour MANQUE recule d'un plan, sans disparaitre : il fait partie du recit. */
.df-f-no { opacity: .38; }
/* LE SEPTIEME PORTE UN LOSANGE et jamais une coche : c'est lui qui donne l'objet,
   il ne peut pas ressembler aux six autres. Plein quand le jour est fait. */
.df-f-7 { border-color: rgba(240, 208, 137, .42); }
.df-f-7 .df-f-m { color: transparent; }
.df-f-7 .df-f-m::before { content: ""; display: block; width: 8px; height: 8px;
  transform: rotate(45deg); border: 1.6px solid rgba(240, 208, 137, .8); border-radius: 1px; }
.df-f-7.df-f-ok .df-f-m::before { background: var(--df-or-1); border-color: var(--df-or-1); }

.df-go { display: flex; gap: 8px; align-items: stretch; }
/* LE BOUTON PORTE LES TROIS CONTRAINTES DU JOUR, sur sa seconde ligne. Elles
   occupaient trois pastilles ; elles se lisent ici, juste avant de lancer. */
.df-go-b { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px; cursor: pointer;
  font: inherit; padding: 9px 12px; border: none; border-radius: 14px;
  background: linear-gradient(180deg, var(--df-or-1), var(--df-or-2)); color: var(--df-or-encre);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .45); }
.df-go-b:active { transform: scale(.985); }
.df-go-t { font-size: 1rem; font-weight: 900; letter-spacing: .02em; line-height: 1.15; }
.df-go-s { max-width: 100%; font-size: .66rem; font-weight: 700; line-height: 1.2; opacity: .8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Deja joue : le bouton n'invite plus, il rend compte. */
.df-go-fait { background: rgba(255, 255, 255, .07); color: var(--df-encre);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .16) inset; }
.df-sac { position: relative; flex: 0 0 auto; width: 54px; border-radius: 14px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .06);
  color: rgba(237, 234, 242, .86); }
.df-sac:active { transform: scale(.96); }
/* LA PASTILLE PORTE LE NOMBRE, jamais un point : un chiffre dit s'il vaut la peine
   d'ouvrir. Le cerne sombre la detache du bouton, comme la notification des badges. */
.df-sac-n { position: absolute; top: -6px; right: -6px; min-width: 20px; height: 20px;
  padding: 0 5px; border-radius: 99px; display: inline-flex; align-items: center;
  justify-content: center; font-size: .64rem; font-weight: 900;
  background: var(--df-alerte-fond); color: var(--df-blanc); border: 2px solid var(--df-fond); }
/* LA LIGNE DES MEDAILLES — discrete, et c'est tout ce qu'il en reste ici. */
.df-med { align-self: center; padding: 1px 6px; border: none; background: none; cursor: pointer;
  font: inherit; font-size: .68rem; font-weight: 800; letter-spacing: .05em;
  color: rgba(237, 234, 242, .44); text-decoration: underline; text-underline-offset: 3px; }
.df-med:hover { color: rgba(237, 234, 242, .8); }

/* ---- LE SAC : LA BOUTIQUE, EN PANNEAU GLISSANT PAR LE BAS ----
   ⚠️ SA LISTE DEFILE A L'INTERIEUR, ET L'ECRAN NON. A 51 objets manques — le
   maximum possible — aucune mise en page ne tient en une page ; c'est le panneau
   qui defile, pas la scene, exactement comme le mur des distinctions defile dans
   son ecran. `.df` porte `overflow: hidden` : le panneau ferme attend hors champ
   sous le bord bas et n'allonge jamais la page. */
.df-pan { position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; flex-direction: column; max-height: 80%;
  padding: 12px 14px 16px; border-radius: 20px 20px 0 0;
  background: rgba(15, 14, 20, .975); border-top: 1px solid rgba(255, 255, 255, .14);
  box-shadow: 0 -18px 44px rgba(0, 0, 0, .6);
  transform: translateY(102%); transition: transform .26s cubic-bezier(.22, .9, .3, 1); }
.df-pan.on { transform: none; }
@media (prefers-reduced-motion: reduce) { .df-pan { transition: none; } }
.df-pan-h { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
.df-pan-t { flex: 1 1 auto; font-size: .9rem; font-weight: 900; color: var(--df-encre); }
.df-pan-s { flex: 0 0 auto; font-size: .84rem; font-weight: 900; color: var(--df-or-1);
  font-variant-numeric: tabular-nums; }
.df-pan-s span { font-size: .74rem; }
/* LA REGLE EN UNE PHRASE, lue dans data/defi.json. Depuis la suppression du
   rattrapage, c'est la seule chose que le systeme ait a dire. */
.df-pan-r { flex: 0 0 auto; margin: 6px 0 10px; font-size: .74rem; line-height: 1.4;
  color: rgba(237, 234, 242, .6); }
.df-pan-v { margin: 6px 0 0; font-size: .78rem; line-height: 1.45; color: rgba(237, 234, 242, .6); }
.df-pan .bq-liste { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 2px; }
/* La rangee de filtres est celle de « Mon arme » : on ne redessine que ses tons,
   la scene etant sombre. Aucune FORME n'est reprise ici. */
.df-pan .sk-fil { flex: 0 0 auto; }
.df-pan .sk-f { background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .12);
  color: rgba(237, 234, 242, .68); }
.df-pan .sk-f.on { background: rgba(255, 255, 255, .93); border-color: transparent; color: var(--df-sur-clair); }
.df-pan .sk-f-c { color: inherit; opacity: .7; }
.df-pan .bq-l { background: rgba(255, 255, 255, .055); box-shadow: none;
  border: 1px solid rgba(255, 255, 255, .1); }
.df-pan .bq-l-n { color: var(--df-encre); }
.df-pan .bq-l-s { color: rgba(237, 234, 242, .46); }
.df-pan .btn-ghost { color: rgba(237, 234, 242, .5); border-color: rgba(255, 255, 255, .14); }

/* ---- CE QUI RESTE DE L'ANCIEN ECRAN, ET POURQUOI ----
   `.bq-rendu` / `.bq-arme` / `.bq-theme` sont le COMPOSANT de rendu d'un objet de
   banque : la scene et le sac s'en servent tous les deux, ils restent.
   `.bq-liste` / `.bq-l*` sont la LISTE des objets manques : elle a change de
   contenant, pas de forme.
   ⚠️ `.bq-voile` EST CONSERVE SANS APPELANT, comme chemin de rollback — c'est la
   meme regle que `.dse-plus` et le CSS mort du calendrier. Le retirer demanderait
   de rouvrir la decision « l'objet n'est plus voile », qui est prise. */
.bq-rendu { display: block; line-height: 0; }
.bq-arme svg { max-width: 100%; height: auto; }
.bq-voile { filter: grayscale(1) contrast(.72) brightness(.92); }

.bq-liste { list-style: none; margin: 10px 0 0; padding: 0; display: flex;
  flex-direction: column; gap: 7px; }
.bq-l { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: var(--ds-radius-tile); background: var(--ds-card);
  box-shadow: var(--ds-shadow-tile); }
.bq-l-ap { flex: 0 0 62px; width: 62px; line-height: 0; }
.bq-l-ap .bq-theme, .bq-l-ap .bq-arme { display: block; width: 100%; }
.bq-l-t { flex: 1 1 auto; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.bq-l-n { font-size: .86rem; font-weight: 800; color: var(--ds-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bq-l-s { font-size: .7rem; font-weight: 700; color: var(--ds-text-faint); }
.bq-l .btn { flex: 0 0 auto; white-space: nowrap; }

/* =============================================================================
   LES VINGT MEDAILLES DU DEFI ET L'EMPLACEMENT DE L'EN-TETE      (2026-08-12)
   -----------------------------------------------------------------------------
   Trois blocs, et ils ne se melangent pas : la PIECE elle-meme (`dsd-*`), le MUR
   qui la montre — CINQUIEME ONGLET DE PROGRESSION depuis le 2026-08-12 (`pgm-*`,
   il vivait en pied de l'ecran du Defi sous le prefixe `bq-med-*`) —, et
   l'EMPLACEMENT UNIQUE de l'en-tete de carriere (`hud-porte`).

   ⚠️ AUCUNE COULEUR DE METAL ICI. Les quatre metaux vivent dans `DSE_METAUX`
   (js/ui.js) et sont peints dans le SVG : la feuille de style n'en connait pas
   un hexadecimal, exactement comme pour les ecussons et les medaillons. Ce qui
   est ici est de la MISE EN PAGE, plus le balayage du reflet.
   ============================================================================= */

/* ---- 1. LA PIECE ---- */
.dsd { display: inline-flex; align-items: center; justify-content: center; line-height: 0; flex: 0 0 auto; }
.dsd svg { display: block; }
/* LE REFLET BALAYANT. Il traverse la piece en diagonale et s'arrete net en haut
   a gauche — c'est le dessin qui porte l'arete, pas ce balayage. Meme cadence et
   meme respect du mouvement reduit que le reflet des ecussons. */
.dsd-shine {
  pointer-events: none;
  transform-box: fill-box; transform-origin: center;
  animation: dsd-reflet 6.2s ease-in-out infinite;
}
@keyframes dsd-reflet {
  0%    { transform: translate(-130%, -130%); }
  24%   { transform: translate(130%, 130%); }
  100%  { transform: translate(130%, 130%); }
}
.dsd-lock .dsd-shine { animation: none; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .dsd-shine { animation: none; opacity: 0; }
}

/* ---- 2. LE MUR DES VINGT — CINQUIEME ONGLET DE PROGRESSION  (2026-08-12) ----
   ⚠️ IL A CHANGE D'ECRAN, ET LA GRILLE AVEC LUI. En pied du Defi il tenait en
   deux colonnes de 150 px, chacune portant le nom ET la phrase ET un bouton :
   vingt tuiles faisaient quatre ecrans de defilement, sous un ecran qui doit
   tenir en une page. Ici, dans un ecran de collection, il passe en QUATRE
   COLONNES et la tuile se reduit a la piece et au nom — la condition s'obtient
   en touchant une medaille verrouillee, et le bouton disparait : LA TUILE EST LE
   BOUTON. Mesure a 390 px : 4 colonnes = 82 px de tuile, la piece a 58 px y
   garde sa gravure lisible (le plancher mesure est 26 px). */
.pgm { display: block; }
.pgm-vide { margin: 0 0 14px; padding: 12px 14px; border-radius: var(--ds-radius-tile);
  background: var(--ds-field-bg); font-size: .8rem; line-height: 1.45; color: var(--ds-text-dim); }
/* LA MEDAILLE PORTEE, EN TETE ET EN GRAND — avec sa condition et le seul bouton
   de l'onglet. C'est la reponse a « qu'est-ce que je porte ? », sans avoir a
   chercher la tuile marquee dans le mur. */
.pgm-porte { display: flex; align-items: center; gap: 12px; margin: 0 0 14px;
  padding: 12px 14px; border-radius: var(--ds-radius-card);
  background: var(--ds-card); box-shadow: var(--ds-shadow-tile);
  border: 1px solid var(--ds-accent); }
.pgm-porte-t { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pgm-porte-k { font-size: .62rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-accent-deep); }
.pgm-porte-n { font-size: .96rem; font-weight: 900; color: var(--ds-text); }
.pgm-porte-p { font-size: .74rem; line-height: 1.35; color: var(--ds-text-faint); }
.pgm-porte .btn { flex: 0 0 auto; }

.pgm-mur { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-top: 12px; }
.pgm-c { display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 9px 4px 8px; text-align: center; cursor: pointer; font: inherit;
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  border: 1px solid var(--ds-line); box-shadow: var(--ds-shadow-tile); }
.pgm-c:active { transform: scale(.97); }
/* Une medaille GAGNEE se distingue par son cadre, jamais par sa piece : la piece
   dit deja tout, c'est le metal qui a change. Les VERROUILLEES restent en gris —
   c'est le metal `lock`, pose par le dessin, pas un filtre applique ici. */
.pgm-c-eu { border-color: var(--ds-accent); }
/* … et celle qui est PORTEE par un filet plein, la meme marque que le mur des
   distinctions emploie pour l'ecu porte. */
.pgm-c-on { border-color: var(--ds-accent); box-shadow: 0 0 0 2px var(--ds-accent-soft-bg), var(--ds-shadow-tile); }
.pgm-c-n { font-size: .64rem; font-weight: 800; line-height: 1.2; color: var(--ds-text-faint);
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.pgm-c-eu .pgm-c-n { color: var(--ds-text); }

/* ---- 2 bis. LES DEUX SECTIONS DE L'ONGLET ---- (2026-08-17)
   ⚠️ DEUX FAMILLES, DEUX TITRES, DEUX COMPTEURS. Les medailles du Defi viennent
   du profil, les pieces de saison viendront du passe : melangees dans une seule
   grille, on ne saurait plus ce qui vient d'ou. Le titre porte le compteur de SA
   famille, et ce compteur est calcule dans js/main.js sur SON catalogue — aucun
   nombre d'objets n'est ecrit dans cette feuille. */
.pgm-sec { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin: 18px 0 0; padding: 0 2px 6px; border-bottom: 1px solid var(--ds-line); }
.pgm-sec-t { font-size: .72rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-accent-deep); }
.pgm-sec-c { font-size: .74rem; font-weight: 900; color: var(--ds-text-dim); }
/* Le premier titre suit la carte « portee » ou son message, qui portent deja
   leur marge basse : il ne redouble pas l'ecart. */
.pgm-porte + .pgm-sec, .pgm-vide + .pgm-sec { margin-top: 4px; }

/* LA TUILE D'UNE PIECE — ⚠️ SON DESSIN NE VIT PAS ICI. Depuis le 2026-08-18 la
   tuile demande sa piece a `UI.pieceHTML`, la seule porte de rendu, celle par ou
   passe aussi l'emplacement de l'en-tete : cette feuille n'a plus rien a dire du
   dessin, et il n'y a plus de place reservee a tenir de deux cotes. Ce n'est
   toujours pas un bouton : rien ne s'attribue encore, donc rien ne se porte. */
.pgm-p { display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 9px 4px 8px; text-align: center;
  background: var(--ds-card); border-radius: var(--ds-radius-tile);
  border: 1px solid var(--ds-line); box-shadow: var(--ds-shadow-tile); }
/* ⚠️ `.dsp` NE PEINT RIEN, ET C'EST STRUCTUREL : le dore d'une piece est une
   signature du jeu, comme les quatre metaux, et il reste HORS DE PORTEE DES
   THEMES. Il vit dans `DSE_METAUX` (js/ui.js) et nulle part ailleurs — pas une
   couleur de piece n'est ecrite dans cette feuille. La regle n'ajoute que la
   mise en boite ; la taille, elle, se pose en ligne sur le SVG. */
.dsp { display: inline-flex; align-items: center; justify-content: center;
  line-height: 0; flex: 0 0 auto; }
.dsp svg { display: block; }
/* ⚠️ LA MARQUE D'UN OBJET PORTE INTROUVABLE. Elle n'est PAS la place reservee :
   une place reservee dit « ça viendra », celle-ci dit « quelque chose est porte
   que plus rien ne connait ». Elle prend la couleur d'alerte du theme courant —
   jamais un hexadecimal ecrit ici — et reste lisible sur les douze thèmes. */
.dsx { display: inline-flex; align-items: center; justify-content: center;
  line-height: 0; flex: 0 0 auto; color: var(--ds-alerte); }
.dsx svg { display: block; }
.pgm-p-n { font-size: .64rem; font-weight: 800; line-height: 1.2; color: var(--ds-text);
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.pgm-p-s { font-size: .58rem; font-weight: 700; line-height: 1.2; color: var(--ds-text-faint);
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
/* ⚠️ « A VENIR » N'EST PAS UNE ALERTE : neuf pieces existent pour deux saisons
   ouvertes, et c'est l'etat voulu. La marque sert a le RELEVER — un invariant
   la cherche —, pas a crier : elle se contente d'italique. */
.pgm-p-s-att { font-style: italic; }
/* L'ETAT DE LA PIECE — ⚠️ C'EST LUI, ET LUI SEUL, QUI DIT « GAGNEE » OU « A
   GAGNER ». Les neuf sont en or dans les deux cas : le metal ne porte aucune
   echelle entre elles, il est la signature de la famille. */
.pgm-p-e { font-size: .55rem; font-weight: 900; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.pgm-p.pgm-c-eu .pgm-p-e { color: var(--ds-accent-deep); }

/* ---- 3. L'EMPLACEMENT UNIQUE DE L'EN-TETE ---- */
/* ⚠️ SON `flex-shrink` EST LE POINT DE TOUTE CETTE REGLE, ET IL EST MESURE.
   A 390 px la capsule offre 328 px utiles, DEJA entierement pris : le nom
   d'organisation y est tronque des le pseudo ordinaire. Les 32 px d'un
   emplacement se prelevent donc integralement sur le couple pseudo /
   organisation, et l'ordre de cession decide qui paie.

   Trois valeurs essayees, pseudo VISIBLE mesure dans le pire cas du jeu
   (pseudo de 16 caracteres + organisation de 22, a 390 px) :

     flex-shrink de l'emplacement   pseudo visible   emplacement
        0      (ne cede jamais)         71 px          entier      -> REFUSE
      100      (cede apres l'org)      108 px          replie
    10000      (cede avec l'org)       111 px          replie

   0 est REFUSE : il fait tomber le pseudo sous le plancher de lisibilite de
   100 px que `verif-ecussons-ui.js` exige, et un ornement ne coute jamais une
   information. 10000 le ferait ceder EN MEME TEMPS que le nom d'organisation,
   donc dans des cas ou la place existe encore. 100 le place exactement ou il
   doit etre : l'organisation se replie d'abord jusqu'a son plancher de 4ch,
   l'emplacement ensuite, le pseudo en DERNIER et jamais sous son seuil.

   ⚠️ ET LE REPLI EST PROGRESSIF, PAS UN ROGNAGE. Les deux regles ci-dessous
   rendent au SVG une largeur RELATIVE : la piece se met a l'ECHELLE quand la
   boite retrecit, au lieu d'etre coupee a droite. Sans elles, un emplacement a
   mi-largeur montrait une DEMI-medaille, ce qui est pire qu'une medaille
   absente. Au bout du repli la boite vaut zero et l'emplacement disparait
   proprement : dans le pire cas du jeu (pseudo de 16 caracteres + organisation
   de 22, a 390 px), c'est exactement ce qui arrive, et le pseudo garde ses
   107 px — au-dessus de son plancher. */
/* ⚠️ `flex-shrink: 0` DEPUIS LE 2026-08-12, ET C'EST UN CHANGEMENT D'ARBITRAGE.
   Il valait 100 : l'emplacement cedait apres l'organisation et avant le pseudo,
   en se repliant progressivement. Mesure faite depuis : sur le pire cas du jeu
   il ne se repliait pas, il TOMBAIT A ZERO — donc l'ornement disparaissait, et
   sa zone tapable avec lui. Un dessin n'a pas de demi-lecture. Il ne cede donc
   plus rien ; c'est le nom d'organisation qui cede a sa place (voir le plancher
   conditionnel, plus haut), et le pseudo reste protege. */
.hud-porte { flex: 0 0 auto; min-width: 0; overflow: hidden; display: inline-flex; align-items: center; }
.hud-porte .dse, .hud-porte .dsd, .hud-porte .dsp, .hud-porte .dsx { flex: 0 1 auto; max-width: 100%; }
.hud-porte .dse svg, .hud-porte .dsd svg, .hud-porte .dsx svg { width: 100%; height: auto; }
/* Le separateur « · », dessine en `::before` comme ceux de l'age, du blason et
   du rang VRS : c'est une ponctuation, elle n'a pas a etre lue ni copiee. */
html.theme-clair .hud-pill .hud-porte::before {
  content: "·"; margin: 0 5px 0 3px; color: var(--ds-text-dim); opacity: .55; font-weight: 400;
}

/* ---- 4. L'ECU PORTE, MARQUE SUR LE MUR DES DISTINCTIONS ---- */
/* Le mur doit dire lequel des ecus est a l'en-tete, sinon le joueur doit ouvrir
   les cases une par une pour le retrouver. Meme marque que la tuile portee du
   mur des medailles, pour que les deux collections se lisent pareil. */
.dst-case-on { border-radius: var(--ds-radius-tile); box-shadow: 0 0 0 2px var(--ds-accent); }

/* =============================================================================
   LES TROIS ZONES TAPABLES DE L'EN-TETE ET LEUR PANNEAU          (2026-08-12)
   -----------------------------------------------------------------------------
   ⚠️ LES ZONES NE CHANGENT PAS D'UN PIXEL LA MISE EN PAGE DE LA PASTILLE, et
   c'est la contrainte de tout ce bloc : le plancher de lisibilite du pseudo
   (100 px, `verif-ecussons-ui.js`) et l'ordre de cession de la place sont mesures
   sur elle. Une zone tapable n'ajoute donc NI marge, NI rembourrage, NI bordure —
   seulement un curseur, un anneau de focus et un tres leger fond au contact.
   ============================================================================= */
.hud-z { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.hud-z:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; border-radius: 6px; }
.hud-z:active { opacity: .72; }

/* LE PANNEAU. Il vit hors des ecrans, il couvre donc la page entiere ; sa feuille
   glisse par le bas, comme le sac du Defi — un seul geste, appris une fois. */
.hp { position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
  justify-content: flex-end; }
.hp[hidden] { display: none; }
.hp-fond { position: absolute; inset: 0; background: rgba(10, 9, 14, .5);
  opacity: 0; transition: opacity .22s ease; }
.hp.on .hp-fond { opacity: 1; }
.hp-in { position: relative; display: flex; flex-direction: column; max-height: 86dvh;
  padding: 12px 16px 20px; border-radius: 20px 20px 0 0;
  background: var(--ds-bg-1); color: var(--ds-text);
  box-shadow: 0 -18px 44px rgba(0, 0, 0, .35);
  transform: translateY(102%); transition: transform .26s cubic-bezier(.22, .9, .3, 1); }
.hp.on .hp-in { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .hp-in, .hp-fond { transition: none; }
}
.hp-h { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.hp-t { flex: 1 1 auto; font-size: .95rem; font-weight: 900; color: var(--ds-text); }
.hp-x { flex: 0 0 auto; width: 32px; height: 32px; padding: 0; border-radius: 99px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ds-line); background: var(--ds-field-bg); color: var(--ds-text-dim); }
.hp-corps { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-top: 6px; }
.hp-lab { margin: 14px 0 7px; font-size: .64rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.hp-lab b { font-size: .78rem; letter-spacing: 0; color: var(--ds-text-dim); font-variant-numeric: tabular-nums; }
.hp-vide { margin: 0; padding: 11px 13px; border-radius: var(--ds-radius-tile);
  background: var(--ds-field-bg); font-size: .78rem; line-height: 1.45; color: var(--ds-text-dim); }
.hp-note { margin: 0 0 10px; font-size: .74rem; line-height: 1.4; color: var(--ds-text-faint); }
.hp-off { margin-bottom: 4px; }
/* ⚠️ LA PHRASE D'UN OBJET PORTE INTROUVABLE. Elle reprend le bloc `.hp-vide` —
   meme boite, meme respiration — et n'ajoute que la couleur d'alerte du theme
   courant : ce n'est pas une section vide de plus, c'est un etat a defaire. */
.hp-orph { margin-bottom: 4px; color: var(--ds-alerte); border: 1px solid var(--ds-alerte); }

/* ---- Panneau 1 : l'apercu du VRAI pseudo, puis les cinq paliers ---- */
.hp-ap { display: flex; flex-direction: column; gap: 2px; align-items: center;
  padding: 14px 12px; border-radius: var(--ds-radius-card);
  background: var(--ds-field-bg); }
.hp-ap-k { font-size: .62rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ds-text-faint); }
.hp-ap-n { font-size: 1.7rem; font-weight: 900; line-height: 1.2; }
.hp-ren { margin-top: 9px; }
.hp-bri { display: flex; flex-direction: column; gap: 6px; }
.hp-b { display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 10px; text-align: left; cursor: pointer; font: inherit;
  padding: 10px 12px; border-radius: var(--ds-radius-tile);
  background: var(--ds-card); border: 1px solid var(--ds-line);
  box-shadow: var(--ds-shadow-tile); }
/* Un palier NON GAGNE reste montre — il dit ce qu'il y a a chercher — mais il
   recule d'un plan et ne se prend pas. */
.hp-b[disabled] { cursor: default; opacity: .5; box-shadow: none; }
.hp-b-on { border-color: var(--ds-accent); box-shadow: 0 0 0 2px var(--ds-accent-soft-bg), var(--ds-shadow-tile); }
.hp-b-n { font-size: 1rem; font-weight: 900; }
.hp-b-c { font-size: .72rem; line-height: 1.3; color: var(--ds-text-faint); }
.hp-b-e { font-size: .6rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ds-text-faint); white-space: nowrap; }
.hp-b-e-on { color: var(--ds-accent-deep); }

/* ---- Panneau 2 : les deux collections, en grille ---- */
.hp-grille { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.hp-o { display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 9px 4px 8px; cursor: pointer; font: inherit; text-align: center;
  background: var(--ds-card); border: 1px solid var(--ds-line);
  border-radius: var(--ds-radius-tile); box-shadow: var(--ds-shadow-tile); }
/* Un objet DEJA EXPOSE ailleurs sur la carte d'identite reste montre — il dit ou
   il est, par son infobulle et par la phrase sous la grille — mais il ne se prend
   pas : il faut le retirer de la ou il est. Meme facture que le palier non gagne
   du panneau 1 et que la grille eteinte de « Mon arme ». */
.hp-o[disabled] { cursor: default; opacity: .38; filter: grayscale(1); box-shadow: none; }
.hp-o-on { border-color: var(--ds-accent); box-shadow: 0 0 0 2px var(--ds-accent-soft-bg), var(--ds-shadow-tile); }
.hp-o-n { font-size: .62rem; font-weight: 800; line-height: 1.2; color: var(--ds-text-faint);
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.hp-o-on .hp-o-n { color: var(--ds-text); }

/* ---- Panneau 3 : les huit premieres equipes ---- */
.hp-vrs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.hp-v { display: grid; grid-template-columns: 26px 22px 1fr auto auto; align-items: center;
  gap: 9px; padding: 7px 10px; border-radius: var(--ds-radius-tile);
  background: var(--ds-card); box-shadow: var(--ds-shadow-tile); }
/* L'equipe du joueur se repere sans etre cherchee. */
.hp-v-mien { box-shadow: 0 0 0 1.5px var(--ds-accent) inset, var(--ds-shadow-tile); }
.hp-v-r { font-size: .84rem; font-weight: 900; color: var(--ds-text-faint);
  font-variant-numeric: tabular-nums; text-align: right; }
.hp-v-e { line-height: 0; }
.hp-v-n { font-size: .84rem; font-weight: 800; color: var(--ds-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-v-p { font-size: .76rem; font-weight: 700; color: var(--ds-text-dim);
  font-variant-numeric: tabular-nums; }
/* LE MOUVEMENT. ⚠️ UN RANG QUI BAISSE EST UNE MONTEE : le vert dit « + », donc
   « le nombre a diminue ». Le signe est calcule dans js/main.js, pas ici. */
.hp-v-up, .hp-v-dn, .hp-v-0 { font-size: .7rem; font-weight: 900; min-width: 26px;
  text-align: right; font-variant-numeric: tabular-nums; }
.hp-v-up { color: var(--ds-good-ink); }
.hp-v-dn { color: var(--ds-warn-ink); }
.hp-v-0 { color: var(--ds-text-faint); }

/* =============================================================================
   LE TABLEAU DE FIN DE SAISON — UNE SCENE PLEIN ECRAN, DU TEXTE, DEUX BOUTONS
   (2026-08-12, calage plein ecran du 2026-08-13)

   Il s'intercale entre la derniere decision de l'annee et le bilan. C'est un
   VOILE POSE PAR-DESSUS, pas un ecran : `#screen-season` reste l'ecran actif
   dessous, le bilan y est deja rendu, et refermer le tableau ne fait rien
   d'autre que le decouvrir. Rien n'est sauvegarde, rien n'est calcule ici.

   ⚠️ LA SCENE OCCUPE MAINTENANT LES 844 px, ET LE RAPPORT 390 x 300 A SAUTE. Elle
   etait dessinee dans un cadre de 390 x 300 et posee telle quelle au milieu de
   l'ecran : elle occupait une BANDE, laissait deux vides colores au-dessus et en
   dessous, et le sujet finissait masque par le texte et les boutons. Le viewBox
   monte a 0 0 390 844, le dessin est agrandi de 40 % et remonte, et le sol est
   prolonge jusqu'au bas de l'ecran. ⚠️ LE CALAGE N'EST PAS ICI : ses trois nombres
   vivent dans `TABLEAU.CALAGE` (js/tableau.js) et nulle part ailleurs. Le
   recadrage lateral de 20 % est VOULU.

   ⚠️ LE TEXTE ET LES DEUX BOUTONS FLOTTENT SUR L'ILLUSTRATION — ils ne sont plus
   poses sous elle sur un fond vide. Les trois calques (`.scrim`, `.txt`, `.act`)
   sont donc en absolu dans `.tb`, qui est le seul bloc positionne du voile.

   ⚠️ LE VOILE REDEVIENT UN CALQUE FIXE (`.scrim`, 42 % du bas), ET C'EST UN
   RENVERSEMENT ASSUME. Il etait porte par le bloc de texte lui-meme, ce qui
   garantissait STRUCTURELLEMENT 96 % d'opacite sous chaque ligne ; une version
   encore anterieure posait un voile fixe sur 38 % et AVALAIT le sujet de la
   plupart des dessins. Ce qui a change entre-temps : les sujets sont desormais
   tous au-dessus de 560 px et le tiers inferieur est libre, si bien que le voile
   ne monte plus sur eux. LA GARANTIE N'EST DONC PLUS STRUCTURELLE MAIS MESUREE :
   `verif-tableau.js` lit le contraste reel du titre et de la phrase sur les
   dix-neuf scenes, aux deux largeurs, et exige 4,5:1. Ne pas retirer cette mesure.

   ⚠️ EXCEPTION HEXADECIMALE DECLAREE, ET BORNEE A CINQ REGLES. Deux controles
   (g30 « ecran Progression » et g32 « Palmares / Comment ca marche ») lisent la
   feuille DE LEUR MARQUEUR JUSQU'A LA FIN DU FICHIER et echouent sur le moindre
   `#rrggbb`. Les cinq regles de texte et de boutons ci-dessous en portent, parce
   que la commande les fournit VERBATIM et que le tableau n'est pas un ecran
   themable : c'est un voile toujours sombre, dont les couleurs ne viennent
   d'aucun des 37 themes. L'exception suit le mecanisme deja en place pour le fond
   de nuit de la vitrine (`TABLEAU_REGLES` a cote de `VITRINE_REGLES` dans
   suite.js) : les cinq regles sont RETIREES DE LA LECTURE, nommees une par une,
   et un controle dedie (g57) verifie que l'exception ne contient rien d'autre.
   ⚠️ TOUT HEXADECIMAL ECRIT AILLEURS DANS CE BLOC RESTE VU.

   Les trois couleurs de la scene, elles, arrivent toujours EN LIGNE depuis
   js/tableau.js dans `--tb-a` / `--tb-b` / `--tb-c` — c'est ce qui permet a la
   teinte de deriver du resultat de la saison, et la feuille n'en connait aucune.
   ============================================================================= */
.tb { position: fixed; inset: 0; z-index: 70; overflow: hidden;
  background: linear-gradient(to bottom, var(--tb-a, rgba(24, 22, 32, 1)) 0%,
    var(--tb-b, rgba(16, 15, 22, 1)) 52%, var(--tb-c, rgba(10, 9, 14, 1)) 100%);
  opacity: 0; transition: opacity .22s ease; }
.tb[hidden] { display: none; }
.tb.on { opacity: 1; }

/* LA SCENE. Elle remplit le voile, et son SVG porte deja le rapport : il n'y a
   plus ni `aspect-ratio`, ni conteneur intermediaire a centrer. */
#tab-art { position: absolute; inset: 0; }
.fond { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ------------------------------------------------------------------------------
   LES CINQ REGLES DE L'EXCEPTION HEXADECIMALE DECLAREE CI-DESSUS.
   Reprises VERBATIM de la commande. Ne pas y substituer de jetons : le tableau
   n'est pas un ecran themable, et ces valeurs sont celles de la maquette.
   ------------------------------------------------------------------------------ */
.scrim{position:absolute;left:0;right:0;bottom:0;height:42%;
 background:linear-gradient(180deg,rgba(6,9,17,0),rgba(6,9,17,.42) 36%,rgba(6,9,17,.82) 68%,rgba(6,9,17,.94))}
/* ⚠️ LE PLATEAU LOCAL — LA SEULE MODIFICATION DES CINQ REGLES VERBATIM, ET ELLE
   EST MESUREE (2026-08-13, decision 17 tranchee). Le calque fixe seul faisait
   tomber le contraste du sur-titre a 2,45:1 contre les 4,5 exiges. LES TROIS
   LEVIERS ANNONCES ONT ETE MESURES ET AUCUN NE CONVIENT : renforcer les arrets
   plafonne a 3,35:1 ; monter le calque a 75 % passe (5,32:1) mais eteint la
   bande du sujet de 66 % — c est le defaut « le voile avale le dessin » ; et
   DESCENDRE LE TEXTE EST NUISIBLE — a 110 px le bloc tombe sur les boutons et la
   phrase se retrouve sur le degrade dore de « Voir le bilan » : 1,17:1.
   CE QUI EST FAIT A LA PLACE : le bloc de texte porte SON PROPRE plateau. Il
   descend jusqu en bas et rend par `padding-bottom` la place qu il occupait —
   LE TEXTE NE BOUGE PAS D UN PIXEL, son aplomb reste les memes 150 px, qui sont
   desormais ecrits dans le `padding` et lus la par g55.
   ⚠️ 82 % N EST PAS UN REGLAGE A L OEIL : c est la plus petite opacite pour
   laquelle un pixel BLANC PUR sous le sur-titre tient encore 4,5:1 (4,99:1
   mesure). La garantie redevient donc STRUCTURELLE — vraie quel que soit le
   dessin, quelle que soit la hauteur du bloc, et SANS rien devoir au `.scrim`.
   ⚠️ Le fondu se termine sur une longueur EN PIXELS, egale au `padding-top`,
   donc exactement au-dessus du sur-titre. Ecrit en POURCENTAGE il couvrirait la
   premiere ligne et ne servirait a rien : mesure, 2,45:1 inchange.
   `.act` vient APRES dans le document : les deux boutons restent au-dessus du
   plateau, et cliquables. */
.txt{position:absolute;left:0;right:0;bottom:0;padding:44px 24px 150px;
 background:linear-gradient(180deg,rgba(6,9,17,0),rgba(6,9,17,.82) 44px,rgba(6,9,17,.82) 100%)}
.txt .kk {font-size:10px;font-weight:800;letter-spacing:.22em;text-transform:uppercase;color:#93A6CC}
.txt .tt {font-size:34px;font-weight:800;color:#fff;line-height:1.05;margin-top:8px;letter-spacing:-.6px}
.txt .st {font-size:14px;font-weight:650;color:#C2CEE4;line-height:1.5;margin-top:11px}
.act{position:absolute;left:0;right:0;bottom:0;padding:0 20px 22px;display:flex;flex-direction:column;gap:9px}
.act .go {border:none;font-family:inherit;font-size:16px;font-weight:800;border-radius:16px;padding:16px;
 background:linear-gradient(180deg,#F7DA9B,#DFA62E);color:#241A03;cursor:pointer;
 box-shadow:0 8px 22px rgba(0,0,0,.34)}
.act .sk {border:1.6px solid rgba(255,255,255,.22);background:rgba(255,255,255,.06);font-family:inherit;
 font-size:14px;font-weight:800;border-radius:15px;padding:13px;color:#C2CEE4;cursor:pointer;
 backdrop-filter:blur(4px)}

/* Le titre et la phrase sont des elements de texte du jeu : ils gardent la marge
   nulle que le reste de la feuille leur donne, sinon un `<h2>` et un `<p>`
   ajouteraient la leur par-dessus les `margin-top` ci-dessus. */
.txt .tt, .txt .st { margin-bottom: 0; }
.txt .tt { margin-left: 0; margin-right: 0; }
.txt .kk { display: block; }

/* Le bas de l'ecran respecte l'encoche : la marge de 22 px de `.act` est un
   plancher, jamais un plafond. */
@supports (padding: max(0px)) {
  .act { padding-bottom: max(22px, env(safe-area-inset-bottom)); }
}
