/* Design tokens (--bg-deep, --gold, --radius-btn, etc.) now live exclusively
   in tokens.css, loaded before this file. See tokens.css header for the
   cascade contract. --radius-btn resolves to --radius-md (12px) here. */

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* Accessibilité : Indicateurs de Focus */
:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 4px;
    box-shadow: 0 0 20px var(--gold-glow);
    border-radius: var(--radius-btn);
    transition: outline-offset var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}

/* Visually hidden but screen-reader accessible */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: -100px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--gold);
    color: black;
    padding: var(--space-3) var(--space-5);
    z-index: var(--z-skip-link);
    transition: top var(--dur-base) var(--ease-standard);
    text-decoration: none;
    font-weight: var(--weight-bold);
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    text-transform: uppercase;
    font-size: var(--text-sm);
    letter-spacing: 1px;
}

.skip-link:focus {
    top: 0;
}

body {
    font-family: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    /* Le dégradé vit sur ::before, en position:fixed, pas en
       `background-attachment: fixed` : sur Chrome/Edge Windows cette valeur sort le
       défilement du compositeur (HasBackgroundAttachmentFixedObjects) et repeint le
       dégradé plein écran à chaque cran de molette — le « scroll pénible sur PC ».
       Une couche fixe séparée rend le même visuel, composée une fois. Le fond uni
       reste sur body : il se propage au canevas et couvre le sur-défilement.
       `isolation: isolate` : --z-under passe sous le contenu de body, jamais sous
       ce fond. */
    background: var(--surface-solid-6);
    color: var(--text-main);
    overflow-x: hidden;
    min-height: 100vh;
    isolation: isolate;
}

body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: var(--z-under);
    background: radial-gradient(circle at top left, var(--surface-solid-1) 0%, var(--surface-solid-5) 50%, var(--surface-solid-6) 100%);
    pointer-events: none;
}

h1,
h2,
h3 {
    font-weight: var(--weight-display);
    letter-spacing: 4px;
    text-transform: uppercase;
}

.gradient-text {
    color: var(--gold); /* Fallback pour mode contraste élevé ou texte transparent */
    background: var(--accent-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    display: inline-block;
}

/* En contraste force, le degrade de fond est supprime mais -webkit-text-fill-color
   ne l'est pas : sans ce bloc, tous les titres .gradient-text deviennent invisibles. */
@media (forced-colors: active) {
    .gradient-text,
    .home-title {
        background: none;
        -webkit-text-fill-color: currentColor;
        color: CanvasText;
        animation: none;
    }
    :focus-visible { outline: 3px solid Highlight; }
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: var(--space-7);
}

.screen {
    display: none;
    animation: screenEnter var(--dur-base) ease-out forwards;
}

.screen.active {
    display: block;
}

@keyframes screenEnter {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.floating-score {
    position: absolute;
    color: var(--correct-color);
    font-weight: var(--weight-impact);
    font-size: 1.8rem;
    pointer-events: none;
    animation: floatUp 1.2s ease-out forwards;
    z-index: var(--z-modal);
    text-shadow: 0 0 10px color-mix(in srgb, var(--correct-color) 50%, transparent);
}

@keyframes floatUp {
    0% {
        opacity: 1;
        transform: translateY(0) scale(1);
    }

    100% {
        opacity: 0;
        transform: translateY(-40px) scale(1.3);
    }
}

.logo-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

/* Le fauteuil et le titre se dimensionnaient sur la seule LARGEUR : sur un
   portable large mais court (1366x640), 30vw butait sur son maximum alors que
   la hauteur, elle, etait epuisee — la carte « Fauteuil du jour », qui suit
   l'en-tete, tombait entierement sous la ligne de flottaison.
   Le plafond en vh s'applique PAR-DESSUS le clamp existant, pas dedans : un
   plancher en px abaisse aurait rapetissi le fauteuil sur telephone, ou c'est
   justement le plancher qui gouverne (30vw = 112px a 375px de large).
   DEUX seuils, a ne pas confondre : 26vh passe sous le PLAFOND de 320px des
   1231px de haut, et sous le PLANCHER de 200px a 769px. Autrement dit tout
   ecran de moins de 1231px de haut — donc la quasi-totalite du parc, portables
   compris — recoit un fauteuil plus petit qu'avant : -35% a 1280x800, -23% a
   1920x950, -13% sur un iPhone SE (667px). C'est la demande (« un peu plus
   petit »), pas un effet de bord ; ne pas reecrire le commentaire en
   « seuls les ecrans courts bougent », c'est faux.
   svh apres vh : sur iOS, vh se resout sur le GRAND viewport (barre d'URL
   retractee), donc le plafond ne mordait pas a l'instant precis ou la barre est
   deployee — l'etat le plus court, celui qui debordait. */
.throne-image-container {
    width: min(clamp(200px, 30vw, 320px), 26vh);
    width: min(clamp(200px, 30vw, 320px), 26svh);
    height: auto;
    margin: 0 auto var(--space-4);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    filter: drop-shadow(0 0 40px color-mix(in srgb, var(--red-pure) 30%, transparent));
}

.home-throne-img {
    width: 100%;
    height: auto;
    object-fit: contain;
    animation: floatThrone 8s ease-in-out infinite;
}

@keyframes floatThrone {
    0%, 100% { transform: translateY(0) rotate(0deg) scale(1); }
    50% { transform: translateY(-20px) rotate(2deg) scale(1.05); }
}

.home-header {
    position: relative;
    text-align: center;
    margin-top: 5vh;
    margin-bottom: var(--space-7);
}

/* Descendue sur la ligne de credits : c'est une metadonnee de pied de page,
   plus une pastille rouge au-dessus du jeu. */
.version-badge {
    display: none;
    color: inherit;
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-chip);
    margin-left: var(--space-2);
}

.home-header-divider {
    margin: var(--space-4) 0;
    color: var(--gold);
    font-size: var(--text-lg);
}

.home-header h1 {
    /* Deux lignes empilees : chacune est deux fois plus courte qu'avant, donc
       la meme largeur d'ecran porte des lettres nettement plus grandes.
       Le plafond en vh : voir .throne-image-container. Quand il gouverne, la
       taille ne suit plus le reglage « texte plus grand » de l'OS — acceptable
       ici, c'est le logotype et non du contenu, et le zoom du navigateur (WCAG
       1.4.4) rebascule sur les media queries etroites, donc il agrandit bien. */
    font-size: min(clamp(3.2rem, 15vw, 7.5rem), 11vh);
    font-size: min(clamp(3.2rem, 15vw, 7.5rem), 11svh);
    line-height: 0.92;
    font-weight: var(--weight-bold);
    letter-spacing: -2px;
    text-transform: uppercase;
}

/* « Objectif » / « Fauteuil » sur deux lignes. Deux <span> en bloc plutot
   qu'un <br> : le noeud de texte espace qui les separe reste dans le calcul
   du nom accessible, donc les lecteurs d'ecran annoncent toujours
   « Objectif Fauteuil » et pas « ObjectifFauteuil ». */
.home-title-line { display: block; }

/* « Objectif » un cran plus petit : c'est le mot de service, « Fauteuil » est
   le sujet. Les deux mots ont 8 lettres, donc a taille egale ils formaient un
   bloc parfaitement rectangulaire, sans hierarchie. Em et pas rem : la ligne
   suit le clamp du h1, donc le rapport tient a toutes les largeurs. */
.home-title-line:first-child { font-size: 0.78em; }

/* Titre d'accueil — le brand mark en rouge, qui respire. Classe dediee et
   pas .gradient-text : celle-ci habille une vingtaine de titres de modales
   qui doivent rester sur la teinte creme/rose. Le pulse ne joue que sur la
   halo et vers le HAUT de la luminosite (1 -> 1.12), jamais en dessous :
   le contraste au repos est le pire cas, donc il reste conforme. */
.home-title {
    color: var(--wrong-soft); /* Fallback : contraste non transparent */
    background: var(--brand-mark-red);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    display: inline-block;
    animation: home-title-pulse 3.2s var(--ease-standard) infinite;
}

@keyframes home-title-pulse {
    0%, 100% {
        filter: brightness(1) drop-shadow(0 0 6px color-mix(in srgb, var(--red-pure) 18%, transparent));
    }
    50% {
        filter: brightness(1.12) drop-shadow(0 0 26px color-mix(in srgb, var(--red-pure) 55%, transparent));
    }
}

@media (prefers-reduced-motion: reduce) {
    .home-title { animation: none; }
}

/* Ecran court (portable 1366x768 fenetre, telephone en paysage) : sous cette
   hauteur l'air vaut moins que la carte « Fauteuil du jour », qui doit rester
   au-dessus de la ligne de flottaison. On resserre les marges de l'en-tete
   plutot que de rapetisser encore la marque — les plafonds en vh ci-dessus ont
   deja fait leur part. Rien ici ne s'applique a un ecran de bureau. */
@media (max-height: 700px) {
    .home-header {
        margin-top: var(--space-3);
        margin-bottom: var(--space-5);
    }

    /* 41px (8 + 25 + 8) pour trois points decoratifs, aria-hidden : c'est la
       difference entre un bouton RELEVER visible et coupe sur un iPhone SE en
       Safari (375x553 barre d'URL deployee, mesure : 572 > 553). */
    .home-header-divider { display: none; }

    .logo-container {
        gap: var(--space-2);
        margin-bottom: var(--space-2);
    }

    .throne-image-container { margin-bottom: var(--space-2); }
}

.home-info {
    text-align: center;
    max-width: 850px;
    margin: 0 auto var(--space-8);
    color: var(--text-muted);
    line-height: 1.7;
    font-weight: var(--weight-display);
    font-size: var(--text-lg);
}

.cta-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
    margin: var(--space-6) 0 var(--space-7);
}

.link-btn {
    background: none;
    border: none;
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-ui);
    text-transform: uppercase;
    cursor: pointer;
    padding: var(--space-1) var(--space-3);
    border-bottom: 1px solid transparent;
    position: relative;
    transition: color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}

/* Cible tactile de 44px sans deplacer le souligne : le pseudo-element
   agrandit la zone cliquable, pas la boite visible. */
.link-btn::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    min-height: var(--control-h-md);
    height: 100%;
}

.search-input-wrap {
    position: relative;
}

.search-input {
    width: 100%;
    min-height: var(--control-h-lg);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-btn);
    background: var(--surface-2);
    /* Contraste de bordure WCAG 1.4.11 : limite du champ visible au repos. */
    border: 1px solid var(--border-contrast);
    color: var(--text-main);
    font-family: inherit;
    outline: none;
    transition: border-color var(--dur-base) var(--ease-standard);
}

.search-input:focus {
    outline: none;
    border-color: var(--gold);
}

/* Focus clavier : on rétablit l'anneau global (le :focus ci-dessus le retirait,
   laissant l'utilisateur clavier sans repère visible sur le champ de recherche). */
.search-input:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
    box-shadow: 0 0 20px var(--gold-glow);
}

/* Résultats de recherche — styles déplacés depuis un style="" inline (search.js).
   Chaque item est un role="button" atteignable au clavier. */
.search-result-item {
    padding: var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    border: 1px solid var(--border);
    cursor: pointer;
    transition: border-color var(--dur-base) var(--ease-standard);
}
.search-result-item:hover,
.search-result-item:focus-visible {
    border-color: var(--gold);
}
.search-res-empty {
    text-align: center;
    padding: var(--space-5);
    color: color-mix(in srgb, var(--text-main) 50%, transparent);
}

.search-submit-btn {
    position: absolute;
    right: var(--space-2);
    top: var(--space-2);
    bottom: var(--space-2);
    border-radius: var(--radius-btn);
    border: none;
    background: var(--gold);
    color: var(--bg-deep);
    padding: 0 var(--space-4);
    cursor: pointer;
    font-weight: var(--weight-bold);
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-chip);
}

/* Système de boutons unifié : taille gérée par .btn, les variantes ne changent
   QUE la couleur. « rectangle légèrement arrondi », hauteur identique partout.
   Cas spéciaux (héros, icône carrée, pagination) ont leurs propres classes
   (.cta-hero-btn, .icon-btn, …) qui surchargent .btn ponctuellement. */
.btn {
    min-height: var(--control-h-md);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-btn);
    font-weight: var(--weight-body);
    letter-spacing: var(--tracking-ui);
    text-transform: uppercase;
    cursor: pointer;
    /* Liste explicite plutot que `all` : les 4 variantes :hover n'animent que ces
       proprietes. `all` animait aussi min-height/padding/font-size a chaque
       changement d'etat. */
    transition: background var(--dur-base) var(--ease-standard),
                border-color var(--dur-base) var(--ease-standard),
                color var(--dur-base) var(--ease-standard),
                transform var(--dur-fast) var(--ease-standard),
                box-shadow var(--dur-base) var(--ease-standard);
    border: 1px solid transparent;
    font-size: var(--text-md);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    line-height: 1.2;
}

/* Seule variante de taille. Le hero et le bouton Suivant sont les deux
   seuls controles qui doivent dominer leur ecran. */
.btn--lg {
    min-height: var(--control-h-lg);
    padding: var(--space-3) var(--space-6);
    font-size: var(--text-base);
    letter-spacing: var(--tracking-cta);
}

.btn-primary {
    background: var(--gold);
    /* Hygiene des tokens : couleur de texte sur aplat --gold dediee, pas de noir brut. */
    color: var(--on-gold);
    border-color: var(--gold);
    box-shadow: 0 0 20px var(--gold-glow);
}

.btn-primary:hover {
    transform: translateY(-3px);
    box-shadow: 0 0 30px var(--gold-glow);
}

.btn-secondary {
    background: transparent;
    color: var(--gold);
    border-color: var(--gold);
}

.btn-secondary:hover {
    background: color-mix(in srgb, var(--gold) 10%, transparent);
    transform: translateY(-2px);
}

.transition-btns-group {
    display: flex;
    justify-content: center;
    align-items: stretch;
    gap: var(--space-5);
    margin-top: var(--space-6);
    width: 100%;
}

.transition-btns-group .btn {
    flex: 1;
    max-width: 300px;
    margin-top: 0 !important;
    padding: 1.2rem var(--space-5);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    height: 100%;
}

/* Bilan (ui.js showBilan) : le groupe de boutons ouvre le bilan, il ne le
   clôt plus — margin-top pensé pour un groupe en fin d'écran collait les
   boutons contre le titre en haut, et laissait le classement/résumé suivant
   sans respiration. */
.bilan-btns-top { margin-top: var(--space-5); margin-bottom: var(--space-6); }

/* ===== Écran de transition (showTransitionScreen, ui.js) ===== */
.transition-header {
    margin-bottom: var(--space-6);
}

.transition-header .glow-dot {
    width: 12px;
    height: 12px;
    background: var(--gold);
    border-radius: 50%;
    margin: 0 auto var(--space-4);
    box-shadow: 0 0 15px var(--gold);
}

.transition-header-rule {
    width: 60px;
    height: 2px;
    background: var(--gold);
    margin: 0 auto;
    opacity: 0.5;
}

.transition-title {
    font-size: var(--text-display);
    margin-bottom: var(--space-2);
    letter-spacing: 4px;
    font-weight: var(--weight-impact);
    text-transform: uppercase;
}

.transition-body {
    color: var(--text-muted);
    margin-bottom: var(--space-7);
    font-size: var(--text-lg);
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
    line-height: 1.6;
}

.transition-progress-container {
    width: 200px;
    height: 4px;
    background: var(--surface-2);
    /* 2px kept raw: this bar is only 4px tall, so --radius-sm (8px) would
       read as a full pill instead of a subtle rounding — a feel change,
       not a measurement snap. Flagged in the map's REVIEW list. */
    border-radius: 2px;
    margin: 0 auto var(--space-7);
    overflow: hidden;
    position: relative;
}

.transition-progress-bar {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background: var(--gold);
    width: 0;
    /* Keeping the "ease-out" keyword literal — the map warns against
       blind-replacing it with --ease-decelerate, a numerically different
       curve. */
    animation: progressFill 0.8s ease-out forwards;
}

.transition-cta-btn {
    padding: var(--space-5) var(--space-7);
    font-size: var(--text-base);
    letter-spacing: 2px;
    transform: translateY(10px);
    opacity: 0;
    animation: btnSlideUp var(--dur-base) ease forwards 0.6s;
}

/* Thème imposé / thème du jour — custom content injected into the
   transition screen (startPhase2/startPhase3, script.js). */
.theme-announce {
    margin: var(--space-6) 0;
}

.theme-announce--daily {
    margin: var(--space-5) 0;
}

.theme-announce-name {
    font-size: var(--text-2xl);
    color: var(--gold);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
}

.theme-announce-label {
    font-size: var(--text-sm);
    letter-spacing: 2px;
    color: var(--text-muted);
    text-transform: uppercase;
    margin-bottom: var(--space-2);
}

.theme-announce-note {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin-top: var(--space-4);
}

.bilan-search-btn {
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-muted);
    width: var(--control-icon-inline);
    height: var(--control-icon-inline);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--dur-base) ease;
    margin-left: var(--space-3);
    vertical-align: middle;
}

.bilan-search-btn:hover {
    border-color: var(--gold);
    color: var(--gold);
    transform: scale(1.1);
}

.bilan-search-btn svg {
    width: 14px;
    height: 14px;
}

.phases-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
    margin-bottom: 5rem;
    /* Passe de <div> a <ul> (a11y) : neutralise les puces et le padding par
       defaut de la liste, margin-bottom existant conserve tel quel. */
    list-style: none;
    padding-left: 0;
}

.phase-card {
    background: var(--bg-card);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    padding: var(--space-6);
    border-radius: 1.2rem;
    border: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    text-align: center;
    transition: transform var(--dur-base) ease, border-color var(--dur-base) ease;
    display: flex;
    flex-direction: column;
    min-height: 320px;
}

.phase-card:hover {
    transform: translateY(-5px);
    border-color: color-mix(in srgb, var(--gold) 30%, transparent);
}

.phase-card .num {
    font-size: var(--text-xl);
    font-weight: var(--weight-impact);
    color: var(--gold);
    margin-bottom: var(--space-2);
    display: block;
}

/* margin-top:auto — les blocs d'action des trois cartes s'alignent sur
   leur bord bas quelle que soit la longueur de la description. */
.card-actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    margin-top: auto;
    padding-top: var(--space-6);
}

.btn-outline {
    background: transparent;
    border-color: var(--border);
    color: var(--text-muted);
}

.btn-outline:hover {
    background: var(--surface-2);
    border-color: var(--gold);
    color: var(--gold);
}

/* « N nouveaux thèmes » des cartes Compét' et Défi, injecté dans
   #new-themes-slot-N par renderNewThemeChips (ui.js) ; absent quand le compte
   est 0 — jamais rendu vide.

   Surtitre et non bannière : le libellé, puis un filet court dessous, dans le
   flux normal en haut de la carte. C'est la grammaire des surtitres du reste du
   jeu, et ça tient À L'INTÉRIEUR du cadre — une banderole à cheval sur le bord
   criait plus fort que le titre de la manche. Le filet s'allonge au survol :
   la seule chose qui bouge, et elle dit que ça se clique. */
.phase-card-new {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--gold);
    font-family: inherit;
    font-size: var(--text-2xs);
    font-weight: var(--weight-medium);
    letter-spacing: 2px;
    text-transform: uppercase;
    cursor: pointer;
}

.phase-card-new::after {
    content: '';
    width: 28px;
    height: 2px;
    border-radius: 2px;
    background: var(--gold);
    transition: width var(--dur-base) ease;
}

.phase-card-new:hover:not(:disabled)::after,
.phase-card-new:focus-visible::after {
    width: 56px;
}

.phase-card-new:disabled {
    cursor: default;
}

.phase-card h3 {
    font-size: var(--text-lg);
    margin-bottom: var(--space-4);
}

/* Carte « Le Marathon » (index.html) : même famille que les cartes de manche, en bandeau
   sous la grille — c'est un mode à part, pas une quatrième manche. Sans backdrop-filter
   (audit perf 2026-09-09) : le fond opaque de la carte suffit sur le fond d'accueil. */
.marathon-card {
    background: var(--bg-card);
    border: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    border-radius: 1.2rem;
    padding: var(--space-6);
    margin: 0 0 var(--space-6);
    text-align: center;
}

.marathon-head {
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.marathon-head .num {
    font-size: var(--text-xl);
    font-weight: var(--weight-impact);
    color: var(--gold);
}

.marathon-head h3 { font-size: var(--text-lg); margin: 0; }

/* Pastille « Bêta » (carte Marathon) : même grammaire que .theme-card-flag, contour seul
   pour ne pas rivaliser avec le titre. */
.beta-tag {
    display: inline-block;
    vertical-align: middle;
    margin-left: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--gold);
    border-radius: var(--radius-pill);
    color: var(--gold);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    letter-spacing: 2px;
    text-transform: uppercase;
}

.marathon-record {
    font-size: var(--text-xs);
    color: var(--gold);
    letter-spacing: 1px;
    text-transform: uppercase;
}

.marathon-card p {
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: 1.5;
    margin: var(--space-3) 0 0;
    font-weight: var(--weight-display);
}

.marathon-actions {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    padding-top: var(--space-5);
}

.marathon-actions .btn { flex: 1 1 160px; max-width: 240px; }

.marathon-stop-btn { margin-right: var(--space-3); }

.marathon-bilan-line { color: var(--gold); }

.phase-card p {
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: 1.5;
    flex-grow: 1;
    font-weight: var(--weight-display);
}

.game-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: var(--surface-2);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    padding: var(--space-5) var(--space-6);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-6);
    border: 1px solid var(--border);
    box-shadow: 0 10px 30px color-mix(in srgb, var(--shadow-base) 20%, transparent);
}

.score-board {
    text-align: right;
    min-width: 150px;
}

.score-board .score {
    font-size: 2rem;
    font-weight: var(--weight-display);
    color: var(--gold);
    letter-spacing: 2px;
}

.score-header {
    justify-content: center;
}

#user-score {
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    color: var(--gold);
}

#phase-title {
    margin-bottom: 0;
}

#question-counter {
    color: var(--text-muted);
    font-size: var(--text-md);
    margin-top: var(--space-2);
}

/* Overrides .btn — placed after it in the cascade on purpose (same
   specificity as the base .btn rule; source order decides). */
.cta-hero-btn {
    width: 100%;
    max-width: 420px;
}

/* Bouton icone autonome : rond, jamais de libelle. Le 45px d'avant etait
   une coquille a cote des 44px de .settings-btn / .footer-key-btn. */
.icon-btn {
    padding: 0;
    margin-top: 0;
    min-width: var(--control-icon);
    width: var(--control-icon);
    height: var(--control-icon);
    min-height: var(--control-icon);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border-color: var(--border);
}

.quiz-area {
    background: linear-gradient(135deg, var(--surface-1) 0%, color-mix(in srgb, var(--text-main) 1%, transparent) 100%);
    /* Pas de backdrop-filter : derrière la boîte il n'y a que le dégradé de body,
       lisse — le flouter le laisse identique (diff de pixels 2026-09-11 : 0 pixel
       sur 1 049 088, flou coupé ou non). Sur PC, avec la boîte à hauteur naturelle
       qui défile sous le viewport, un blur(25px) de 1100×900 px se recalculait à
       chaque frame de molette pour rien. Les .phase-card de l'accueil gardent le
       leur (décision DA 2026-09-09). */
    padding: var(--space-8) var(--space-7);
    border-radius: 2rem;
    text-align: center;
    /* 600px de confort, jamais plus que 85 % du viewport : sur un écran court la
       boîte ne doit pas dépasser seule le pli. Repli 600px sec pour un moteur sans
       `svh`. */
    min-height: 600px;
    min-height: min(600px, 85svh);
    /* Pas de plafond ni de défilement interne : la boîte prend sa hauteur naturelle
       et c'est la PAGE qui défile. Avant, `max-height: 85svh` + `overflow-y: auto`
       avec l'ascenseur masqué faisaient de la boîte un scroller invisible : la
       molette défilait d'abord la boîte (bilan, relevé, Cash) puis la page — le
       « scroll qui se bat » signalé sur PC. Les media queries 768px / 520px et
       .selection-mode avaient déjà tranché dans ce sens, chacune pour son format. */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    box-shadow: 
        0 25px 50px color-mix(in srgb, var(--shadow-base) 50%, transparent),
        inset 0 0 30px var(--surface-1);
    position: relative;
    margin-top: var(--space-4);
    gap: var(--space-5);
    transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease;
}



/* Enfant direct de .quiz-area (0,2,0) : doTransition ne pose ces classes que sur
   area.children, et la spécificité garantit qu'une `animation` propre à un composant
   (déclarée plus bas, à 0,1,0) ne gagnera jamais la cascade sur l'entrée/sortie
   commune — c'est ce qui faisait sauter l'image de question. */
.quiz-area > .quiz-content-animate {
    animation: contentEnter var(--dur-base) var(--ease-decelerate) forwards;
}

@keyframes contentEnter {
    from { 
        opacity: 0; 
        transform: translateY(14px) scale(0.98);
    }
    to { 
        opacity: 1; 
        transform: translateY(0) scale(1);
    }
}

.quiz-area > .quiz-content-exit {
    animation: contentExit var(--dur-fast) ease-in forwards;
}

@keyframes contentExit {
    to { 
        opacity: 0; 
        transform: translateY(-8px) scale(0.99);
    }
}

@keyframes progressFill {
    from { width: 0; }
    to { width: 100%; }
}

@keyframes btnSlideUp {
    from { 
        opacity: 0;
        transform: translateY(20px);
    }
    to { 
        opacity: 1;
        transform: translateY(0);
    }
}

.quiz-area:not(.selection-mode) {
    justify-content: flex-start;
}

/* Sélecteur de thème (manches 2 et 3) : un catalogue de 130+ thèmes, contenu non
   borné contrairement aux écrans de question. Pas de plancher de 600px, le contenu
   part du haut. `doTransition` remet la page en haut en quittant ce mode. */
.quiz-area.selection-mode {
    justify-content: flex-start;
    padding-top: var(--space-6);
    min-height: 0;
}

.question-theme {
    color: var(--gold);
    font-size: var(--text-md);
    text-transform: uppercase;
    letter-spacing: 4px;
    margin-bottom: var(--space-2);
    font-weight: var(--weight-display);
}

/* .qpt-badge moved to end of file */

.ia-badge {
    position: absolute;
    top: 20px;
    right: 20px;
    background: var(--surface-1);
    border: 1px solid var(--border);
    color: var(--text-muted);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    pointer-events: none;
    z-index: var(--z-raised);
}

/* Default hidden state (was inline style="display:none" in index.html).
   script.js/ui.js toggle these via el.style.display at runtime, which — as
   an inline style — still wins over this ID rule, so behavior is unchanged. */
#qpt-badge,
#ia-badge,
#question-image-container {
    display: none;
}

.question-meta {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin: 0 auto var(--space-5);
    font-family: 'Outfit', sans-serif;
    letter-spacing: 0.5px;
    width: fit-content;
}

/* L'identifiant de question n'intéresse que l'admin et le relecteur (correction) :
   masqué pour les joueurs, il encombrait le pied de question. */
.q-id {
    display: none;
    color: var(--gold);
    font-weight: var(--weight-bold);
}

body.admin-active .q-id {
    display: inline;
}

.q-author {
    opacity: 0.8;
}

.question-text {
    font-size: 1.8rem;
    font-weight: var(--weight-bold);
    margin-bottom: var(--space-7);
    line-height: 1.4;
    color: white;
    text-shadow: 0 2px 4px color-mix(in srgb, var(--shadow-base) 30%, transparent);
}

/* Pas d'animation propre : enfant direct de .quiz-area, le bloc entre et sort avec
   ses frères (.quiz-content-*). Celle qu'il avait gagnait la cascade sur la sortie
   commune : l'image restait pleine pendant que le reste s'effaçait, puis sautait. */
.question-image-container {
    margin: -1rem auto var(--space-7);
    max-width: 100%;
    display: flex;
    justify-content: center;
}

/* <picture> (variante WebP, game.webpVariant) : transparente pour la mise en page,
   les règles sur l'<img> s'appliquent comme avant. */
.question-image-container picture,
.bilan-thumb-btn picture,
.lightbox-overlay picture { display: contents; }

.question-image-container img {
    max-width: 100%;
    max-height: 350px;
    border-radius: var(--radius-md);
    border: 3px solid var(--border);
    box-shadow: 0 10px 30px color-mix(in srgb, var(--shadow-base) 50%, transparent), 0 0 0 1px var(--surface-3);
    object-fit: contain;
}

#quiz-controls {
    display: flex;
    flex-direction: column;
    align-items: center; /* Centre le bilan et les blocs à max-width (sinon collés à gauche) */
    gap: var(--space-5);
    width: 100%;
}

.modes-grid {
    display: flex;
    justify-content: center;
    gap: var(--space-5);
    margin: var(--space-6) 0;
    width: 100%;
}

.mode-btn {
    flex: 1;
    max-width: 220px;
    min-height: 90px;
    padding: 1.2rem var(--space-6);
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: var(--surface-2);
    color: white;
    cursor: pointer;
    transition: all 0.4s var(--ease-standard);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
}

/* Mode sans assez de propositions pour cette question (renderQuestion, modeDistractors). */
.mode-btn:disabled {
    cursor: not-allowed;
    opacity: 0.4;
}

.mode-btn:hover:not(:disabled) {
    border-color: var(--gold);
    background: color-mix(in srgb, var(--gold) 8%, transparent);
    transform: translateY(-5px);
    box-shadow: 0 10px 20px color-mix(in srgb, var(--shadow-base) 20%, transparent);
}

.mode-btn strong {
    display: block;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--gold);
}

.mode-btn span {
    font-size: var(--text-sm);
    color: var(--text-muted);
    font-weight: var(--weight-display);
    text-transform: uppercase;
    letter-spacing: 1px;
}

/* Trait d'or (ui.js, modeTraceStart / modeTracePlay) : au clic sur Duo ou Carré, les
   autres modes s'effacent et le bouton choisi se replie en un trait d'or, qui palpite tant
   que le serveur du défi n'a pas rendu les propositions. Mouvement réduit : jamais posé. */
.modes-grid.is-picking .mode-btn:not(.is-picked) {
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-decelerate), transform var(--dur-fast) var(--ease-decelerate);
}

.modes-grid.is-picking .mode-btn.is-picked {
    border-color: var(--gold);
    box-shadow: 0 0 14px var(--gold-glow);
    pointer-events: none;
    animation: modeCollapse 0.16s var(--ease-standard) forwards, modeLinePulse 1.1s ease-in-out 0.16s infinite;
}

/* Le défi désactive les boutons pendant l'appel au serveur : le trait garde son éclat. */
.modes-grid.is-picking .mode-btn.is-picked:disabled {
    opacity: 1;
    cursor: default;
}

.modes-grid.is-picking .mode-btn.is-picked > * {
    opacity: 0;
    transition: opacity 0.08s ease-in;
}

@keyframes modeCollapse {
    40%  { transform: scale(1.03); }
    100% { transform: scaleY(0.025); background-color: var(--gold); border-color: var(--gold); }
}

@keyframes modeLinePulse {
    50% { opacity: 0.45; }
}

/* Le temps du tracé : la grille des modes reste par-dessus, à sa place, et la vraie grille
   des propositions attend, invisible, sous le calque SVG. */
#quiz-controls.is-tracing {
    position: relative;
}

.modes-grid.is-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    pointer-events: none;
}

.options-grid.is-tracing {
    opacity: 0;
    pointer-events: none;
}

.mode-trace {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
    z-index: var(--z-raised);
}

.mode-trace line,
.mode-trace path {
    fill: none;
    stroke: var(--gold);
    stroke-linecap: round;
    filter: drop-shadow(0 0 4px var(--gold-glow));
}

.mode-trace line {
    stroke-width: 2;
    opacity: 0;
    transform-box: fill-box;
    transform-origin: center;
}

.mode-trace path {
    stroke-width: 1.5;
}

.options-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-5);
    max-width: 750px;
    margin: 0 auto;
    width: 100%;
}

/* Super Cash number picker: same grid, narrower + bigger numbers. Modifier
   only — .option-btn itself (game component with answer-reveal state) is
   untouched. */
.options-grid--supercash {
    grid-template-columns: repeat(2, 1fr);
    max-width: 300px;
    margin: 0 auto;
}

.mode-announce-label {
    color: var(--gold);
    font-weight: var(--weight-bold);
    margin-bottom: var(--space-5);
    text-transform: uppercase;
    letter-spacing: 2px;
}

.win-highlight {
    color: var(--correct-color);
    font-weight: var(--weight-bold);
}

.option-btn {
    position: relative;
    overflow: hidden;
    background: var(--surface-1);
    /* Contraste de bordure WCAG 1.4.11 : le bouton de reponse est un
       composant d'interface, sa limite doit rester visible au repos. */
    border: 1px solid var(--border-contrast);
    color: white;
    padding: var(--space-5);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: var(--text-base);
    font-weight: var(--weight-display);
    /* Liste explicite : `all` animait aussi le padding-right posé à la révélation
       (place pour la coche / la croix), le texte glissait sur 0,4 s. */
    transition: background-color 0.4s var(--ease-standard), border-color 0.4s var(--ease-standard), box-shadow 0.4s var(--ease-standard), transform 0.4s var(--ease-standard), opacity 0.4s var(--ease-standard), color 0.4s var(--ease-standard);
    letter-spacing: 1px;
    z-index: var(--z-base);
    /* Une réponse longue sans espace (URL, mot composé) était rognée par
       l'overflow:hidden au lieu de passer à la ligne. */
    overflow-wrap: anywhere;
}

/* Overrides .option-btn — placed after it in the cascade on purpose. */
.option-btn--supercash {
    font-size: var(--text-xl);
    font-weight: var(--weight-impact);
    padding: var(--space-5);
}

.option-btn::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1; /* sous son parent .option-btn (pile locale) */
    opacity: 0;
    transform: scale(0.98);
    transition: opacity 0.8s var(--ease-standard), transform 0.8s var(--ease-standard);
}

.option-btn span {
    position: relative;
    z-index: calc(var(--z-base) + 1);
    transition: all var(--dur-slow) ease;
}

.option-btn:hover:not(:disabled) {
    background: var(--surface-2);
    border-color: var(--gold);
}

.option-btn.correct {
    border-color: color-mix(in srgb, var(--success-alt) 80%, transparent);
    box-shadow: 0 0 20px color-mix(in srgb, var(--success-alt) 20%, transparent);
    font-weight: var(--weight-medium);
    background: transparent !important;
    /* Marge pour le glyphe de ::before, cf. plus bas : la reponse ne doit
       jamais chevaucher le symbole. */
    padding-right: var(--space-7);
}

.option-btn.correct::after {
    background: color-mix(in srgb, var(--success-alt) 25%, transparent);
    opacity: 1;
    transform: scale(1);
}

.option-btn.wrong {
    border-color: color-mix(in srgb, var(--danger-alt) 80%, transparent);
    box-shadow: 0 0 20px color-mix(in srgb, var(--danger-alt) 20%, transparent);
    opacity: 0.9;
    background: transparent !important;
    padding-right: var(--space-7);
}

.option-btn.wrong::after {
    background: color-mix(in srgb, var(--danger-alt) 25%, transparent);
    opacity: 1;
    transform: scale(1);
}

/* Indice non-color (WCAG 1.4.1) : correct/faux ne se distinguent pas que par
   la teinte, un glyphe le confirme (utile en daltonisme ou contraste force). */
.option-btn.correct::before,
.option-btn.wrong::before {
    position: absolute;
    top: 50%;
    right: var(--space-3);
    transform: translateY(-50%);
    font-weight: var(--weight-impact);
    z-index: calc(var(--z-base) + 1);
    pointer-events: none;
}

.option-btn.correct::before {
    content: '\2713';
    color: var(--success-alt);
}

.option-btn.wrong::before {
    content: '\2715';
    color: var(--danger-alt);
}

.cash-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-7);
    margin: var(--space-7) auto;
    width: 100%;
    animation: fadeIn 0.6s ease-out;
}

.cash-input {
    width: 100%;
    max-width: 550px;
    padding: 1.2rem var(--space-6);
    border-radius: var(--radius-md);
    /* Contraste de bordure WCAG 1.4.11 : limite du champ visible au repos. */
    border: 1px solid var(--border-contrast);
    background: var(--surface-1);
    color: white;
    font-size: clamp(1.2rem, 3.5vw, 2.2rem);
    font-weight: var(--weight-display);
    text-align: center;
    transition: all 0.4s var(--ease-standard);
    letter-spacing: 2px;
    text-transform: uppercase;
    box-shadow: inset 0 2px 10px color-mix(in srgb, var(--shadow-base) 20%, transparent);
    font-family: inherit;
}

.cash-input:focus {
    outline: 2px solid var(--gold);
    outline-offset: 4px;
    border-color: var(--gold);
    background: var(--surface-2);
    box-shadow: 0 0 30px color-mix(in srgb, var(--gold) 10%, transparent), inset 0 2px 10px color-mix(in srgb, var(--shadow-base) 20%, transparent);
    letter-spacing: 4px;
}

.cash-input::placeholder {
    /* --border-strong (alpha .20) tombait à 1,79:1 sur --surface-1 : illisible.
       --text-muted donne ~7,3:1 sur le même fond. */
    color: var(--text-muted);
    font-size: var(--text-md);
    letter-spacing: 1px;
    text-transform: none;
    font-weight: var(--weight-display);
}

.feedback-msg {
    margin-top: var(--space-6);
    font-size: var(--text-base);
    font-weight: var(--weight-display);
    min-height: 2rem;
    letter-spacing: 2px;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
}

.search-btn {
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-muted);
    width: var(--control-icon);
    height: var(--control-icon);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--dur-base) ease;
    padding: 0;
}

.theme-btn:hover {
    background: color-mix(in srgb, var(--gold) 8%, transparent);
    border-color: var(--gold);
    transform: translateY(-3px);
}

        .theme-btn span {
            display: block;
        }

.search-btn:hover {
    background: var(--surface-3);
    border-color: var(--gold);
    color: var(--gold);
    transform: scale(1.1);
}

.search-btn svg {
    width: 18px;
    height: 18px;
}

.next-timer-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 6px;
    background: var(--surface-2);
    overflow: hidden;
    border-radius: 1.5rem 1.5rem 0 0;
    opacity: 0;
    visibility: hidden;
    /* Le container reste non-interactif meme actif : il ne porte que
       .next-timer-bar, purement visuel. .active ne restaure donc pas
       pointer-events (repris du bloc supprime, comportement inchange). */
    pointer-events: none;
    transition: opacity var(--dur-base) ease;
    z-index: var(--z-raised);
}

.next-timer-container.active {
    opacity: 1;
    visibility: visible;
}

.next-timer-bar {
    height: 100%;
    width: 100%;
    background: linear-gradient(to right, var(--gold), var(--text-main));
    box-shadow: 0 0 15px var(--gold-glow);
    transform-origin: left;
    transform: scaleX(0);
}

.next-timer-container.active .next-timer-bar {
    animation: nextTimerFill 4s linear forwards;
}

@keyframes nextTimerFill {
    from {
        transform: scaleX(1);
    }

    to {
        transform: scaleX(0);
    }
}

/* Chrono par question (script.js, chronoStart). La jauge est une animation de 30 s
   relancée à chaque question ; `is-paused` la fige sur le temps restant une fois la
   réponse donnée, `is-urgent` passe au rouge pour les dix dernières secondes. */
.chrono {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    max-width: 520px;
    margin: 0 auto var(--space-4);
}

.chrono-track {
    position: relative;
    flex: 1;
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    overflow: hidden;
}

/* Entre deux questions (script.js, chronoArm) : la jauge remonte à plein ; si la question
   tarde (défi servi par le serveur), un reflet la parcourt jusqu'à son arrivée. Le délai
   le tient invisible quand la question arrive aussitôt. */
.chrono.is-arming .chrono-track::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 28%;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--text-main) 70%, transparent), transparent);
    animation: chronoGlint 0.9s linear 0.25s infinite backwards;
}

@keyframes chronoGlint {
    from { transform: translateX(-100%); }
    to { transform: translateX(380%); }
}

.chrono-fill {
    display: block;
    height: 100%;
    width: 100%;
    background: var(--gold);
    transform-origin: left;
}

.chrono.is-running .chrono-fill {
    animation: chronoDrain 30s linear forwards;
}

.chrono.is-paused .chrono-fill {
    animation-play-state: paused;
}

.chrono-num {
    min-width: 3.2em;
    text-align: right;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    font-variant-numeric: tabular-nums;
    color: var(--gold);
}

.chrono.is-urgent .chrono-fill { background: var(--wrong-color); }
.chrono.is-urgent .chrono-num { color: var(--wrong-color); }

@keyframes chronoDrain {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

/* Mouvement réduit : la règle globale ramène toute animation à 0,01 ms, la jauge se
   viderait d'un coup et mentirait sur le temps restant. Le décompte chiffré suffit. */
@media (prefers-reduced-motion: reduce) {
    .chrono-track { display: none; }
}

/* .next-btn : la definition unique est plus bas (section « Next Button &
   Timer »). Un premier bloc vivait ici et etait silencieusement ecrase par
   celui-la ; supprime le 2026-08-19. */

/* Bilan Styles */
.bilan-container {
    max-height: none;
    overflow-y: auto;
    text-align: left;
    padding: var(--space-2) var(--space-4) var(--space-2) 0;
    margin-top: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.bilan-card {
    background: var(--surface-1);
    border-left: 2px solid transparent;
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md);
    display: grid;
    grid-template-columns: 80px 60px 1fr 240px;
    align-items: center;
    gap: var(--space-5);
    margin-bottom: var(--space-2);
    transition: background var(--dur-base) ease;
}

.bilan-card:hover {
    background: var(--surface-2);
}

.bilan-col-num {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.bilan-q-num {
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    color: var(--text-muted);
    text-transform: uppercase;
}

.bilan-pts {
    font-size: var(--text-md);
    font-weight: var(--weight-bold);
}

.bilan-col-img {
    display: flex;
    justify-content: center;
}

.bilan-col-text {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-base);
    line-height: 1.4;
    color: color-mix(in srgb, var(--text-main) 90%, transparent);
}

.bilan-col-ans {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.ans-box {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-md);
}

.ans-icon {
    font-size: var(--text-base);
    flex-shrink: 0;
}

.ans-val {
    font-weight: var(--weight-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bilan-q-text {
    font-size: var(--text-base);
    font-weight: var(--weight-display);
    margin-bottom: var(--space-2);
}

/* Bilan 2026 — hiérarchie claire et cartes de réponses */
.bilan-shell { width: min(100%, 900px); margin: 0 auto; text-align: left; }
.bilan-overview {
    padding: var(--space-5);
    margin-bottom: var(--space-6);
    border: 1px solid var(--gold-glow);
    border-radius: 18px;
    background: linear-gradient(145deg, color-mix(in srgb, var(--gold) 8.5%, transparent), var(--surface-1));
    box-shadow: 0 18px 45px color-mix(in srgb, var(--shadow-base) 22%, transparent);
}
.bilan-eyebrow { margin: 0 0 var(--space-4); color: var(--gold); font-size: var(--text-xs); font-weight: var(--weight-impact); letter-spacing: 1.8px; text-transform: uppercase; }
.bilan-overview-grid { display: grid; grid-template-columns: 1.35fr 1fr 1fr; gap: var(--space-3); }
.bilan-score-panel, .bilan-stat-panel {
    min-height: 104px;
    padding: var(--space-4) var(--space-4);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    border: 1px solid var(--surface-3);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--shadow-base) 20%, transparent);
}
.bilan-score-panel { border-color: color-mix(in srgb, var(--gold) 32%, transparent); }
.bilan-score-panel.is-negative { border-color: color-mix(in srgb, var(--wrong-pale-3) 35%, transparent); }
.bilan-stat-label { color: color-mix(in srgb, var(--text-main) 62%, transparent); font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: 1px; text-transform: uppercase; }
.bilan-score-value, .bilan-stat-panel strong { color: white; font-size: 2rem; font-weight: var(--weight-impact); line-height: 1; }
.bilan-score-panel.is-positive .bilan-score-value { color: var(--gold); }
.bilan-score-panel.is-negative .bilan-score-value { color: var(--wrong-color); }
.bilan-score-value { font-size: 2.7rem; }
.bilan-score-value small, .bilan-stat-panel small { margin-left: var(--space-2); color: color-mix(in srgb, var(--text-main) 58%, transparent); font-size: var(--text-xs); font-weight: var(--weight-medium); }
.bilan-filters {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    color: var(--gold);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-2);
}
.bilan-filters input { flex: 1; min-width: 80px; color: white; background: transparent; border: 0; outline: 0; font: inherit; font-size: var(--text-sm); }
/* .bilan-filters input pose outline:0 avec une specificite (0,1,1) qui ecrase
   le :focus-visible global (0,1,0) : sans cette regle le champ est invisible au clavier. */
.bilan-filters input:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--radius-sm); }
.bilan-filters input::placeholder { color: var(--text-muted); }
.bilan-filters select { padding: var(--space-2) var(--space-3); color: white; background: var(--surface-solid-3); border: 1px solid var(--border); border-radius: var(--radius-sm); font: inherit; font-size: var(--text-sm); }
/* « Détail des réponses » pliable. L'état par défaut vient du réglage « bilan
   détaillé » et y retourne à chaque bascule (ui.js) : un seul état, deux surfaces. */
.bilan-detail { margin-top: var(--space-4); }
/* Un <summary> en flex perd son marqueur natif (::marker est ignoré par un conteneur
   flex) : plus rien ne disait que la ligne s'ouvre. On le remplace par un chevron
   dessiné, qui pivote à l'ouverture. `list-style: none` + `::-webkit-details-marker`
   pour Safari, qui garde son triangle sans ça. */
.bilan-detail-sum {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    margin: 0 var(--space-1) var(--space-3);
    padding: var(--space-2) 0; cursor: pointer; list-style: none;
}
.bilan-detail-sum::-webkit-details-marker { display: none; }
.bilan-detail-title { display: flex; align-items: center; gap: var(--space-2); color: white; font-size: var(--text-base); font-weight: var(--weight-bold); }
.bilan-detail-title::before {
    content: ''; width: 0; height: 0; flex-shrink: 0;
    border-left: 5px solid currentColor;
    border-top: 4px solid transparent; border-bottom: 4px solid transparent;
    transition: transform var(--dur-fast);
}
.bilan-detail[open] .bilan-detail-title::before { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
    .bilan-detail-title::before { transition: none; }
}
.bilan-detail-count { color: color-mix(in srgb, var(--text-main) 50%, transparent); font-size: var(--text-xs); }
.bilan-detail-sum:hover .bilan-detail-title { color: var(--gold); }
.bilan-results-list { display: grid; gap: var(--space-3); }
.bilan-result-card {
    padding: var(--space-4) var(--space-4);
    border: 1px solid var(--border);
    border-left: 4px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    box-shadow: 0 9px 24px color-mix(in srgb, var(--shadow-base) 16%, transparent);
}
.bilan-result-card.is-correct { border-left-color: var(--correct-color); background: linear-gradient(100deg, color-mix(in srgb, var(--correct-color) 8.5%, transparent), var(--surface-1) 35%); }
.bilan-result-card.is-wrong { border-left-color: var(--wrong-color); background: linear-gradient(100deg, color-mix(in srgb, var(--wrong-color) 7.5%, transparent), var(--surface-1) 35%); }
.bilan-result-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.bilan-result-meta, .bilan-result-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.bilan-question-number { color: white; font-size: var(--text-xs); font-weight: var(--weight-impact); letter-spacing: 0.8px; }
.bilan-mode-chip, .bilan-status-chip { padding: var(--space-1) var(--space-2); border-radius: var(--radius-pill); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.7px; text-transform: uppercase; }
.bilan-mode-chip { color: var(--gold); background: color-mix(in srgb, var(--gold) 10%, transparent); border: 1px solid color-mix(in srgb, var(--gold) 22%, transparent); }
.is-correct .bilan-status-chip { color: var(--correct-color); background: color-mix(in srgb, var(--correct-color) 12%, transparent); }
.is-wrong .bilan-status-chip { color: var(--wrong-color); background: color-mix(in srgb, var(--wrong-color) 12%, transparent); }
.bilan-points { min-width: 54px; text-align: right; font-size: var(--text-sm); font-weight: var(--weight-impact); }
.bilan-points.is-positive { color: var(--gold); }
.bilan-points.is-negative { color: var(--wrong-color); }
.bilan-points.is-zero { color: color-mix(in srgb, var(--text-main) 50%, transparent); }
.bilan-result-card .bilan-search-btn { width: 40px; height: 40px; opacity: 0.72; }
.bilan-result-card .bilan-search-btn:hover { opacity: 1; }
.bilan-question-text { margin: 0 0 var(--space-3); color: color-mix(in srgb, var(--text-main) 92%, transparent); font-size: var(--text-md); font-weight: var(--weight-medium); line-height: 1.48; }
.bilan-answer-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.bilan-answer-grid.single { grid-template-columns: 1fr; }
.bilan-answer-block { min-width: 0; padding: var(--space-3) var(--space-3); border-radius: var(--radius-md); background: color-mix(in srgb, var(--shadow-base) 20%, transparent); border: 1px solid var(--surface-3); }
.bilan-answer-block span { display: block; margin-bottom: var(--space-1); color: color-mix(in srgb, var(--text-main) 52%, transparent); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.8px; text-transform: uppercase; }
.bilan-answer-block strong { display: block; overflow-wrap: anywhere; color: white; font-size: var(--text-sm); line-height: 1.35; }
.bilan-answer-block.is-user-wrong strong { color: var(--wrong-color); text-decoration: line-through; text-decoration-thickness: 1px; }
.bilan-answer-block.is-correction { border-color: color-mix(in srgb, var(--gold) 20%, transparent); background: color-mix(in srgb, var(--gold) 6.5%, transparent); }
.bilan-answer-block.is-correction strong, .bilan-answer-block.is-correct-answer strong { color: var(--gold); }
.bilan-thumb-container { width: 76px; height: 58px; margin: 0 0 var(--space-3); }
.bilan-empty, .bilan-limit { padding: var(--space-6) var(--space-4); color: color-mix(in srgb, var(--text-main) 58%, transparent); text-align: center; border: 1px dashed var(--border); border-radius: var(--radius-md); }
.bilan-limit { padding: var(--space-4); font-size: var(--text-sm); }

@media (max-width: 650px) {
    .bilan-overview { padding: var(--space-4); }
    .bilan-overview-grid { grid-template-columns: 1fr 1fr; }
    .bilan-score-panel { grid-column: 1 / -1; }
    .bilan-score-panel, .bilan-stat-panel { min-height: 90px; padding: var(--space-4); }
    .bilan-result-card { padding: var(--space-4) var(--space-4); }
    .bilan-answer-grid { grid-template-columns: 1fr; }
    .bilan-result-head { align-items: flex-start; }
    .bilan-filters { flex-wrap: wrap; }
    .bilan-filters input { flex-basis: calc(100% - 32px); }
    .bilan-filters select { margin-left: var(--space-6); }
}

/* Contrôle du volume persistant */
.global-volume-control {
    --volume-percent: 50%;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 280px;
    /* 44px comme le lien Discord et les deux boutons ronds du bandeau. */
    min-height: var(--control-h-md);
    padding: var(--space-2) var(--space-4);
    color: white;
    background: linear-gradient(135deg, color-mix(in srgb, var(--gold-tint) 18%, transparent), var(--surface-2));
    border: 1px solid color-mix(in srgb, var(--gold) 58%, transparent);
    /* Pilule : le bandeau bas est un groupe de chrome a lui seul (lien
       Discord en pilule + deux boutons ronds) ; le slider s'y aligne. */
    border-radius: var(--radius-pill);
    box-shadow: 0 8px 26px color-mix(in srgb, var(--shadow-base) 28%, transparent), 0 0 18px color-mix(in srgb, var(--gold-tint) 10%, transparent);
}
.global-volume-icon { display: flex; align-items: center; color: var(--gold); flex-shrink: 0; }
.global-volume-control label { color: var(--gold); font-size: var(--text-xs); font-weight: var(--weight-impact); letter-spacing: var(--tracking-ui); }
.global-volume-control output { min-width: 38px; color: white; font-size: var(--text-sm); font-weight: var(--weight-bold); text-align: right; }
.global-volume-control input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: 140px;
    height: 10px;
    margin: 0;
    border-radius: 99px;
    background: linear-gradient(to right, var(--gold) 0 var(--volume-percent), var(--border) var(--volume-percent) 100%);
    cursor: pointer;
}
.global-volume-control input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 24px;
    height: 24px;
    border: 3px solid var(--surface-solid-2);
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 0 2px var(--gold), 0 0 16px color-mix(in srgb, var(--gold) 55%, transparent);
}
.global-volume-control input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border: 3px solid var(--surface-solid-2);
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 0 2px var(--gold), 0 0 16px color-mix(in srgb, var(--gold) 55%, transparent);
}
.global-volume-control input[type="range"]:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--gold) 50%, transparent);
    outline-offset: 5px;
}

/* Settings icon is now global in footer */
.settings-icon {
    cursor: pointer;
    transition: transform 0.4s var(--ease-standard),
                background var(--dur-base) ease,
                border-color var(--dur-base) ease,
                box-shadow var(--dur-base) ease;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: color-mix(in srgb, var(--text-main) 60%, transparent);
    position: relative;
    margin: 0;
    flex-shrink: 0;
}

.settings-icon:hover {
    background: color-mix(in srgb, var(--gold) 10%, transparent);
    border-color: color-mix(in srgb, var(--gold) 40%, transparent);
    color: var(--gold);
    transform: rotate(72deg);
    box-shadow: 0 0 16px color-mix(in srgb, var(--gold) 15%, transparent);
}

/* Settings Modal */
.settings-modal {
    position: fixed;
    top: 20px;
    right: 20px;
    background: var(--bg-card);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-md);
    padding: var(--space-5);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    box-shadow: var(--glass-shadow);
    transform: translateY(-10px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    /* Transition explicite (pas "all") : visibility bascule en 0s a l'ouverture
       pour que trapFocus puisse focaliser l'element des l'ajout de .active, et
       seulement apres le fondu a la fermeture (sinon focus() echoue). */
    transition: opacity var(--dur-base) ease, transform var(--dur-base) ease, visibility 0s linear var(--dur-base);
    z-index: var(--z-popover);
    /* NE PAS borner la largeur ici : `.settings-modal` est la classe de base de
       14 modales (#info-modal 600px, #profile-modal 520px…), pas seulement du
       panneau Réglages. Le correctif de débordement mobile est scopé à
       #settings-modal, plus bas. */
    min-width: 320px;
    text-align: left;
}

.settings-modal.active {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity var(--dur-base) ease, transform var(--dur-base) ease, visibility 0s;
}

#info-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.95);
    width: 90%;
    max-width: 600px;
    /* Repli vh d'abord : sur un moteur sans svh la ligne suivante est invalide
       et sans elle la modale n'aurait plus aucune borne de hauteur. svh (petit
       viewport, barre d'URL déployée) plutôt que dvh : dvh se recalcule pendant
       que la barre se rétracte et fait tressauter la modale en plein défilement. */
    max-height: 85vh;
    max-height: 85svh;
    overflow-y: auto;
    text-align: left;
}

#info-modal.active {
    transform: translate(-50%, -50%) scale(1);
}

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: color-mix(in srgb, var(--shadow-base) 70%, transparent);
    backdrop-filter: blur(5px);
    z-index: var(--z-overlay);
    opacity: 0;
    visibility: hidden;
    /* Transition explicite (pas "all") : visibility bascule en 0s a l'ouverture
       pour que trapFocus puisse focaliser l'element des l'ajout de .active. */
    transition: opacity var(--dur-base) ease, visibility 0s linear var(--dur-base);
}

.modal-overlay.active {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--dur-base) ease, visibility 0s;
}

/* ===== Lightbox image (game.zoomImage, ui.js) ===== */
.lightbox-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    /* No black-alpha ladder defined this stage (map REVIEW gap) — left raw. */
    background: color-mix(in srgb, var(--shadow-base) 90%, transparent);
    z-index: var(--z-lightbox);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
    animation: fadeIn var(--dur-base) ease;
}

.lightbox-img {
    max-width: 90%;
    max-height: 90%;
    border-radius: var(--radius-sm);
    box-shadow: 0 0 50px color-mix(in srgb, var(--shadow-base) 50%, transparent);
}

.lightbox-close {
    position: absolute;
    top: var(--space-5);
    right: var(--space-5);
    color: var(--text-main);
    font-size: var(--text-2xl);
}

.settings-modal h3 {
    font-size: var(--text-lg);
    margin-bottom: 1.2rem;
    color: var(--gold);
    border-bottom: 1px solid var(--border);
    padding-bottom: var(--space-2);
}

.settings-close-btn {
    margin-top: var(--space-4);
    padding: var(--space-2);
    width: 100%;
}

/* ===== Modale "Concept du jeu" ===== */
.info-title {
    font-size: var(--text-xl);
    border-bottom-color: var(--gold);
}

.info-content {
    font-weight: var(--weight-display);
    line-height: 1.6;
    color: var(--text-main);
}

.info-intro,
.info-footer-note {
    margin-bottom: var(--space-5);
}

.info-footer-note {
    font-size: var(--text-md);
    font-style: italic;
    color: var(--text-muted);
    margin-bottom: 0;
}

.info-section {
    margin-bottom: var(--space-5);
}

.info-section-title {
    color: var(--gold);
    margin-bottom: var(--space-2);
    text-transform: uppercase;
    font-size: var(--text-md);
    letter-spacing: 1px;
}

.info-list {
    list-style: none;
    padding-left: 0;
}

.info-list-item {
    margin-bottom: var(--space-3);
}

.info-list-label {
    color: var(--gold);
}

.info-mode-intro {
    font-size: var(--text-md);
    margin-bottom: var(--space-3);
}

.info-mode-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-3);
    text-align: center;
}

.info-mode-card {
    background: var(--surface-2);
    padding: var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
}

.info-mode-name {
    display: block;
    color: var(--gold);
}

.info-mode-pts {
    font-size: var(--text-sm);
}

.info-supercash-note {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin-top: var(--space-3);
}

.info-close-btn {
    margin-top: var(--space-6);
    width: 100%;
}

/* ===== Modale recherche ===== */
#search-modal {
    max-width: 600px;
    max-height: 80vh;
    max-height: 80svh;
    display: none;
    flex-direction: column;
}

.search-results-list {
    overflow-y: auto;
    flex-grow: 1;
    margin: var(--space-4) 0;
    padding-right: var(--space-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.search-close-btn {
    margin-top: auto;
    width: 100%;
}

/* ===== Modale login joueur ===== */
#player-auth-modal {
    max-width: 380px;
}

/* ===== Modale Mon profil (shell — le contenu vient de profile.js) ===== */
/* En-tête figé, corps défilant — même structure que #daily-lb-modal. Avant, la
   modale ENTIÈRE défilait : sur un profil fourni, le titre et la croix de
   fermeture sortaient du champ et il fallait remonter pour fermer. */
#profile-modal {
    width: min(94vw, 640px);
    max-width: 640px;
    max-height: 88vh;
    max-height: 88svh;
    display: flex;
    flex-direction: column;
    overflow: hidden;   /* le défilement se fait dans #profile-body */
}

#profile-body {
    /* min-height: 0 — sans lui, un enfant flex refuse de se comprimer et déborde
       au lieu de défiler (même verrou que #cat-list). */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* overflow-y: auto seul fait passer overflow-x à auto : une carte un peu large
       ajouterait une seconde barre, horizontale, dans la modale. */
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

#profile-modal h3 {
    margin: 0;
}

.profile-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-2);
}

.modal-icon-close-btn {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: var(--text-lg);
    cursor: pointer;
    line-height: 1;
    /* 20x17px sans ca : sous le minimum de 24x24 de la WCAG 2.5.8.
       Passe a 44px (echelle icone) — un coin de modale a la place. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    min-width: var(--control-icon);
    min-height: var(--control-icon);
}

/* « Fermer » en tête des panneaux admin (index.html, .modal-top-bar) : collé en haut de
   la modale quand c'est elle qui défile (modal--scroll-*), pour ne plus descendre au
   bouton du bas. Le fond reprend celui de la modale : le contenu passe dessous. */
.modal-top-bar {
    position: sticky;
    top: calc(-1 * var(--space-5));
    z-index: var(--z-raised);
    display: flex;
    justify-content: flex-end;
    margin: calc(-1 * var(--space-5)) calc(-1 * var(--space-5)) var(--space-2);
    padding: var(--space-3) var(--space-5) var(--space-2);
    background: var(--surface-solid-1);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.modal-top-close {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--control-h-sm);
    padding: 0 var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 1px;
    cursor: pointer;
}
.modal-top-close:hover { border-color: var(--gold); color: var(--gold); }

.setting-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    cursor: pointer;
    font-size: var(--text-base);
    color: var(--text-main);
}

.setting-item input[type="checkbox"] {
    accent-color: var(--gold);
    width: 18px;
    height: 18px;
}

.setting-item input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

        /* Grille du sélecteur de thèmes (ui.js). Seule survivante du bloc
           « Theme Selection » : .theme-search-*, .theme-btn, .theme-select,
           .theme-selection-footer, .qualifs-divider, .home-footer et
           .discord-mini-* ne sont produits par aucun HTML/JS depuis la
           réécriture du sélecteur (.theme-card-sq / .sel-action-btn). */
        .theme-grid {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: var(--space-4);
            width: 100%;
            max-width: 800px;
            margin: 0 auto;
        }

#discord-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-5);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    color: color-mix(in srgb, var(--text-main) 60%, transparent);
    text-decoration: none;
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    transition: all var(--dur-base) var(--ease-standard);
    margin: 0;
}

#discord-link, #discord-link:visited, #discord-link span, #discord-link:visited span {
    color: color-mix(in srgb, var(--text-main) 60%, transparent);
    text-decoration: none !important;
}

#discord-link:hover {
    background: color-mix(in srgb, var(--discord) 15%, transparent) !important;
    border-color: color-mix(in srgb, var(--discord) 60%, transparent) !important;
    color: var(--discord) !important;
    transform: translateY(-2px) !important;
    box-shadow: 0 6px 20px color-mix(in srgb, var(--discord) 20%, transparent) !important;
}

#discord-link:hover span {
    color: var(--discord) !important;
}

.discord-badge svg {
    display: block;
    fill: currentColor;
    transition: transform var(--dur-base) ease;
}

.discord-badge:hover svg {
    transform: scale(1.1);
}

.global-footer {
    margin-top: 5rem;
    padding: var(--space-7) 0;
    border-top: 1px solid var(--surface-1);
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-4);
    width: 100%;
    position: relative;
    z-index: var(--z-raised);
    /* Transition fluide par défaut */
    opacity: 1;
    transition: opacity 0.6s ease;
}

.footer-key-btn {
    background: color-mix(in srgb, var(--gold-tint) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 40%, transparent);
    color: var(--gold);
    width: var(--control-icon);
    height: var(--control-icon);
    border-radius: 50%;
    font-size: var(--text-base);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--dur-base) var(--ease-standard);
}

.credits-line {
    text-align: center;
    font-size: var(--text-xs);
    color: color-mix(in srgb, var(--text-main) 35%, transparent);
    margin: 0 0 var(--space-5);
}

/* Lien de confidentialite dans la ligne de credits. Il herite du gris a 35 %
   de .credits-line, illisible pour une cible cliquable : la couleur est donc
   remontee, et le survol passe a l'or. Le point separateur est aria-hidden,
   un lecteur d'ecran n'annonce pas une puce decorative. */
.credits-link {
    color: color-mix(in srgb, var(--text-main) 55%, transparent);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color var(--dur-fast) var(--ease-standard),
                border-color var(--dur-fast) var(--ease-standard);
}

.credits-link:hover,
.credits-link:focus-visible {
    color: var(--gold);
    border-bottom-color: var(--gold);
}

.credits-sep {
    margin: 0 var(--space-1);
}

@media (max-width: 680px) {
    .global-footer { padding: var(--space-6) var(--space-3); gap: var(--space-3) !important; }
    .global-volume-control { order: -1; width: min(100%, 360px); min-width: 0; }
    .global-volume-control input[type="range"] { flex: 1; width: auto; min-width: 90px; }
    .discord-badge span { display: none; }
}

.global-footer.footer-dimmed {
    opacity: 0.15;
    transition: opacity var(--dur-fast) ease;
    pointer-events: none;
}

.qpt-badge {
    display: inline-block;
    background: color-mix(in srgb, var(--gold-tint) 10%, transparent);
    border: 1px solid var(--gold);
    color: var(--gold);
    padding: var(--space-1) var(--space-3);
    border-radius: 20px;
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
    letter-spacing: 1px;
    pointer-events: none;
    margin-bottom: var(--space-2);
    box-shadow: 0 0 10px color-mix(in srgb, var(--gold-tint) 10%, transparent);
}

.question-meta {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--space-4);
    background: var(--surface-1);
    border: 1px solid var(--border);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin: 0 auto var(--space-4);
    font-family: 'Outfit', sans-serif;
    letter-spacing: 0.5px;
    width: fit-content;
}

/* In-game footer meta bar: was inline style="…" in index.html, overriding
   the two rules above (ID beats class, so this wins regardless of which
   duplicate .question-meta declaration is cascade-last). */
#question-meta {
    margin-top: auto;
    margin-bottom: -1rem;
    opacity: 0.5;
    font-size: var(--text-xs);
    border: none;
    background: transparent;
    flex-direction: column;
    gap: 0;
}

.q-meta-row {
    display: flex;
    gap: var(--space-4);
    align-items: center;
}

@media (max-width: 768px) {
    /* backdrop-filter force une couche de compositing relue a chaque frame :
       10-25 ms/frame sur GPU mobile d'entree de gamme. Derriere un overlay quasi
       opaque le rendu est identique, donc on le coupe sous 768px. */
    .phase-card,
    .game-header,
    .settings-modal,
    .modal-overlay {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }

    /* --bg-card est translucide (alpha .65) : il compte sur le flou pour rester
       lisible. Le flou coupé juste au-dessus, le titre de la page et le classement
       traversaient la modale. Fond opaque, réservé au même palier. */
    .settings-modal {
        background: var(--surface-solid-2);
    }

    .container {
        padding: var(--space-5);
    }

    .home-header h1 {
        /* Le clamp gere deja le petit ecran (2.6rem plancher) ; forcer
           --text-display (3rem) ici le rabaissait sous son propre plancher.
           Le plafond en vh ne mord qu'en paysage, ou 14.5vw reste large
           pendant que la hauteur tombe sous 400px. */
        font-size: min(clamp(2.6rem, 14.5vw, 4.5rem), 13vh);
        font-size: min(clamp(2.6rem, 14.5vw, 4.5rem), 13svh);
    }

    /* Signalement joueur (« soucis pour scroller ») et mesure sur un 360×640 :
       `min-height: 600px` l'emporte sur `max-height: 85vh` (544px à cette hauteur)
       — c'est la règle de résolution CSS, le minimum gagne. La boîte restait donc
       figée à 600px pendant que son contenu en demandait 798, et les 200px de trop
       étaient CLIPPÉS : #feedback-msg (« la bonne réponse était… ») et #question-meta
       n'étaient plus peints du tout. document.elementFromPoint rendait BODY à leur
       place. Scroller la PAGE déplaçait la boîte sans révéler son débordement, et sa
       barre de scroll est masquée : aucune affordance.
       Sous 768px la boîte reprend donc sa hauteur naturelle et c'est la page qui
       défile — un seul scroll, visible. Même parti pris que la règle paysage
       `max-height: 520px` plus bas. */
    .quiz-area {
        padding: var(--space-7) var(--space-5);
        min-height: 0;
    }

    .question-text {
        font-size: 1.4rem;
    }

    .options-grid {
        grid-template-columns: 1fr;
    }

    .modes-grid {
        flex-direction: column;
        gap: var(--space-3);
    }

    .mode-btn {
        max-width: none;
        min-height: 70px;
    }

    .theme-search-container {
        flex-direction: column;
    }

    .game-header {
        flex-direction: column;
        gap: var(--space-4);
        text-align: center;
    }

    .phases-grid, .theme-grid {
        grid-template-columns: minmax(0, 1fr) !important;
    }
}

/* Écran court (ex. téléphone en paysage, 812×375) : le plancher de 600px
   et le scroll interne poussaient les boutons de réponse hors champ.
   On repasse en flux naturel de la page (scroll du document) plutôt
   qu'un scroll interne à .quiz-area, et on resserre le padding. Placé
   après le bloc max-width:768px pour gagner sur .quiz-area même quand
   les deux media queries matchent (portrait étroit ET court). */
@media (max-height: 520px) {
    .quiz-area {
        min-height: 0;
        padding: var(--space-5) var(--space-4);
    }

    /* Le correctif jumeau du bloc `max-width: 768px` : un iPhone en paysage fait
       844×390, il passe DEVANT le seuil de largeur et n'était donc pas couvert.
       Mesuré à 844×390 : 11px de recouvrement du SUIVANT sur #question-meta. */
    .next-btn.active {
        position: static;
        align-self: flex-end;
        margin-top: var(--space-2);
    }

    /* Accueil, ecran tres court : on resserre encore l'en-tete. Les etats
       lourds de la carte du jour (« tentative interrompue », « score non
       transmis ») ajoutent une centaine de pixels sous le bouton — c'est eux
       qui fixent le budget ici, pas l'etat par defaut. */
    .home-header {
        margin-top: var(--space-1);
        margin-bottom: var(--space-3);
    }

    #screen-home .container { padding-top: var(--space-3); }
}

/* Ecran court ET large (telephone en paysage) : le fauteuil EMPILE sur le titre
   mangeait tout l'ecran. La largeur, elle, est abondante — on met la marque sur
   une seule ligne. Le palier de largeur n'est pas cosmetique : sans lui la
   regle attrapait aussi un iPhone SE 1re generation en Safari (320x454, court
   par la HAUTEUR), ou le flex-shrink ecrasait le fauteuil a 48x44px. Sous
   480px de large la colonne tient tres bien, mesuree a 423 < 454. */
@media (max-height: 520px) and (min-width: 480px) {
    .logo-container {
        flex-direction: row;
        justify-content: center;
        gap: var(--space-4);
    }

    /* `margin: 0 auto` en base : en flex ROW, les marges auto absorbent tout
       l'espace libre et poussaient le titre sous le bouton Connexion.
       `flex-shrink: 0` : le fauteuil est deja plafonne en vh, il n'a pas a
       ceder en plus a l'etroit. */
    .throne-image-container {
        margin: 0;
        flex-shrink: 0;
    }
}
/* Unified Theme Selection */
.theme-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5);
    margin-bottom: var(--space-6);
    width: 100%;
    max-width: 800px;
    margin-left: auto;
    margin-right: auto;
}

.theme-select-title {
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
    color: var(--text-main);
    margin-bottom: var(--space-2);
}

.theme-empty-result {
    grid-column: 1/-1;
    padding: var(--space-7);
    text-align: center;
    color: var(--text-muted);
    opacity: 0.6;
    font-style: italic;
    letter-spacing: 1px;
}

.theme-card-sq {
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-6) var(--space-5);
    cursor: pointer;
    /* Survol sans transform ni backdrop-filter : la carte soulevée (-8px, scale)
       quittait le curseur par le bas et clignotait entre survol et repos, le
       scale floutait le texte, et le flou d'arrière-plan d'une carte en
       mouvement laissait des bandes claires sur la voisine. */
    transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
    text-align: center;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 120px;
}

.theme-card-sq:hover {
    border-color: var(--gold);
    background: color-mix(in srgb, var(--gold-pure) 6%, var(--surface-1));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 35%, transparent),
                0 12px 28px color-mix(in srgb, var(--shadow-base) 40%, transparent);
}

.theme-card-sq h4 {
    margin: 0;
    font-size: var(--text-base);
    color: white;
    text-transform: uppercase;
    letter-spacing: 2px;
    font-weight: var(--weight-bold);
}

.selection-actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    max-width: 500px;
    margin: var(--space-5) auto;
}

.sel-action-btn {
    background: color-mix(in srgb, var(--bg-deep) 60%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md);
    color: var(--gold);
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--space-3);
    transition: all var(--dur-base) ease;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    letter-spacing: 1px;
    text-transform: uppercase;
    width: 100%;
}

.sel-action-btn:hover {
    border-color: var(--gold);
    background: color-mix(in srgb, var(--gold-pure) 8%, transparent);
}

.sel-action-btn .arrow {
    transition: transform var(--dur-base) ease;
    font-size: var(--text-xs);
}

.sel-action-btn.active .arrow {
    transform: rotate(180deg);
}

.collapsible-section {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    /* Transition explicite (pas "all") : visibility ne bascule qu'apres le
       repli, pour ne jamais laisser un contenu focusable mais invisible. */
    transition: max-height var(--dur-slow) var(--ease-standard), opacity var(--dur-slow) var(--ease-standard), margin-top var(--dur-slow) var(--ease-standard), padding-bottom var(--dur-slow) var(--ease-standard), visibility 0s linear var(--dur-slow);
    width: 100%;
}

.collapsible-section.active {
    max-height: 6000px;
    opacity: 1;
    visibility: visible;
    margin-top: var(--space-5);
    padding-bottom: var(--space-6);
    transition: max-height var(--dur-slow) var(--ease-standard), opacity var(--dur-slow) var(--ease-standard), margin-top var(--dur-slow) var(--ease-standard), padding-bottom var(--dur-slow) var(--ease-standard), visibility 0s;
}

.collapsible-section input {
    width: 100%;
    background: var(--surface-2);
    border: 1px solid var(--border);
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md);
    color: white;
    font-size: var(--text-base);
    font-family: inherit;
    outline: none;
    transition: all var(--dur-base) ease;
    text-align: center;
}

.collapsible-section input:focus-visible {
    border-color: var(--gold);
    background: color-mix(in srgb, var(--gold-pure) 5%, transparent);
    box-shadow: 0 0 20px color-mix(in srgb, var(--gold) 10%, transparent);
    outline: 2px solid var(--gold);
}

/* Nouveaux thèmes de la communauté (mise en avant 7 jours, cf. ui.js).
   La carte reprend .theme-card-sq et n'ajoute qu'un axe vertical : la pastille,
   le nom, l'auteur. Le liseré doré la sépare des suggestions sans introduire une
   seconde famille de cartes. */
.theme-card-sq--new {
    flex-direction: column;
    gap: var(--space-2);
    border-color: color-mix(in srgb, var(--gold) 45%, transparent);
    background: color-mix(in srgb, var(--gold-pure) 4%, var(--surface-1));
}

.theme-card-flag {
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: 2px;
    font-weight: var(--weight-bold);
    color: var(--bg-deep);
    background: var(--gold);
    border-radius: var(--radius-pill);
    padding: var(--space-1) var(--space-3);
}

/* Le pseudo est une donnée joueur de longueur libre, et .theme-card-sq porte
   `overflow: hidden` : sans césure il n'était pas débordé, il était COUPÉ.
   Mesuré : tient jusqu'à 25 caractères sur une carte de 262px, casse au-delà. */
.theme-card-by {
    font-size: var(--text-xs);
    color: var(--text-muted);
    letter-spacing: 1px;
    max-width: 100%;
    overflow-wrap: anywhere;
}

.selection-subtitle {
    color: var(--gold);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 3px;
    margin-bottom: var(--space-5);
    opacity: 0.6;
    font-weight: var(--weight-bold);
}

.theme-grid-mini {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-3);
    width: 100%;
}

.theme-card-mini {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    cursor: pointer;
    transition: all var(--dur-base) ease;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 70px;
}

.theme-card-mini:hover {
    background: color-mix(in srgb, var(--gold) 5%, transparent);
    border-color: var(--gold);
    transform: translateY(-3px);
}

.theme-card-mini h4 {
    font-size: var(--text-sm);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 0;
    color: color-mix(in srgb, var(--text-main) 80%, transparent);
}

/* Signalement de bug (360×705, Firefox Android) : la grille du catalogue débordait
   de la carte, et .collapsible-section (overflow:hidden) coupait la colonne de droite.
   Deux causes, corrigées ensemble.
   1. Une piste `1fr` vaut `minmax(auto, 1fr)` : elle ne descend jamais sous le
      min-content du plus long nom de thème (« VOCABULAIRE MARINS »). D'où le
      `minmax(0, 1fr)` partout sur ces grilles.
   2. La césure. `anywhere` et non `break-word` : seul `anywhere` réduit la taille
      MIN-CONTENT du bloc (CSS Text 3). Avec `break-word`, « IMPRESSIONNISTES » (le
      plus long mot du catalogue, 122px) restait insécable et ressortait de sa carte
      dès 320px — le `minmax(0, 1fr)` ci-dessus n'y peut rien, un item de grille garde
      `min-width: auto`. D'où aussi le `min-width: 0` sur la carte. Même choix que
      `.option-btn`. Hors media query : le rognage par overflow:hidden existe à
      toutes les largeurs, pas seulement sous 768px. */
.theme-card-mini,
.theme-card-sq {
    min-width: 0;
}

/* Thème déjà joué (ui.js, themePlayedMark) : coche discrète dans le coin, le détail
   (bonnes réponses) dans le title et dans le texte masqué du bouton. */
.theme-card-mini { position: relative; }
.theme-played {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--correct-color) 18%, transparent);
    color: var(--correct-color);
}
.theme-played .ui-icon { width: 14px; height: 14px; }

/* Case « Jouer avec chrono » de l'écran de choix du thème (ui.js). */
.theme-chrono-toggle {
    justify-content: center;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.theme-card-mini h4,
.theme-card-sq h4 {
    overflow-wrap: anywhere;
}

@media (max-width: 768px) {
    .theme-grid {
        grid-template-columns: minmax(0, 1fr);
    }
    .theme-grid-mini {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* À 360px, deux colonnes au gabarit d'origine ne tenaient pas de toute façon :
   sous 480px la carte du catalogue est resserrée. */
@media (max-width: 480px) {
    .theme-card-mini {
        padding: var(--space-3);
        min-height: 64px;
    }
    .theme-card-mini h4 {
        font-size: var(--text-xs);
        letter-spacing: 0.5px;
    }
}

/* Bilan Thumbnails */
.bilan-thumb-container {
    position: relative;
    width: 76px;
    height: 58px;
    margin: 0 0 var(--space-3);
}

.bilan-thumb-btn { display: block; width: 100%; height: 100%; padding: 0; border: 0; background: transparent; }

.bilan-thumb {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
    cursor: zoom-in;
    border: 1px solid var(--border);
    transition: transform var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}

.bilan-thumb:hover {
    transform: scale(1.1);
    box-shadow: 0 0 10px color-mix(in srgb, var(--gold-tint) 30%, transparent);
    border-color: var(--gold);
}

.bilan-zoom-icon {
    position: absolute;
    bottom: -2px;
    right: -2px;
    background: var(--gold);
    /* Hygiene des tokens : couleur de texte sur aplat --gold dediee, pas de noir brut. */
    color: var(--on-gold);
    width: 14px;
    height: 14px;
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    box-shadow: 0 2px 4px color-mix(in srgb, var(--shadow-base) 30%, transparent);
}

.bilan-zoom-icon svg {
    width: 10px;
    height: 10px;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ── Score Reveal Card (fin de manche) ──────────────────── */
.score-reveal-card {
    margin: var(--space-5) auto 0;
    max-width: 380px;
    width: 100%;
    background: var(--surface-1);
    border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
    border-radius: var(--radius-md);
    padding: var(--space-7) var(--space-6) var(--space-6);
    text-align: center;
    box-shadow: 0 0 40px color-mix(in srgb, var(--gold) 6%, transparent), inset 0 0 20px color-mix(in srgb, var(--shadow-base) 20%, transparent);
    animation: scoreCardEnter var(--dur-slow) var(--ease-decelerate) forwards;
}

@keyframes scoreCardEnter {
    from { opacity: 0; transform: translateY(20px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.score-reveal-label {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    text-transform: uppercase;
    letter-spacing: 4px;
    color: var(--text-muted);
    margin-bottom: var(--space-3);
}

.score-reveal-number {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

#score-counter {
    font-size: clamp(4rem, 12vw, 6rem);
    font-weight: var(--weight-bold);
    color: var(--gold);
    line-height: 1;
    letter-spacing: -2px;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 30px color-mix(in srgb, var(--gold) 40%, transparent);
    transition: text-shadow 0.1s ease;
}

.score-reveal-pts {
    font-size: 1.4rem;
    font-weight: var(--weight-display);
    color: var(--gold);
    opacity: 0.7;
    letter-spacing: 2px;
    text-transform: uppercase;
}

.score-reveal-record {
    font-size: var(--text-md);
    color: var(--text-muted);
    font-weight: var(--weight-display);
    letter-spacing: 0.5px;
}

.score-reveal-record strong {
    color: color-mix(in srgb, var(--text-main) 80%, transparent);
    font-weight: var(--weight-medium);
}

.new-record-badge {
    display: inline-block;
    background: linear-gradient(135deg, color-mix(in srgb, var(--gold-tint) 15%, transparent), color-mix(in srgb, var(--gold-pure) 8%, transparent));
    border: 1px solid color-mix(in srgb, var(--gold-tint) 50%, transparent);
    color: var(--gold);
    padding: var(--space-1) var(--space-4);
    border-radius: 20px;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    letter-spacing: 1px;
    text-transform: uppercase;
    animation: recordPulse 1.2s ease-in-out infinite alternate;
}

@keyframes recordPulse {
    from { box-shadow: 0 0 8px color-mix(in srgb, var(--gold-tint) 20%, transparent); }
    to   { box-shadow: 0 0 20px color-mix(in srgb, var(--gold-tint) 50%, transparent); }
}
/* ── Accessibility: Reduced Motion ───────────────────────── */
/* Transitions à 0s, PAS 0.01ms (audit 2026-10-15) : 0.01ms crée une vraie transition, et le
   `visibility 0s` des boutons et modales (« Suivant », confirm, overlays) devenait une
   transition qui vaut « hidden » jusqu'à la frame suivante. Un focus() en setTimeout(0)
   frappait un élément encore caché : focus perdu après chaque réponse, et hors du dialogue
   de confirmation. À 0s, avec le délai à 0s de la règle jumelle de components.css, aucune
   transition n'est créée. Conséquence : aucun `transitionend` sous mouvement réduit — n'en
   attendre aucun dans le code. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0s !important;
        scroll-behavior: auto !important;
    }
}

/* ── Settings Button Replacement ────────────────────────── */
.settings-btn {
    background: var(--surface-1);
    border: 1px solid var(--border);
    color: var(--text-muted);
    width: var(--control-icon);
    height: var(--control-icon);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--dur-base) ease;
    padding: 0;
}

.settings-btn:hover {
    background: var(--surface-3);
    border-color: var(--gold);
    color: var(--gold);
    transform: rotate(45deg);
}

/* ── Input Focus Overrides ─────────────────────────────── */
/* .theme-search-input et .theme-select retirés : sélecteurs fantômes depuis la
   réécriture du sélecteur de thèmes, cette règle ne s'appliquait qu'au 3e. */
.collapsible-section input:focus {
    outline: 2px solid var(--gold) !important;
    outline-offset: 2px !important;
}

/* Search & Stats */
.search-result-item:hover {
    border-color: var(--gold) !important;
    background: color-mix(in srgb, var(--gold-tint) 10%, transparent) !important;
    transform: translateX(5px);
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(-5px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ── Next Button & Timer ───────────────────────────────── */
.next-btn {
    position: absolute;
    bottom: 3rem;
    right: 3rem;
    background: var(--gold);
    color: black;
    border: none;
    min-height: var(--control-h-lg);
    padding: var(--space-4) var(--space-7);
    border-radius: var(--radius-btn);
    font-weight: var(--weight-impact);
    font-size: var(--text-base);
    text-transform: uppercase;
    letter-spacing: var(--tracking-cta);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(20px);
    /* Transition explicite (pas "all") : visibility bascule en 0s a l'ouverture
       pour que focusNextBtn puisse focaliser le bouton des l'ajout de .active. */
    transition: opacity var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), transform var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), visibility 0s linear var(--dur-slow);
    box-shadow: 0 10px 40px color-mix(in srgb, var(--gold-tint) 40%, transparent);
    z-index: var(--z-modal);
}

.next-btn.active {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), transform var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow var(--dur-slow) cubic-bezier(0.175, 0.885, 0.32, 1.275), visibility 0s;
}

.next-btn:hover {
    transform: scale(1.08) translateY(-5px);
    box-shadow: 0 20px 50px color-mix(in srgb, var(--gold-tint) 60%, transparent);
}

/* Ancien widget timer (.timer-bar-bg / .timer-bar-fill, bottom/left) supprime :
   son markup n'existe plus (index.html porte .next-timer-bar). Il redeclarait
   .next-timer-container et ses valeurs fuyaient sur la barre vivante :
   left:3rem + width:100% la faisaient deborder de 47px hors de .quiz-area. */

/* Sous 768px, .quiz-area n'est plus une boîte à hauteur imposée (cf. la règle
   `min-height: 0` plus haut) : elle épouse son contenu. Un bouton `position:
   absolute` calé sur `bottom` vient alors se poser SUR la dernière ligne du flux
   — mesuré : 24px de recouvrement sur #question-meta, le SUIVANT masquait l'auteur
   de la question. Tant que la boîte était plus haute que son contenu, l'espace mort
   du bas cachait le problème.
   Le passage en flux est réservé à `.active`, et c'est le point à ne pas perdre :
   au repos le bouton est `visibility: hidden` mais garde sa boîte. Le mettre en
   `static` sans condition lui faisait réserver 52px de vide au bas de CHAQUE écran
   mobile — sélection de thème, choix du mode, question posée — pour un bouton
   invisible (mesuré). Hors flux tant qu'il ne sert pas, dans le flux dès qu'il
   s'affiche. */
@media (max-width: 768px) {
    .next-btn {
        bottom: 1.5rem;
        right: 1.5rem;
        padding: var(--space-3) var(--space-5);
        font-size: var(--text-md);
    }

    .next-btn.active {
        position: static;
        align-self: flex-end;
        margin-top: var(--space-2);
    }
}

/* ── Simulation Mode HUD & Styling ──────────────────────── */
.btn-simulation {
    background: linear-gradient(135deg, var(--backstage) 0%, var(--backstage-2) 100%);
    color: var(--text-main) !important;
    border: none;
    box-shadow: 0 0 20px var(--backstage-glow);
    font-weight: var(--weight-medium);
}

.btn-simulation:hover {
    transform: translateY(-3px);
    box-shadow: 0 0 30px var(--backstage-glow-strong);
    background: linear-gradient(135deg, var(--backstage) 0%, var(--backstage-2) 100%);
}

.simulation-hud {
    width: 100%;
    max-width: 750px;
    padding: var(--space-5) var(--space-6);
    border-radius: var(--radius-md);
    background: var(--backstage-wash);
    border: 1px solid var(--backstage-border);
    display: none;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
    box-shadow: 0 10px 30px var(--backstage-wash), inset 0 0 15px var(--backstage-wash-faint);
    backdrop-filter: blur(var(--blur-sm));
    -webkit-backdrop-filter: blur(var(--blur-sm));
    animation: screenEnter var(--dur-base) var(--ease-decelerate);
}

.simulation-hud.active {
    display: flex;
}

.hud-pulse {
    width: var(--space-3);
    height: var(--space-3);
    background: var(--backstage);
    border-radius: var(--radius-pill);
    display: inline-block;
    box-shadow: 0 0 10px var(--backstage);
    animation: pulse 1.5s infinite alternate;
}

@keyframes pulse {
    0% { transform: scale(1); opacity: 0.5; box-shadow: 0 0 5px var(--backstage); }
    100% { transform: scale(1.2); opacity: 1; box-shadow: 0 0 15px var(--backstage), 0 0 25px var(--backstage); }
}

.sim-speed-btn {
    background: var(--surface-1);
    border: 1px solid var(--border);
    color: var(--text-muted);
    font-size: var(--text-xs);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: all var(--dur-base) var(--ease-standard);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: var(--weight-bold);
}

.sim-speed-btn:hover {
    border-color: var(--backstage);
    color: var(--text-main);
}

.sim-speed-btn.active {
    background: linear-gradient(135deg, var(--backstage), var(--backstage-2));
    border-color: transparent;
    color: var(--text-main);
    box-shadow: 0 0 10px var(--backstage-glow);
}

.sim-control-btn {
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-size: var(--text-xs);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all var(--dur-base) var(--ease-standard);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 0;
}

.sim-control-btn:hover {
    background: var(--backstage-tint);
    border-color: var(--backstage);
    transform: translateY(-1px);
}

.sim-control-btn.active {
    background: color-mix(in srgb, var(--wrong-color) 20%, transparent);
    border-color: var(--wrong-color);
}

/* ===== MODE ADMIN ===== */
/* La barre admin est position:fixed bottom:0 — réserver l'espace pour ne pas
   masquer le bas du contenu d'accueil (toggle via adminInit). */
body.admin-active { padding-bottom: 140px; }

.admin-icon-bar {
    display: flex;
    gap: var(--space-2);
    justify-content: flex-end;
    margin-top: var(--space-3);
    padding: 0 var(--space-1);
}
.admin-icon-btn {
    background: color-mix(in srgb, var(--gold-tint) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 30%, transparent);
    border-radius: var(--radius-btn);
    color: var(--gold);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    letter-spacing: 0.3px;
    padding: var(--space-2) var(--space-3);
    transition: background var(--dur-fast);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}
.admin-icon-btn:hover { background: color-mix(in srgb, var(--gold-tint) 25%, transparent); }
.admin-icon-btn.danger { border-color: color-mix(in srgb, var(--wrong-soft) 40%, transparent); color: var(--wrong-color); }
.admin-icon-btn.danger:hover { background: color-mix(in srgb, var(--wrong-soft) 15%, transparent); }

.cat-item {
    flex-shrink: 0;
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.cat-item-text { flex: 1; font-size: var(--text-md); color: color-mix(in srgb, var(--text-main) 85%, transparent); }
.cat-item-meta { font-size: var(--text-xs); color: var(--gold); font-weight: var(--weight-bold); letter-spacing: 0.5px; white-space: nowrap; }
.cat-item-id { font-size: var(--text-xs); color: var(--text-muted); font-weight: var(--weight-medium); white-space: nowrap; }
.cat-item-ro { font-size: var(--text-xs); color: var(--text-muted); font-style: italic; white-space: nowrap; opacity: 0.8; padding: 0 var(--space-2); }

/* Réordonnancement (↑↓) dans un thème */
.cat-move { display: flex; flex-direction: column; gap: var(--space-1); flex-shrink: 0; }
/* Taille de cible WCAG 2.5.8 : 24x24 minimum meme pour une icone compacte. */
.cat-move-btn { min-width: 24px; min-height: 24px; padding: 0; }
.cat-move-btn:disabled { opacity: 0.25; cursor: default; }
.cat-move-btn:disabled:hover { background: color-mix(in srgb, var(--gold-tint) 12%, transparent); }

/* Libellé de section dans un thème (DUO / CARRÉ…) */
.cat-section-label {
    font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 1.5px;
    color: var(--text-muted); text-transform: uppercase;
    margin: var(--space-2) var(--space-1) var(--space-1); padding-top: var(--space-1);
}
.cat-section-label:first-child { margin-top: 0; }

/* En-tête de bloc dans les résultats de recherche */
.cat-search-section {
    font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: 1px;
    color: var(--gold); text-transform: uppercase;
    margin: var(--space-4) var(--space-1) var(--space-2);
}
.cat-search-section:first-child { margin-top: 0; }
.cat-empty { color: var(--text-muted); opacity: 0.6; font-style: italic; padding: var(--space-5); text-align: center; }

/* Éditeur admin de la partie du jour */
.adp-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    padding: var(--space-5) var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
}
.adp-eyebrow {
    display: block;
    margin-bottom: var(--space-1);
    color: color-mix(in srgb, var(--gold) 65%, transparent);
    font-size: var(--text-2xs);
    font-weight: var(--weight-impact);
    letter-spacing: 1.8px;
    text-transform: uppercase;
}
#admin-daily-modal h3,
#admin-audience-modal h3,
#special-admin-modal h3 {
    margin: 0;
    padding: 0;
    color: white;
    border: 0;
    font-size: var(--text-lg);
    line-height: 1.2;
}
.adp-day-switch.adp-day-switch--3 { grid-template-columns: 1fr 1fr 1fr; }
.adp-close {
    width: 38px;
    height: 38px;
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    color: color-mix(in srgb, var(--text-main) 55%, transparent);
    background: var(--surface-2);
    border: 1px solid var(--surface-3);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: color var(--dur-fast) ease, background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.adp-close:hover { color: white; background: var(--surface-3); border-color: var(--border); }
.adp-context-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
}
.adp-day-switch {
    display: inline-grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-1);
    padding: var(--space-1);
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
}
.adp-day-btn {
    min-height: 32px;
    padding: var(--space-2) var(--space-3);
    color: color-mix(in srgb, var(--text-main) 50%, transparent);
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    cursor: pointer;
}
.adp-day-btn:hover { color: color-mix(in srgb, var(--text-main) 85%, transparent); }
.adp-day-btn.is-active { color: var(--on-gold); background: var(--gold); box-shadow: 0 3px 12px color-mix(in srgb, var(--gold-tint) 20%, transparent); }
/* Bande de 8 jours (aujourd'hui + 7) : jour court au-dessus, quantième dessous, pastille or si un plan existe. */
#admin-daily-days { grid-template-columns: repeat(8, minmax(36px, 1fr)); max-width: 100%; overflow-x: auto; }
#admin-daily-days .adp-day-btn { position: relative; display: grid; gap: 1px; justify-items: center; padding: var(--space-1) var(--space-2); line-height: 1.1; }
#admin-daily-days .adp-day-btn span { font-size: var(--text-xs); font-weight: var(--weight-medium); text-transform: capitalize; }
#admin-daily-days .adp-day-btn b { font-size: var(--text-sm); }
#admin-daily-days .adp-day-btn.has-plan::after { content: ""; position: absolute; top: var(--space-1); right: var(--space-1); width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--gold); }
#admin-daily-days .adp-day-btn.has-plan.is-active::after { background: var(--on-gold); }
.adp-meta { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-4); min-width: 0; }
.adp-meta > div { display: flex; align-items: baseline; justify-content: flex-end; gap: var(--space-2); min-width: 0; }
.adp-meta strong { overflow: hidden; color: color-mix(in srgb, var(--text-main) 88%, transparent); font-size: var(--text-sm); text-overflow: ellipsis; white-space: nowrap; }
.adp-meta > div > span { color: color-mix(in srgb, var(--text-main) 38%, transparent); font-size: var(--text-xs); white-space: nowrap; }
.adp-status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-2);
    border: 1px solid currentColor;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    white-space: nowrap;
}
.adp-status > span { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.adp-status-on { color: var(--correct-color); background: color-mix(in srgb, var(--correct-color) 8%, transparent); }
.adp-status-draft { color: var(--gold); background: color-mix(in srgb, var(--gold-warm) 8%, transparent); }
.adp-status-auto { color: color-mix(in srgb, var(--text-main) 45%, transparent); background: var(--surface-1); }
.adp-tabs {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
    padding: 0 var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
}
.adp-tab {
    position: relative;
    min-width: 0;
    padding: var(--space-3) 38px var(--space-3) var(--space-3);
    color: color-mix(in srgb, var(--text-main) 52%, transparent);
    text-align: left;
    background: var(--surface-1);
    border: 1px solid var(--surface-3);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: color var(--dur-fast) ease, background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.adp-tab:hover { color: color-mix(in srgb, var(--text-main) 82%, transparent); background: var(--surface-2); }
.adp-tab small { display: block; margin-bottom: var(--space-1); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.8px; text-transform: uppercase; opacity: 0.65; }
.adp-tab span { display: block; overflow: hidden; font-size: var(--text-sm); font-weight: var(--weight-bold); text-overflow: ellipsis; white-space: nowrap; }
.adp-tab b { position: absolute; top: 50%; right: 12px; transform: translateY(-50%); color: color-mix(in srgb, var(--text-main) 38%, transparent); font-size: var(--text-xs); }
.adp-tab.is-active { color: white; background: color-mix(in srgb, var(--gold-tint) 9%, transparent); border-color: color-mix(in srgb, var(--gold-tint) 45%, transparent); }
.adp-tab.is-active::after { content: ''; position: absolute; left: 14px; right: 14px; bottom: -1px; height: 2px; background: var(--gold); border-radius: 2px 2px 0 0; }
.adp-tab.is-active b { color: var(--gold); }
/* Le tableau de bord Audience porte six onglets là où « Partie du jour » en a
   trois : la grille reste à trois colonnes et passe sur deux rangs, resserrés
   pour ne pas manger la hauteur du corps défilant. */
#admin-audience-tabs .adp-tab { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.adp-scroll-region {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    padding: var(--space-5) var(--space-5) var(--space-6);
}
/* Barre de défilement : apparence globale, cf. components.css (section Défilement). */
.adp-loading { height: 100%; min-height: 180px; display: grid; place-content: center; gap: var(--space-3); color: color-mix(in srgb, var(--text-main) 45%, transparent); font-size: var(--text-sm); text-align: center; }
.adp-loading span { width: 22px; height: 22px; margin: 0 auto; border: 2px solid var(--border); border-top-color: var(--gold); border-radius: 50%; animation: adp-spin 700ms linear infinite; }
@keyframes adp-spin { to { transform: rotate(360deg); } }
.adp-section { width: 100%; max-width: 900px; margin: 0 auto; }
.adp-section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-5); margin-bottom: var(--space-4); }
.adp-section-head > div:first-child { min-width: 0; }
.adp-section-head > div:first-child > span { color: var(--gold); font-size: var(--text-2xs); font-weight: var(--weight-impact); letter-spacing: 1.3px; text-transform: uppercase; }
.adp-section-head h4 { margin: var(--space-1) 0 var(--space-1); color: white; font-size: var(--text-base); }
.adp-section-head p { margin: 0; color: color-mix(in srgb, var(--text-main) 42%, transparent); font-size: var(--text-xs); line-height: 1.45; }
.adp-section-controls { display: flex; align-items: flex-end; gap: var(--space-2); flex: 0 0 auto; }
.adp-theme-wrap, .adp-replace-wrap { display: flex; flex-direction: column; gap: var(--space-1); }
.adp-theme-wrap > span, .adp-replace-wrap > span { color: color-mix(in srgb, var(--text-main) 34%, transparent); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.7px; text-transform: uppercase; }
.adp-theme, .adp-replace {
    height: 34px;
    min-width: 0;
    padding: 0 var(--space-6) 0 var(--space-3);
    color: color-mix(in srgb, var(--text-main) 82%, transparent);
    background: var(--surface-solid-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--text-xs);
    cursor: pointer;
}
.adp-theme { width: min(240px, 28vw); color: var(--gold); border-color: color-mix(in srgb, var(--gold-tint) 35%, transparent); font-weight: var(--weight-bold); }
.adp-question-list { display: grid; gap: var(--space-2); }
.adp-q {
    display: grid;
    grid-template-columns: 26px 52px minmax(0, 1fr) minmax(175px, 220px);
    align-items: center;
    gap: var(--space-2);
    min-height: 58px;
    padding: var(--space-2) var(--space-3);
    background: var(--surface-1);
    border: 1px solid var(--surface-2);
    border-radius: var(--radius-sm);
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.adp-q:hover, .adp-q:focus-within { background: var(--surface-2); border-color: var(--border); }
.adp-q-num { display: grid; place-items: center; width: 24px; height: 24px; color: color-mix(in srgb, var(--text-main) 42%, transparent); background: var(--surface-2); border-radius: var(--radius-sm); font-size: var(--text-xs); font-weight: var(--weight-impact); }
.adp-q-tag { overflow: hidden; padding: var(--space-1) var(--space-2); color: color-mix(in srgb, var(--gold) 72%, transparent); background: color-mix(in srgb, var(--gold-tint) 7%, transparent); border: 1px solid color-mix(in srgb, var(--gold-tint) 15%, transparent); border-radius: var(--radius-sm); font-size: var(--text-2xs); font-weight: var(--weight-impact); letter-spacing: 0.35px; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
.adp-q-body { min-width: 0; }
.adp-q-text { display: -webkit-box; overflow: hidden; color: color-mix(in srgb, var(--text-main) 88%, transparent); font-size: var(--text-xs); font-weight: var(--weight-medium); line-height: 1.35; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.adp-q-answer { overflow: hidden; margin-top: var(--space-1); color: var(--correct-color); font-size: var(--text-xs); text-overflow: ellipsis; white-space: nowrap; }
.adp-q-answer > span { margin-right: var(--space-2); color: color-mix(in srgb, var(--text-main) 30%, transparent); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.6px; text-transform: uppercase; }
.adp-q-answer small { margin-left: var(--space-2); color: var(--border-strong); font-size: var(--text-2xs); }
.adp-q-actions { display: grid; grid-template-columns: 32px minmax(0, 1fr); align-items: end; gap: var(--space-2); min-width: 0; opacity: 0.72; transition: opacity var(--dur-fast) ease; }
.adp-q:hover .adp-q-actions, .adp-q:focus-within .adp-q-actions { opacity: 1; }
/* Onglet Scores de l'éditeur du jour : rang, joueur, saisie du score. */
.adp-score-row { grid-template-columns: 26px minmax(0, 1fr) 112px; }
.adp-score-wrap { display: grid; gap: var(--space-1); min-width: 0; }
.adp-score-wrap > span { color: color-mix(in srgb, var(--text-main) 34%, transparent); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.7px; text-transform: uppercase; }
.adp-score-input {
    height: 34px;
    width: 100%;
    padding: 0 var(--space-3);
    color: var(--gold);
    background: var(--surface-solid-4);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 35%, transparent);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    text-align: center;
}
.adp-score-input:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.adp-score-edited { margin-left: var(--space-2); color: color-mix(in srgb, var(--gold) 72%, transparent); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.35px; text-transform: uppercase; }
/* Onglet Suspicions de l'éditeur du jour : rang, joueur + signaux, bouton détail. */
.adp-int-row { grid-template-columns: 26px minmax(0, 1fr) 72px; align-items: start; }
.adp-int-row .adp-q-num { margin-top: var(--space-1); }
.adp-int-row .adp-q-text { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); -webkit-line-clamp: unset; }
.adp-int-row--high { border-color: color-mix(in srgb, var(--wrong-color) 45%, transparent); }
.adp-int-row--suspect { border-color: color-mix(in srgb, var(--warn-soft) 40%, transparent); }
.adp-int-badge { display: inline-block; padding: 1px var(--space-2); border: 1px solid transparent; border-radius: var(--radius-sm); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.35px; text-transform: uppercase; white-space: nowrap; }
.adp-int-clean { color: color-mix(in srgb, var(--text-main) 40%, transparent); border-color: var(--border); }
.adp-int-watch { color: var(--gold); background: color-mix(in srgb, var(--gold-tint) 8%, transparent); border-color: color-mix(in srgb, var(--gold-tint) 35%, transparent); }
.adp-int-suspect { color: var(--warn-soft); background: color-mix(in srgb, var(--warn-soft) 10%, transparent); border-color: color-mix(in srgb, var(--warn-soft) 45%, transparent); }
.adp-int-high { color: white; background: color-mix(in srgb, var(--wrong-color) 70%, transparent); border-color: var(--wrong-color); }
.adp-int-sum { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.adp-int-chip { padding: 1px var(--space-2); color: color-mix(in srgb, var(--text-main) 62%, transparent); background: var(--surface-2); border-radius: var(--radius-sm); font-size: var(--text-2xs); }
.adp-int-chip--hot { color: var(--warn-soft); background: color-mix(in srgb, var(--warn-soft) 9%, transparent); }
.adp-int-detail { margin: var(--space-2) 0 0; padding: 0; list-style: none; display: grid; gap: 2px; color: color-mix(in srgb, var(--text-main) 70%, transparent); font-size: var(--text-xs); line-height: 1.4; }
.adp-int-detail b { display: inline-block; min-width: 28px; margin-right: var(--space-1); color: color-mix(in srgb, var(--text-main) 40%, transparent); font-weight: var(--weight-bold); }
.adp-int-toggle { min-height: var(--control-h-sm); padding: var(--space-1) var(--space-2); color: color-mix(in srgb, var(--text-main) 62%, transparent); background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius-sm); font: inherit; font-size: var(--text-2xs); font-weight: var(--weight-bold); cursor: pointer; }
.adp-int-toggle:hover, .adp-int-toggle:focus-visible { color: white; border-color: var(--gold); }
.adp-int-filter { min-height: var(--control-h-sm); padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.adp-int-filter[aria-pressed="true"] { color: var(--gold); border-color: var(--gold); }
.adp-int-verdict-cheat { color: white; background: var(--danger-dark); border-color: var(--danger-dark-hover); }
.adp-int-verdict-ok { color: var(--correct-color); border-color: color-mix(in srgb, var(--correct-color) 50%, transparent); }
.adp-int-verdict-check { color: var(--warn-soft); border-color: color-mix(in srgb, var(--warn-soft) 50%, transparent); }
.adp-int-rates { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.adp-int-rate { padding: 1px var(--space-2); color: color-mix(in srgb, var(--text-main) 55%, transparent); background: var(--surface-2); border-radius: var(--radius-sm); font-size: var(--text-2xs); font-weight: var(--weight-bold); white-space: nowrap; }
.adp-int-rate--rare { color: var(--warn-soft); background: color-mix(in srgb, var(--warn-soft) 9%, transparent); }
.adp-int-hist { margin: var(--space-2) 0 0; color: color-mix(in srgb, var(--text-main) 62%, transparent); font-size: var(--text-xs); }
.adp-int-hist b { color: color-mix(in srgb, var(--text-main) 82%, transparent); font-weight: var(--weight-bold); }
.adp-int-hist--muted { color: color-mix(in srgb, var(--text-main) 40%, transparent); }
.adp-int-days { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-1); }
.adp-int-day { padding: 1px var(--space-2); color: color-mix(in srgb, var(--text-main) 55%, transparent); background: var(--surface-2); border: 1px solid transparent; border-radius: var(--radius-sm); font-size: var(--text-2xs); white-space: nowrap; }
.adp-int-day--watch { color: var(--gold); border-color: color-mix(in srgb, var(--gold-tint) 35%, transparent); }
.adp-int-day--suspect { color: var(--warn-soft); border-color: color-mix(in srgb, var(--warn-soft) 45%, transparent); }
.adp-int-day--high { color: white; background: color-mix(in srgb, var(--wrong-color) 60%, transparent); }
.adp-int-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.adp-int-verdict { min-height: var(--control-h-sm); padding: var(--space-1) var(--space-3); font-size: var(--text-2xs); }
.adp-int-verdict--cheat { color: var(--wrong-pale-2); border-color: color-mix(in srgb, var(--wrong-color) 45%, transparent); }
.adp-int-verdict--cheat:hover, .adp-int-verdict--cheat:focus-visible { color: white; background: var(--danger-dark); border-color: var(--danger-dark-hover); }
.adp-edit-btn {
    width: 32px;
    height: 34px;
    display: grid;
    place-items: center;
    color: color-mix(in srgb, var(--text-main) 52%, transparent);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.adp-edit-btn:hover { color: var(--gold); border-color: color-mix(in srgb, var(--gold-tint) 40%, transparent); }
.adp-replace { width: 100%; }
.adp-reroll {
    height: 34px;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0 var(--space-3);
    color: color-mix(in srgb, var(--text-main) 65%, transparent);
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    cursor: pointer;
}
.adp-reroll:hover { color: var(--gold); border-color: color-mix(in srgb, var(--gold-tint) 38%, transparent); background: color-mix(in srgb, var(--gold-tint) 7%, transparent); }
.adp-subhead { display: flex; align-items: baseline; gap: var(--space-2); margin: var(--space-5) var(--space-1) var(--space-2); }
.adp-subhead span { color: var(--gold); font-size: var(--text-xs); font-weight: var(--weight-impact); letter-spacing: 0.9px; text-transform: uppercase; }
.adp-subhead small { color: color-mix(in srgb, var(--text-main) 36%, transparent); font-size: var(--text-xs); }
.adp-modal-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    min-height: 66px;
    padding: var(--space-3) var(--space-5);
    background: color-mix(in srgb, var(--ink-14b) 82%, transparent);
    border-top: 1px solid var(--border-subtle);
}
.adp-feedback { flex: 1; min-width: 0; margin: 0; color: color-mix(in srgb, var(--text-main) 50%, transparent); font-size: var(--text-xs); line-height: 1.35; }
.adp-global-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); flex: 0 0 auto; }
.adp-global-actions .btn { min-height: var(--control-h-sm); display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.adp-save-btn { min-width: 112px; }
.adp-delete-btn { padding: var(--space-2) var(--space-2); color: color-mix(in srgb, var(--wrong-pale-2) 70%, transparent); background: transparent; border: 0; font: inherit; font-size: var(--text-2xs); font-weight: var(--weight-bold); cursor: pointer; }
.adp-delete-btn:hover { color: var(--wrong-color); text-decoration: underline; }
.adp-empty { color: var(--text-muted); opacity: 0.5; padding: var(--space-1); }

@media (max-width: 760px) {
    .adp-modal-head { padding: var(--space-4) var(--space-4) var(--space-3); }
    .adp-context-bar { align-items: stretch; flex-direction: column; gap: var(--space-3); padding: var(--space-3) var(--space-4); }
    .adp-meta { justify-content: space-between; }
    .adp-meta > div { justify-content: flex-start; }
    .adp-tabs { gap: var(--space-2); padding: 0 var(--space-4) var(--space-3); }
    .adp-tab { padding: var(--space-2) 27px var(--space-2) var(--space-2); }
    .adp-tab b { right: 8px; }
    .adp-scroll-region { padding: var(--space-4) var(--space-4) var(--space-5); }
    .adp-section-head { align-items: stretch; flex-direction: column; gap: var(--space-3); }
    .adp-section-controls { width: 100%; }
    .adp-theme-wrap { flex: 1; }
    .adp-theme { width: 100%; }
    .adp-q { grid-template-columns: 24px 48px minmax(0, 1fr); }
    .adp-score-row { grid-template-columns: 24px minmax(0, 1fr) 96px; }
    .adp-int-row { grid-template-columns: 24px minmax(0, 1fr) 64px; }
    .adp-q-actions { grid-column: 3; grid-template-columns: 32px minmax(0, 1fr); width: 100%; opacity: 1; }
    .adp-modal-footer { align-items: stretch; flex-direction: column; gap: var(--space-2); padding: var(--space-3) var(--space-4); }
    .adp-feedback:empty { display: none; }
    .adp-global-actions { width: 100%; }
    .adp-global-actions .adp-generate-btn, .adp-global-actions .adp-save-btn { flex: 1; }
}

@media (max-width: 480px) {
    .adp-tabs small { display: none; }
    .adp-tab span { font-size: var(--text-xs); }
    .adp-tab b { display: none; }
    .adp-tab { padding: var(--space-2) var(--space-2); text-align: center; }
    .adp-meta strong { max-width: 170px; }
    .adp-q { grid-template-columns: 24px minmax(0, 1fr); }
    .adp-score-row { grid-template-columns: 24px minmax(0, 1fr) 84px; }
    .adp-q-tag { grid-column: 2; grid-row: 1; justify-self: start; }
    .adp-q-body { grid-column: 2; }
    .adp-q-actions { grid-column: 2; }
    .adp-global-actions { flex-wrap: wrap; }
    .adp-delete-btn { width: 100%; order: 3; }
}

@media (prefers-reduced-motion: reduce) {
    .adp-loading span { animation: none; }
}

/* Éditeur de proposition de thème (joueur) */
/* Bloc, avec une gouttière sous le libellé : l'anneau de focus global (haut de ce
   fichier) fait 3 px à 4 px d'offset, soit 7 px au-dessus du champ. Un label inline
   à marge nulle collait à son champ et l'anneau lui passait au travers dès qu'on
   cliquait dedans. --space-3 (12 px) le dégage de 5 px ; --space-2 ne laissait
   qu'un pixel. Même gouttière sur --spaced, qui a le même anneau sous lui. */
.prop-label { display: block; margin-bottom: var(--space-3); font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--gold); letter-spacing: 0.5px; }
/* Contraste de bordure WCAG 1.4.11 : limite du champ visible au repos.
   resize vertical : la poignée du textarea, tirée en diagonale, faisait sortir le
   champ de sa ligne (sans effet sur les <input>, qui ne se redimensionnent pas). */
.prop-input { padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--surface-3); border: 1px solid var(--border-contrast); color: white; font-family: inherit; font-size: var(--text-md); width: 100%; box-sizing: border-box; resize: vertical; }
.prop-hint { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-1) 0 var(--space-2); }
.subm-section { font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: 0.8px; text-transform: uppercase; color: var(--gold); margin: var(--space-2) 0 var(--space-1); opacity: 0.85; }
/* Onglets Défi / Compét' : premier écran du wizard de proposition, deux cartes à
   largeur égale plutôt que des radios — c'est le choix qui cadre tout le reste. */
.prop-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
.prop-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    color: var(--text-main);
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.prop-tab--active { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--gold); }
.prop-tab--locked { opacity: 0.5; cursor: not-allowed; }
.prop-tab-name { font-size: var(--text-base); }
.prop-tab-sub { font-weight: var(--weight-medium); font-size: var(--text-2xs); color: var(--text-muted); text-transform: none; letter-spacing: 0; }
.prop-label--spaced { display: block; margin: var(--space-5) 0 var(--space-3); }
.prop-input--big { font-size: var(--text-base); padding: var(--space-3) var(--space-4); }
/* Mauvaises réponses repliées : l'appel est juste après « la bonne réponse » dans
   l'ordre de tabulation, donc au clavier c'est la touche suivante. */
.prop-reveal {
    display: block; width: 100%; margin-top: var(--space-5);
    background: none; border: 1px dashed var(--border-contrast); border-radius: var(--radius-md);
    color: var(--gold); font-family: inherit; font-size: var(--text-sm); font-weight: var(--weight-bold);
    padding: var(--space-3); cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.prop-reveal:hover { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 8%, transparent); }
.prop-reveal-hint { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-2) 0 0; text-align: center; }
/* Flex, pas une grille à trois colonnes : le Duo n'a qu'un champ, et une case au
   tiers de la largeur au milieu d'un formulaire pleine largeur fait bancal.
   flex: 1 1 120px → un seul champ occupe toute la ligne, trois se la partagent. */
.prop-wrongs { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.prop-wrongs .prop-input { flex: 1 1 120px; font-size: var(--text-sm); padding: var(--space-2) var(--space-2); }
.prop-feedback { font-size: var(--text-sm); min-height: 1.1em; margin: var(--space-2) 0 0; }
/* Ligne d'état du brouillon local : discrète tant que tout va bien, rouge quand le
   navigateur refuse le stockage (le seul cas où quitter la page perd la saisie). */
.prop-draft-status { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-4) 0 0; }
.prop-draft-status--err { color: var(--wrong-color); }
/* Sous 520 px, une mauvaise réponse par ligne : trois champs côte à côte n'y
   tiennent qu'au prix d'un texte illisible. */
@media (max-width: 520px) { .prop-wrongs .prop-input { flex-basis: 100%; } }
/* La feuille : les six questions en liste, une seule dépliée. Des cartes espacées
   et non un tableau — pas de bordures partagées, pas de colonnes alignées : c'est
   ce qui sépare une liste lisible d'une feuille de calcul. */
.prop-sheet-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-6); }
.prop-sheet-title { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--gold); letter-spacing: var(--tracking-ui); text-transform: uppercase; }
.prop-sheet-count { font-size: var(--text-xs); font-weight: var(--weight-bold); color: var(--text-muted); white-space: nowrap; }
.prop-sheet-count--ok { color: var(--correct-color); }
.prop-sheet-help { font-size: var(--text-xs); color: color-mix(in srgb, var(--text-main) 40%, transparent); margin: var(--space-1) 0 var(--space-3); }
.prop-sheet { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.prop-row {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}
/* La ligne ouverte se détache : bordure dorée et fond plus clair. On la trouve
   sans la chercher quand on revient d'un défilement. */
.prop-row--open { border-color: var(--gold); background: var(--surface-2); }
.prop-row-head {
    display: flex; align-items: center; gap: var(--space-3);
    width: 100%; padding: var(--space-3) var(--space-4);
    background: none; border: 0; border-radius: var(--radius-md);
    color: var(--text-main); font-family: inherit; font-size: var(--text-sm);
    text-align: left; cursor: pointer;
}
.prop-row:hover { border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
/* Numéro en pastille : un repère, pas une colonne de tableur. Il porte l'état,
   ce qui évite une deuxième colonne pour dire la même chose. */
.prop-row-num {
    flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--text-xs); font-weight: var(--weight-bold);
    background: var(--surface-3); color: var(--text-muted);
    border: 1px solid var(--border-subtle);
}
.prop-row-num--ok { background: color-mix(in srgb, var(--correct-color) 18%, transparent); border-color: color-mix(in srgb, var(--correct-color) 55%, transparent); color: var(--correct-color); }
.prop-row-num--partial { border-color: color-mix(in srgb, var(--gold) 55%, transparent); color: var(--gold); }
.prop-row-body-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Deux lignes maximum, puis coupure : l'énoncé se lit, il n'est pas écrasé dans
   une cellule d'une seule ligne. */
.prop-row-text {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 1.4;
}
.prop-row-text--empty { color: var(--text-muted); font-style: italic; }
.prop-row-tag { font-size: var(--text-2xs); letter-spacing: var(--tracking-chip); text-transform: uppercase; color: var(--text-muted); }
.prop-row-state { flex-shrink: 0; font-size: var(--text-sm); color: var(--text-muted); }
.prop-row-state--ok { color: var(--correct-color); }
.prop-row-state--partial { color: var(--gold); }
.prop-row-fields { padding: 0 var(--space-4) var(--space-4); }
/* « Envoyer aux admins » tient sur trois lignes sous 420 px avec l'interlettrage
   des CTA : on le resserre plutôt que de raccourcir le libellé, que le bandeau de
   correction cite mot pour mot. */
@media (max-width: 420px) {
    #propose-foot .btn { letter-spacing: var(--tracking-chip); font-size: var(--text-xs); padding-left: var(--space-2); padding-right: var(--space-2); }
}

/* iOS zoome automatiquement sur le focus d'un input < 16px, y compris dans
   les modales position:fixed de cet éditeur. On remonte à --text-base
   (16px) sous 768px ; tailles desktop inchangées au-dessus. */
@media (max-width: 767px) {
    .prop-input,
    .prop-wrongs .prop-input {
        font-size: var(--text-base);
    }
}

/* Mes propositions (profil) */
.prop-mine { display: flex; flex-direction: column; gap: var(--space-2); }
.prop-mine-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: var(--text-sm); padding: var(--space-2) var(--space-2); background: var(--surface-1); border-radius: var(--radius-sm); min-width: 0; }
/* Nom de thème saisi par le joueur (maxlength 80) dans #profile-body, qui porte
   `overflow-x: hidden` : le débordement y est coupé, pas scrollable. */
.prop-mine-name { font-weight: var(--weight-medium); color: white; min-width: 0; overflow-wrap: anywhere; }
.prop-mine-meta { color: var(--text-muted); font-size: var(--text-xs); }
.prop-mine-status { margin-left: auto; font-weight: var(--weight-bold); font-size: var(--text-xs); }
.prop-mine-pending { color: var(--gold); }
.prop-mine-accepted { color: var(--correct-color); }
.prop-mine-rejected { color: var(--wrong-color); }
.prop-mine-note { flex-basis: 100%; font-style: italic; color: color-mix(in srgb, var(--text-main) 50%, transparent); font-size: var(--text-xs); }
.prop-mine-empty, .prop-mine-loading { font-size: var(--text-sm); color: var(--text-muted); opacity: 0.6; }

/* Revue admin des propositions */
.subm-card { background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); margin-bottom: var(--space-3); }
.subm-head { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-2); }
.subm-name { font-weight: var(--weight-bold); color: white; min-width: 0; overflow-wrap: anywhere; }
.subm-meta { font-size: var(--text-sm); color: var(--gold); }
.subm-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.subm-btn { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.subm-reject { border-color: color-mix(in srgb, var(--wrong-soft) 50%, transparent); color: color-mix(in srgb, var(--wrong-pale) 90%, transparent); }
.subm-preview { margin-top: var(--space-3); border-top: 1px solid var(--surface-2); padding-top: var(--space-2); display: flex; flex-direction: column; gap: var(--space-1); }
.subm-q { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 85%, transparent); line-height: 1.35; }
.subm-ans { color: var(--correct-color); margin-left: var(--space-1); }
.subm-wrongs { color: var(--text-muted); margin-left: var(--space-1); font-size: var(--text-xs); }
.subm-feedback { font-size: var(--text-sm); min-height: 1em; margin: var(--space-2) 0 0; }
.subm-empty, .subm-loading { font-size: var(--text-sm); color: var(--text-muted); opacity: 0.7; }

/* Catalogue — sections (QUALIFS / COMPET / QPT / GOLD) */
.cat-section-group {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.cat-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
    background: color-mix(in srgb, var(--warn-soft) 8%, transparent);
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.cat-section-header::-webkit-details-marker { display: none; }
.cat-section-header::before { content: '▶'; font-size: var(--text-xs); color: var(--gold); margin-right: var(--space-3); transition: transform var(--dur-fast); }
details[open] > .cat-section-header::before { transform: rotate(90deg); }
.cat-section-title { flex: 1; font-size: var(--text-sm); font-weight: var(--weight-bold); letter-spacing: 1.5px; color: var(--gold); }
.cat-section-body { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2) var(--space-3); }

/* Catalogue — thèmes COMPET */
.cat-theme-group {
    flex-shrink: 0;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-btn);
    overflow: hidden;
}
.cat-theme-header {
    display: flex;
    align-items: center;
    padding: var(--space-2) var(--space-3);
    background: var(--surface-2);
    cursor: pointer;
    user-select: none;
    gap: var(--space-2);
    color: color-mix(in srgb, var(--text-main) 85%, transparent);
    /* Balise passee de <div> a <button> (a11y) : resets pour garder le
       rendu identique a l'ancien div. */
    width: 100%;
    text-align: left;
    border: 0;
    font: inherit;
}
.cat-theme-header:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
}
.cat-theme-header::before { content: '▶'; font-size: var(--text-2xs); color: color-mix(in srgb, var(--text-main) 40%, transparent); flex-shrink: 0; transition: transform var(--dur-fast); }
/* Le header est devenu un <button> (a11y) : il ne peut plus contenir le bouton
   « supprimer le thème », qui devient son frère dans .cat-theme-head-row.
   Le combinateur enfant direct ne suffit donc plus pour la flèche. */
.cat-theme-group.cat-theme-open .cat-theme-header::before { transform: rotate(90deg); }
.cat-theme-head-row {
    display: flex;
    align-items: center;
    background: var(--surface-2);
    padding-right: var(--space-2);
}
.cat-theme-head-row > .cat-theme-header { flex: 1; min-width: 0; }
/* `flex: 1` sans `min-width: 0` garde la taille minimale automatique de l'item :
   le nom débordait de .cat-theme-group, qui porte `overflow: hidden`.
   Ellipse et non césure : .cat-theme-header n'a pas `flex-wrap`, et ses deux frères
   sont en `nowrap` — le nom est le seul item compressible, une césure `anywhere`
   l'aurait réduit à une colonne d'une lettre de large. Même trio que
   .profile-game-mode. */
.cat-theme-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-md); font-weight: var(--weight-medium); color: color-mix(in srgb, var(--text-main) 85%, transparent); }
.cat-theme-count { font-size: var(--text-xs); color: var(--text-muted); white-space: nowrap; margin-left: var(--space-2); }
.cat-theme-author { font-size: var(--text-xs); color: var(--text-muted); opacity: 0.7; white-space: nowrap; margin-left: var(--space-2); }
.cat-theme-del {
    flex-shrink: 0;
    margin-left: var(--space-2);
    background: color-mix(in srgb, var(--wrong-soft) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--wrong-soft) 35%, transparent);
    border-radius: var(--radius-btn);
    color: var(--wrong-color);
    cursor: pointer;
    padding: var(--space-2) var(--space-2);
    display: inline-flex;
    align-items: center;
    transition: background var(--dur-fast);
}
.cat-theme-del:hover { background: color-mix(in srgb, var(--wrong-soft) 22%, transparent); }
.cat-theme-questions { display: none; flex-direction: column; gap: var(--space-2); padding: var(--space-2) var(--space-2); }
.cat-theme-group.cat-theme-open > .cat-theme-questions { display: flex; }

/* Catalogue — navigation cards (vue "all") */
.cat-nav-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
    padding: var(--space-2) 0;
}
.cat-nav-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    padding: var(--space-5) var(--space-3);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-btn);
    cursor: pointer;
    transition: all var(--dur-fast) ease;
    color: white;
}
.cat-nav-card:hover {
    background: color-mix(in srgb, var(--gold-tint) 15%, transparent);
    border-color: color-mix(in srgb, var(--gold-tint) 50%, transparent);
    transform: translateY(-2px);
}
.cat-nav-icon  { font-size: var(--text-base); width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; }
.cat-nav-title { font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: 1.5px; color: var(--gold); margin-top: var(--space-1); }
.cat-nav-count { font-size: 1.8rem; font-weight: var(--weight-bold); line-height: 1.1; }
.cat-nav-label { font-size: var(--text-xs); color: var(--text-muted); }

/* Catalogue — back button */
.cat-back-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    background: none;
    border: none;
    color: var(--gold);
    cursor: pointer;
    font-size: var(--text-sm);
    padding: var(--space-1) 0 var(--space-3);
    opacity: 0.75;
    transition: opacity var(--dur-fast);
}
.cat-back-btn:hover { opacity: 1; }

/* Admin modals — centered, full-width */
#admin-catalogue-modal,
#admin-edit-modal,
#admin-create-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -50%) translateY(12px);
    width: min(95vw, 740px);
}
/* Catalogue en quasi plein écran (feedback : occupait la moitié droite / trop petit) */
#admin-catalogue-modal {
    width: min(96vw, 1400px);
    height: 92vh;
    height: 92svh;
    max-height: 92vh;
    max-height: 92svh;
    display: flex;
    flex-direction: column;
    overflow: hidden; /* le scroll se fait dans .cat-list, pas sur le modal */
}
#admin-edit-modal      { width: min(95vw, 560px); }
#admin-create-modal    { width: min(95vw, 560px); }

/* Liste de questions scrollable (feedback : impossible de défiler les onglets) */
#cat-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0; /* indispensable pour qu'un enfant flex puisse scroller */
    -webkit-overflow-scrolling: touch;
    padding-right: var(--space-2);
}

#admin-catalogue-modal.active,
#admin-edit-modal.active,
#admin-create-modal.active {
    transform: translate(-50%, -50%) translateY(0);
}

/* Modals plein contenu — centrés + contraints en largeur */
#admin-access-modal,
#admin-daily-modal,
#admin-audience-modal,
#special-admin-modal,
#admin-submissions-modal,
#propose-modal,
#daily-q-edit-modal,
#profile-modal,
#admin-login-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.97);
}
#admin-access-modal.active,
#admin-daily-modal.active,
#admin-audience-modal.active,
#special-admin-modal.active,
#admin-submissions-modal.active,
#propose-modal.active,
#daily-q-edit-modal.active,
#profile-modal.active,
#admin-login-modal.active {
    transform: translate(-50%, -50%) scale(1);
}
#admin-access-modal     { width: min(95vw, 580px); }
#admin-daily-modal,
#admin-audience-modal,
#special-admin-modal {
    width: min(96vw, 960px);
    height: min(92vh, 900px);
    height: min(92svh, 900px);
    max-height: calc(100vh - 32px);
    max-height: calc(100svh - 32px);
    min-width: 0;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: color-mix(in srgb, var(--ink-18) 98%, transparent);
    border-color: var(--border);
    border-radius: 18px;
}
#admin-submissions-modal{ width: min(95vw, 720px); }
#propose-modal          { width: min(95vw, 640px); }
#daily-q-edit-modal     { width: min(95vw, 560px); }
/* profile-modal et admin-login-modal ont leur max-width en inline style */

/* ===== Mode Révision ===== */
/* Carte accueil : rejouer ses erreurs (playerStats.failed). */
/* Le bloc revision a quitte l'accueil pour la modale profil : il n'a plus
   besoin d'une carte a lui, il reutilise .profile-section. */
.revision-count { font-size: var(--text-sm); color: var(--text-muted); margin-bottom: var(--space-2); }

/* ===== Défi du jour ===== */
.daily-card {
    width: 100%;
    max-width: 420px;
    margin: 0 auto var(--space-7);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--space-5);
    padding: var(--space-4) var(--space-5);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 22%, transparent);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--gold-tint) 4%, transparent);
}
.daily-card:empty { display: none; }
/* Défi pas encore relevé : pulse doré lent et élégant pour attirer l'œil.
   Le halo vit sur un pseudo-élément dont seule l'OPACITÉ est animée : animer
   box-shadow, background et border sur la carte elle-même repeignait l'accueil
   en continu (audit perf 2026-09-09). `isolation: isolate` + `--z-under` placent
   le pseudo SOUS le contenu de la carte mais au-dessus de son fond : l'ombre
   interne et la teinte ne voilent pas le texte (revue adversariale 2026-09-09),
   et `pointer-events: none` laisse passer le clic. */
.daily-card-live {
    position: relative;
    isolation: isolate;
    border-color: color-mix(in srgb, var(--gold-tint) 30%, transparent);
}
.daily-card-live::before {
    content: '';
    position: absolute;
    inset: -1px;
    z-index: var(--z-under);
    border-radius: inherit;
    border: 1px solid var(--gold);
    background: color-mix(in srgb, var(--gold-tint) 8%, transparent);
    box-shadow: 0 0 34px color-mix(in srgb, var(--gold-tint) 42%, transparent),
                inset 0 0 22px color-mix(in srgb, var(--gold-tint) 12%, transparent);
    opacity: 0;
    pointer-events: none;
    animation: daily-pulse 2.2s ease-in-out infinite;
}
@keyframes daily-pulse {
    0%, 100% { opacity: 0; }
    50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .daily-card-live { border-color: color-mix(in srgb, var(--gold-tint) 50%, transparent); }
    .daily-card-live::before { animation: none; }
    .daily-card-live .daily-head { animation: none; background: none; color: var(--gold); }
}
/* Bandeau de panne du serveur du défi (daily.js, dailyHealth*), collé sous la carte : la carte
   perd sa marge basse tant que le bandeau est affiché, il la reprend. */
.daily-card:has(+ .daily-status:not([hidden])) { margin-bottom: var(--space-3); }
.daily-status {
    width: 100%;
    max-width: 420px;
    margin: 0 auto var(--space-7);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-5);
    text-align: center;
    border: 1px solid color-mix(in srgb, var(--wrong-color) 45%, transparent);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--wrong-color) 8%, transparent);
}
.daily-status[hidden] { display: none; }
.daily-status[data-state="up"] {
    border-color: color-mix(in srgb, var(--gold-tint) 40%, transparent);
    background: color-mix(in srgb, var(--gold-tint) 8%, transparent);
}
.daily-status-title { font-size: var(--text-base); color: var(--text-main); }
.daily-status-text { font-size: var(--text-sm); color: var(--text-muted); }
.daily-status-meta { font-size: var(--text-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* Pastille d'état devant le titre : l'opacité seule bouge (pas de repeinture de la carte). */
.daily-status-title::before {
    content: '';
    display: inline-block;
    width: 0.55em;
    height: 0.55em;
    margin-right: var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--wrong-color);
    animation: daily-status-blink 1.6s ease-in-out infinite;
}
.daily-status[data-state="up"] .daily-status-title::before { background: var(--gold); animation: none; }
@keyframes daily-status-blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
}
@media (prefers-reduced-motion: reduce) {
    .daily-status-title::before { animation: none; }
}

/* Pile de texte centrée : le titre, le #N et le rebours s'alignent sur le
   même axe que le reste de l'accueil, au lieu d'un bloc ferré à gauche. */
.daily-main { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-2); min-width: 0; }

/* Sous ~520px le titre et l'action ne tiennent plus cote a cote : l'action
   passe en dessous et prend toute la largeur plutot que de flotter a gauche. */
@media (max-width: 520px) {
    .daily-card > .btn { flex: 1 1 100%; }
}
.daily-info { display: flex; align-items: center; justify-content: center; gap: var(--space-2); min-width: 0; flex-wrap: wrap; }

/* Titre de la carte. Traitement display de la maison : Outfit en graisse
   fine, capitales, tracking large — la meme voix que les titres de manche,
   pas une seconde famille typographique importee pour un seul libelle. */
.daily-head {
    /* --text-base et pas --text-lg : au-dela, le titre + le bouton ne
       tiennent plus sur une ligne dans les 420px de la carte et le bouton
       tombe en dessous. */
    font-size: var(--text-base);
    font-weight: var(--weight-display);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--gold);
    line-height: 1.1;
}

/* Reflet dore qui balaie le libelle. background-clip: text sous @supports —
   sans le support, le texte reste simplement dore. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .daily-card-live .daily-head {
        background: linear-gradient(100deg,
            var(--gold) 0 42%,
            var(--text-main) 50%,
            var(--gold) 58% 100%);
        background-size: 260% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        animation: daily-shine 4.5s var(--ease-standard) infinite;
    }
}

@keyframes daily-shine {
    0%      { background-position: 130% 0; }
    55%     { background-position: -30% 0; }
    100%    { background-position: -30% 0; }
}
/* Le numero du defi est l'identite du jour : il se lit de loin, au-dessus du
   bouton, pas comme une metadonnee grise. Il vit sur sa propre ligne
   (.daily-main est une colonne) — le grossir ne pousse pas le bouton. */
.daily-title { color: var(--text-main); font-weight: var(--weight-bold); letter-spacing: 0.5px; font-size: var(--text-2xl); line-height: 1; white-space: nowrap; }
.daily-sep { color: var(--border-strong); font-size: var(--text-sm); }
.daily-date { font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; }
.daily-score { font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; }
.daily-score strong { color: var(--gold); }
.daily-spacer { display: none; }
/* Crédit du thème du jour : affiché seulement quand le défi vient d'une proposition
   de joueur (daily.js, refreshDailyCredit). Un thème éditorial ne porte rien —
   le crédit distingue une contribution, il ne décore pas la carte. */
.daily-by { font-size: var(--text-xs); font-weight: var(--weight-medium); color: color-mix(in srgb, var(--gold-tint) 85%, transparent); }
/* Pas de glyphe décoratif : le crédit se lit « Rédigé par X », la plume n'ajoutait
   rien et échappait à la palette (passe SVG 2026-09-10). */
.daily-countdown { font-size: var(--text-xs); color: color-mix(in srgb, var(--gold-tint) 65%, transparent); font-weight: var(--weight-medium); white-space: nowrap; }
/* L'action principale de l'accueil : elle doit peser plus lourd que le
   classement posé juste en dessous. */
.daily-play-btn {
    white-space: nowrap;
    flex-shrink: 0;
    padding: var(--space-3) var(--space-6);
    font-size: var(--text-base);
    letter-spacing: 1px;
}
.daily-share-btn { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); flex-shrink: 0; }
/* Série du défi du jour (streak) : trois paliers visuels (blanc 1-6, rouge 7-30, doré 31+). */
.daily-streak {
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: 0.3px;
    white-space: nowrap;
}
/* Le palier monte en taille avec la série : plus elle dure, plus elle se voit. */
.daily-streak--white {
    color: var(--text-main);
}
.daily-streak--red {
    color: var(--wrong-soft);
    font-size: var(--text-sm);
}
.daily-streak--gold {
    color: var(--gold);
    font-size: var(--text-md);
    text-shadow: 0 0 var(--space-3) var(--gold-glow);
}
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .daily-streak--gold {
        background: linear-gradient(100deg,
            var(--gold) 0 42%,
            var(--text-main) 50%,
            var(--gold) 58% 100%);
        background-size: 260% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        animation: daily-shine 4.5s var(--ease-standard) infinite;
    }
}
@media (prefers-reduced-motion: reduce) {
    .daily-streak--gold {
        animation: none;
        background: none;
        color: var(--gold);
    }
}
/* Classement du jour — top 10, visible sous la carte une fois le défi terminé
   (attribut hidden géré par renderDailyCard/renderDailyLeaderboard). */
/* Sans cadre : deux panneaux dorés empilés se disputaient l'attention alors
   que l'action de la page, c'est « Relever ». Le classement se lit comme une
   légende sous la carte, pas comme une seconde carte. */
.daily-leaderboard {
    width: 100%;
    max-width: 420px;
    margin: 0 auto var(--space-7);
    padding: 0 var(--space-2);
}
/* Carte + classement affichés ensemble : resserrer l'écart entre les deux. */
.daily-card:has(+ .daily-leaderboard:not([hidden])) { margin-bottom: var(--space-6); }
.daily-lb-title { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 1.8px; color: var(--text-muted); margin-bottom: var(--space-2); }
.daily-lb-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); font-size: var(--text-sm); }
.daily-lb-me { background: color-mix(in srgb, var(--gold-tint) 12%, transparent); }
.daily-lb-rank { min-width: 26px; flex-shrink: 0; text-align: center; white-space: nowrap; }
/* Départage des ex æquo : lisible, mais jamais en concurrence avec le score.
   Chiffres tabulaires pour que la colonne ne danse pas d'une ligne à l'autre. */
.daily-lb-time { flex-shrink: 0; white-space: nowrap; color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
/* Deux trophées côte à côte doivent se lire comme UN rang partagé. */
.daily-lb-tie { flex-shrink: 0; white-space: nowrap; color: var(--text-muted); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .04em; }
.daily-lb-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.daily-lb-score { font-weight: var(--weight-bold); color: var(--gold); white-space: nowrap; }
/* Champion du jour — la seule ligne du classement qui doit se voir de loin.
   Pas de cadre : c'est une ligne du classement, pas une carte dans la carte. */
.daily-lb-champ {
    margin-bottom: var(--space-1);
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
    background: color-mix(in srgb, var(--gold-tint) 10%, transparent);
}
.daily-lb-champ .daily-lb-name { font-weight: var(--weight-bold); color: var(--text-main); }
/* Auteur du thème qui relève son propre défi : il connaît les six questions, il
   ne prend donc pas le fauteuil. Sa ligne reste à sa place — le score est réel —
   mais sans le fond doré du champion : une plume et le mot « auteur » disent
   pourquoi elle est au-dessus sans être première. */
.daily-lb-author { background: color-mix(in srgb, var(--text-muted) 9%, transparent); }
.daily-lb-author .daily-lb-name { font-weight: var(--weight-bold); }
.daily-lb-rank--author { color: var(--text-muted); }
.daily-lb-tag { flex-shrink: 0; white-space: nowrap; color: var(--text-muted); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .04em; }
.daily-lb-hint { font-size: var(--text-sm); color: var(--text-muted); }
/* Score « à vérifier » (verdict admin `check`) : un « ? » collé au pseudo — le nom
   cède sa place flexible au « ? » pour que la marque ne parte pas au bout de la
   ligne. Bulle au survol ET au focus (tap, Tab) : c'est un bouton. Elle s'ouvre
   SOUS le « ? » : au-dessus, la liste défilante de la modale la coupait sur la
   première ligne — celle où un score suspect se trouve presque toujours. */
.daily-lb-row--check .daily-lb-name { flex: 0 1 auto; }
.daily-lb-check {
    position: relative;
    flex-shrink: 0;
    margin-right: auto;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 1px solid var(--warn-soft);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--warn-soft);
    font-family: inherit;
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    line-height: 1;
    cursor: help;
}
.daily-lb-check-tip {
    position: absolute;
    top: calc(100% + var(--space-1));
    left: 50%;
    z-index: var(--z-raised);
    width: max-content;
    max-width: 220px;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-deep);
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--weight-body);
    line-height: 1.35;
    text-align: left;
    white-space: normal;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%);
    pointer-events: none;
    transition: opacity var(--dur-fast) ease, visibility var(--dur-fast) ease;
}
.daily-lb-check:hover .daily-lb-check-tip,
.daily-lb-check:focus-visible .daily-lb-check-tip,
.daily-lb-check:focus .daily-lb-check-tip { opacity: 1; visibility: visible; }
/* Dans le bilan, le bloc n'est plus une carte flottante sous la carte d'accueil, mais
   .bilan-shell fait 900px : sans son propre plafond, .daily-lb-name (flex:1) étire les
   lignes du classement et sépare rang/nom/score par un vide énorme sur un grand écran. */
.bilan-daily-leaderboard { max-width: 480px; margin: var(--space-4) auto var(--space-5); }
.daily-lb-cta-text { margin: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--text-muted); text-align: center; }
.daily-lb-login { width: 100%; margin-top: var(--space-2); font-size: var(--text-xs); }
.daily-lb-loading { font-size: var(--text-sm); color: var(--text-muted); }

/* Bouton « Voir les N joueurs » — ouvre la liste complète. Pas un .btn : il
   ouvre un classement, il ne doit pas concurrencer « Relever le défi ». */
.daily-lb-more {
    width: 100%;
    margin-top: var(--space-2);
    padding: var(--space-2);
    background: transparent;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--text-xs);
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.daily-lb-more:hover { color: var(--gold); border-color: var(--gold); }

/* Ligne « Toi » hors du top affiché : détachée par un filet, pas par un cadre. */
.daily-lb-row--detached {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--border-subtle);
    border-radius: 0;
}

/* ---- Modale « tous les joueurs » ---- */
/* Modale et non dépliage : le classement est rendu à deux endroits (accueil et
   bilan) où la hauteur disponible diffère ; vingt lignes dépliées y pousseraient
   les boutons hors écran. */
#daily-lb-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.95);
    width: min(94vw, 460px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}

#daily-lb-modal.active { transform: translate(-50%, -50%) scale(1); }

.daily-lb-modal-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.daily-lb-modal-head h3 { margin: 0; }
.daily-lb-modal-count { flex: 1; font-size: var(--text-xs); color: var(--text-muted); }

/* position:relative — la ligne « Toi » est centrée via offsetTop, donc la liste
   doit être son offsetParent. */
.daily-lb-modal-list {
    position: relative;
    /* flex:1 1 auto + min-height:0 plutôt qu'un max-height fixe : sur un écran
       bas, la liste se comprime et le pied de modale reste visible. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.daily-lb-modal-foot {
    flex-shrink: 0;
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--border-subtle);
}

@media (max-width: 600px) {
    /* Feuille plein écran : sur mobile un classement de 30 lignes n'a pas de
       raison de laisser voir la page derrière. */
    #daily-lb-modal {
        top: 0;
        left: 0;
        width: 100vw;
        max-width: none;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        border-radius: 0;
        border: none;
        transform: translateY(12px);
    }
    #daily-lb-modal.active { transform: translateY(0); }
}



/* ===== Relevé du défi de la veille (daily.js → openDailyRecap) ===== */
/* Parti pris « sobre / éditorial » (planche scratch/proto-releve-defi.html) :
   une colonne, peu de graphes, le verdict porte et le graphe illustre. Les trois
   couleurs de mode sont --mode-duo / --mode-carre / --mode-cash, trois ors de
   clarté décroissante : ils ne se lisent PAS comme trois catégories mais comme
   une échelle de risque Duo → Carré → Cash, ce qui est l'ordre réel du barème.
   D'où la pastille + le libellé partout : la teinte seule ne suffit pas. */

.daily-recap-link {
    align-self: flex-start;
    margin-top: var(--space-2);
    padding: 0 0 2px;
    border: 0;
    border-bottom: 1px solid color-mix(in srgb, var(--gold) 35%, transparent);
    background: transparent;
    color: var(--gold);
    font-family: inherit;
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-chip);
    text-transform: uppercase;
    cursor: pointer;
    transition: border-color var(--dur-base) ease;
}
.daily-recap-link:hover { border-bottom-color: var(--gold); }
/* Cible de 31 px sans bouger la mise en page (le texte en fait 15) : la carte du
   jour doit tenir au-dessus de la ligne de flottaison, pas de padding en plus. */
.daily-recap-link { position: relative; }
.daily-recap-link::after {
    content: '';
    position: absolute;
    inset: calc(-1 * var(--space-2)) 0;
}

#daily-recap-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.95);
    width: min(94vw, 560px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}
#daily-recap-modal.active { transform: translate(-50%, -50%) scale(1); }

/* Classements publics (leaderboards.js) : même gabarit que « tous les joueurs ». */
#leaderboards-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.95);
    width: min(94vw, 480px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}
#leaderboards-modal.active { transform: translate(-50%, -50%) scale(1); }
.lb-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.lb-tab {
    flex: 1 1 auto;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-pill);
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 1px;
    cursor: pointer;
}
.lb-tab:hover { border-color: var(--gold); color: var(--gold); }
.lb-tab[aria-pressed="true"] {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--on-gold);
    font-weight: var(--weight-bold);
}
.lb-desc { font-size: var(--text-xs); color: var(--text-muted); margin: 0 0 var(--space-3); }
.lb-foot { font-size: var(--text-2xs); color: var(--text-muted); margin: var(--space-3) 0 0; }

/* « Revoir mon bilan » (daily.js, openDailyReview) : même gabarit que le relevé. */
#daily-review-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.95);
    width: min(94vw, 640px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}
#daily-review-modal.active { transform: translate(-50%, -50%) scale(1); }
.daily-review-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-right: var(--space-2);
}

/* Classement complet de la veille, replié sous le champion (dailyRecapHtml). */
.rc-board { margin-top: var(--space-4); text-align: left; }
.rc-board-sum {
    cursor: pointer;
    color: var(--gold);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: var(--weight-bold);
    text-align: center;
}
.rc-board-list {
    margin-top: var(--space-3);
    max-height: 320px;
    overflow-y: auto;
}

.daily-recap-body {
    /* Gouttière : la barre de défilement de la modale mange 10 px sans les
       rendre — les pourcentages venaient la toucher. */
    padding-right: var(--space-3);
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.rc-eyebrow {
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--gold);
}
.rc-title {
    margin: var(--space-2) 0 var(--space-1);
    font-size: var(--text-xl);
    font-weight: var(--weight-display);
    color: var(--text-main);
    line-height: 1.2;
}
.rc-sub { font-size: var(--text-sm); color: var(--text-muted); }
.rc-rule { height: 1px; margin: var(--space-5) 0; background: var(--border-subtle); }
/* <h5> : les trois sections du relevé se parcourent au lecteur d'écran par titre. */
.rc-h {
    margin: 0 0 var(--space-4);
    font-weight: inherit;
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--text-muted);
}
.rc-lead {
    font-size: var(--text-lg);
    font-weight: var(--weight-display);
    line-height: 1.45;
    color: var(--text-main);
}
.rc-lead b { color: var(--gold); font-weight: var(--weight-medium); }
.rc-empty, .rc-note { font-size: var(--text-sm); color: var(--text-muted); line-height: 1.5; }
.rc-note { margin-top: var(--space-3); }

/* ---- Champion : la seule chose qui, sans ce relevé, disparaîtrait à minuit ---- */
.rc-champ {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--gold) 7%, transparent);
}
.rc-champ--me { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 14%, transparent); }
.rc-champ-ico { display: flex; color: var(--gold); }
.rc-champ-body { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.rc-champ-label {
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-chip);
    text-transform: uppercase;
    color: var(--text-muted);
}
.rc-champ-tie { color: var(--gold-warm); }
.rc-champ-name {
    font-size: var(--text-base);
    font-weight: var(--weight-medium);
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rc-champ-score {
    flex-shrink: 0;
    text-align: right;
    font-size: var(--text-lg);
    font-weight: var(--weight-display);
    color: var(--gold);
    font-variant-numeric: tabular-nums;
}
.rc-champ-score small {
    display: block;
    font-size: var(--text-2xs);
    font-weight: var(--weight-body);
    color: var(--text-muted);
}

/* ---- Distribution des scores ---- */
.rc-hist {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 84px;
    margin-top: var(--space-5);
}
.rc-hist-b {
    flex: 1;
    min-width: 2px;
    height: var(--rc-h);
    border-radius: 2px 2px 0 0;
    background: var(--surface-3);
    transform-origin: bottom;
    animation: rc-grow var(--dur-slow) cubic-bezier(0.22, 1, 0.36, 1) both;
}
.rc-hist-b--me { background: var(--gold); box-shadow: 0 0 12px var(--gold-glow); }
.rc-hist-ax {
    display: flex;
    justify-content: space-between;
    margin-top: var(--space-2);
    font-size: var(--text-2xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
@keyframes rc-grow { from { transform: scaleY(0); } }

/* ---- Une question ---- */
.rc-q {
    display: grid;
    grid-template-columns: 18px 1fr;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}
.rc-mark { font-size: var(--text-sm); line-height: 1.4; color: var(--text-muted); }
.rc-mark--ok { color: var(--correct-color); }
.rc-mark--ko { color: var(--wrong-color); }
.rc-qt { font-size: var(--text-sm); line-height: 1.45; color: var(--text-main); }
/* La réponse est le sujet du relevé : elle se lit sans avoir à la chercher. */
.rc-qa {
    margin-top: 4px;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--gold);
}
/* ---- La difficulté du jour : six barres, une par question ---- */
/* Remplace l'histogramme des scores en tête de page. Le détail se lit dans une
   LIGNE FIXE sous le graphe, pas dans une infobulle flottante : une infobulle
   n'existe pas au doigt, demande un placement calculé contre les bords de la
   modale, et une sortie au clavier. Une ligne qui se réécrit marche au survol,
   au doigt et au clavier avec le même code, et ne peut pas déborder. */
.rc-spine { margin-top: var(--space-5); }
.rc-spine-bars {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
}
.rc-spine-b {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) 0 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--dur-base) ease;
}
.rc-spine-b:hover, .rc-spine-b--on { background: var(--surface-1); }
/* La colonne fixe la hauteur du graphe et la barre grandit DEDANS : six taux
   différents restent posés sur la même ligne de base. */
.rc-spine-col {
    display: flex;
    align-items: flex-end;
    width: 100%;
    /* Hauteur du graphe, pas un espacement : l’echelle --space-* plafonne a
       64px et ne convient pas ici. */
    height: var(--rc-spine-h, 92px);
}
.rc-spine-fill {
    width: 100%;
    height: var(--rc-h);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    background: var(--mode-duo);
    transform-origin: bottom;
    animation: rc-grow var(--dur-slow) cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* Sous 40 % de réussite, la barre passe à l'or profond : le piège du jour se
   repère sans lire un seul chiffre. */
.rc-spine-b--hard .rc-spine-fill { background: var(--mode-cash); }
.rc-spine-n {
    font-size: var(--text-2xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.rc-spine-mark { font-size: var(--text-2xs); line-height: 1; }
.rc-spine-b--ok .rc-spine-mark { color: var(--correct-color); }
.rc-spine-b--ko .rc-spine-mark { color: var(--wrong-color); }
/* min-height : la ligne se réécrit au survol, et un texte plus court d'une
   ligne faisait sauter tout ce qui suit. Deux lignes réservées. */
.rc-spine-read {
    min-height: 2.9em;
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border-subtle);
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--text-muted);
}
.rc-spine-read b { color: var(--text-main); font-weight: var(--weight-medium); }
.rc-spine-read .rc-spine-q { color: var(--gold); }
.rc-meta { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--text-muted); }

/* ---- Modes ---- */
.rc-mode { letter-spacing: var(--tracking-chip); }
.rc-mode--0 { color: var(--mode-duo); }
.rc-mode--1 { color: var(--mode-carre); }
.rc-mode--2 { color: var(--mode-cash); }
.rc-sw {
    display: inline-block;
    width: 9px;
    height: 9px;
    margin-right: 6px;
    border-radius: 2px;
    background: currentColor;
}
.rc-foot { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.rc-foot-body { flex: 1; min-width: 200px; }
/* Donut à trois segments en conic-gradient, même mécanique que .pf-donut du
   profil : deux angles suffisent, aucun SVG à construire. */
.rc-donut {
    --rc-size: 116px;
    --rc-ring: 13px;
    position: relative;
    flex-shrink: 0;
    width: var(--rc-size);
    height: var(--rc-size);
    border-radius: 50%;
    background: conic-gradient(
        var(--mode-duo) 0 var(--rc-a),
        var(--mode-carre) var(--rc-a) var(--rc-b),
        var(--mode-cash) var(--rc-b) 360deg
    );
}
.rc-donut::before {
    content: '';
    position: absolute;
    inset: var(--rc-ring);
    border-radius: 50%;
    background: var(--surface-solid-1);
}
.rc-modes { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.rc-modes li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 5px 0;
    font-size: var(--text-sm);
}
.rc-modes-v { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.rc-verdict { font-size: var(--text-sm); line-height: 1.5; color: var(--text-main); }
.rc-verdict b { color: var(--gold); font-weight: var(--weight-medium); }

/* Rendez-vous donné au bilan : le relevé du jour n'existera que demain. */
.bilan-recap-tease {
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border-subtle);
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--text-muted);
    text-align: center;
}

@media (max-width: 600px) {
    #daily-recap-modal {
        top: 0;
        left: 0;
        width: 100vw;
        max-width: none;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        border-radius: 0;
        border: none;
        transform: translateY(12px);
    }
    #daily-recap-modal.active { transform: translateY(0); }
    #daily-review-modal {
        top: 0;
        left: 0;
        width: 100vw;
        max-width: none;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        border-radius: 0;
        border: none;
        transform: translateY(12px);
    }
    #daily-review-modal.active { transform: translateY(0); }
    /* Le donut ne descend pas sous 96 px : en dessous, la couronne se lit encore
       mais la colonne de droite n'a plus de place pour ses trois lignes. */
    .rc-donut { --rc-size: 96px; --rc-ring: 11px; }
    .rc-foot { gap: var(--space-4); }
}

@media (prefers-reduced-motion: reduce) {
    .rc-hist-b, .rc-spine-fill { animation: none; }
}

/* ===== Bottom section (search + discord) ===== */
/* La recherche a rejoint la modale Parametres : c'est un outil, pas une
   action de jeu, elle n'a plus sa place en pied d'accueil. */
.settings-search { margin-bottom: var(--space-5); min-width: 260px; }
.settings-search-label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.discord-strip {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-4) 0 var(--space-5);
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.discord-icon { font-size: var(--text-base); }
.discord-text { letter-spacing: 0.3px; }
.discord-link {
    color: var(--gold);
    text-decoration: none;
    font-weight: var(--weight-bold);
    font-size: var(--text-xs);
    letter-spacing: 0.5px;
    padding: var(--space-1) var(--space-3);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 30%, transparent);
    border-radius: 20px;
    transition: background var(--dur-fast), border-color var(--dur-fast);
}
.discord-link:hover { background: color-mix(in srgb, var(--gold-tint) 10%, transparent); border-color: var(--gold); }

/* ===== Auth header ===== */
.auth-slot { position: absolute; top: 0; right: 0; z-index: var(--z-base); display: flex; align-items: center; gap: var(--space-2); }

/* Écran étroit (ex. 375px) : .auth-slot en position absolue chevauchait
   l'illustration du fauteuil (.throne-image-container), centrée et large.
   On repasse le slot dans le flux — il est déjà le premier enfant DOM de
   .home-header, donc il s'affiche naturellement au-dessus de l'image,
   sur sa propre ligne, sans toucher au HTML. Layout desktop inchangé. */
@media (max-width: 480px) {
    .auth-slot {
        position: static;
        justify-content: center;
        /* floatThrone monte l'image de 20px et la grossit de 5 % : la marge
           couvre cette course pour éviter tout chevauchement. */
        margin-bottom: var(--space-6);
    }
}

/* Etroit ET court (iPhone SE 1re generation en Safari, 320x454) : le slot est
   dans le flux, donc ses 32px de marge sont du budget vertical pur. Ils
   n'existent que pour laisser passer floatThrone (-20px + 5%) ; on coupe
   l'animation, la marge n'a plus rien a couvrir. Sans cela le bouton RELEVER
   restait coupe de 19px. Doit rester APRES le bloc max-width:480px : meme
   specificite, c'est l'ordre du fichier qui tranche. */
@media (max-width: 480px) and (max-height: 520px) {
    .auth-slot { margin-bottom: var(--space-2); }

    .home-throne-img { animation: none; }
}
.auth-btn {
    display: flex; align-items: center; justify-content: center; gap: var(--space-2);
    min-height: var(--control-h-md); box-sizing: border-box;
    background: color-mix(in srgb, var(--gold) 8%, transparent);
    border: 1px solid var(--gold);
    color: var(--gold);
    border-radius: var(--radius-btn); padding: 0 var(--space-5);
    cursor: pointer; font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-bold); letter-spacing: var(--tracking-chip);
    white-space: nowrap;
    /* Pas de halo au repos : sur un controle de 44px dans un header plat,
       le glow ajoutait du poids visuel sans porter d'information. */
    transition: background var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast);
}
.auth-btn:hover { background: color-mix(in srgb, var(--gold) 18%, transparent); box-shadow: 0 0 26px var(--gold-glow); transform: translateY(-1px); }
.auth-btn-admin { background: color-mix(in srgb, var(--gold-tint) 16%, transparent); border-color: var(--gold); color: var(--gold); font-weight: var(--weight-bold); }
.auth-btn-admin:hover { background: color-mix(in srgb, var(--gold-tint) 28%, transparent); }
.auth-avatar { width: 24px; height: 24px; border-radius: 50%; }
/* Avatar de repli (compte email sans photo Google) : mêmes dimensions que la photo
   qu'il remplace, sinon l'icône hérite du 1,15 em carré de .ui-icon et l'en-tête
   saute selon le fournisseur de connexion. */
.auth-avatar-icon { width: 24px; height: 24px; }
.auth-name { max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 600px) { .auth-name { display: none; } }
/* ══════════════════════════════════════════════════════════════════════════
   Centre de notifications (notifications.js) — pastille sur le bouton profil
   et bloc « À voir » en tête de la modale.
   Rouge et non doré : l'en-tête est déjà doré (bordure et texte de .auth-btn),
   une pastille dorée sur un bouton doré ne se voit pas. L'ambiguïté avec le
   rouge d'état (--wrong-color = mauvaise réponse) est assumée : la pastille
   vit dans l'en-tête, jamais dans une zone de résultat, et elle porte un
   chiffre (décision 2026-09-10).
   ══════════════════════════════════════════════════════════════════════════ */
.auth-btn.has-notif { position: relative; overflow: visible; }
.notif-badge {
    position: absolute; top: -7px; right: -7px;
    min-width: 20px; height: 20px; padding: 0 var(--space-1);
    border-radius: var(--radius-pill);
    /* Bordure de la couleur du FOND de l'en-tête, pas transparente : la pastille
       chevauche la bordure dorée du bouton, il lui faut un liseré qui l'en détache. */
    border: 2px solid var(--bg-deep);
    background: var(--notif-fill); color: var(--text-main);
    font-size: var(--text-2xs); font-weight: var(--weight-bold); line-height: 1;
    display: flex; align-items: center; justify-content: center;
    animation: notif-pulse 2.4s ease-in-out infinite;
}
/* Pulsation lente : elle doit attirer l'œil au repos, pas clignoter. Bornée à
   une variation d'ombre et d'échelle — pas d'opacité, qui rendrait le chiffre
   illisible la moitié du temps. */
@keyframes notif-pulse {
    0%, 100% { transform: scale(1);    box-shadow: 0 0 0 0 color-mix(in srgb, var(--wrong-color) 55%, transparent); }
    50%      { transform: scale(1.08); box-shadow: 0 0 0 6px color-mix(in srgb, var(--wrong-color) 0%, transparent); }
}
/* Une animation infinie sur un élément d'alerte est exactement ce que WCAG 2.2.2
   vise : coupée dès que le système le demande. */
@media (prefers-reduced-motion: reduce) {
    .notif-badge { animation: none; }
}

.notif-pane {
    margin: 0 0 var(--space-5);
    padding: var(--space-4);
    border: 1px solid var(--gold);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--gold) 7%, transparent);
}
.notif-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.notif-title { display: flex; align-items: center; gap: var(--space-2); margin: 0; font-size: var(--text-md); color: var(--gold); }
.notif-title-icon { color: var(--gold); }
.notif-clear { font-size: var(--text-xs); padding: var(--space-1) var(--space-3); min-height: var(--space-5); /* 24 px : cible minimale WCAG 2.5.8 */ }
.notif-list { display: flex; flex-direction: column; gap: var(--space-2); }
.notif-row {
    display: flex; align-items: flex-start; gap: var(--space-3); width: 100%;
    padding: var(--space-3); text-align: left;
    border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--surface-1); color: var(--text-main);
    font-family: inherit; font-size: var(--text-sm); cursor: pointer;
    transition: background var(--dur-fast), border-color var(--dur-fast);
}
.notif-row:hover { background: var(--surface-2); border-color: var(--gold); }
.notif-row--flat { cursor: default; }
.notif-row--flat:hover { background: var(--surface-1); border-color: var(--border-subtle); }
.notif-row-icon { color: var(--gold); margin-top: 0.15em; }
.notif-row-txt { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.notif-row-title { font-weight: var(--weight-bold); line-height: 1.3; }
.notif-row-note { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.4; }
.notif-more { margin: var(--space-3) 0 0; font-size: var(--text-xs); color: var(--text-muted); text-align: center; }

/* Deux CTA d'en-tête de profil (proposer, défier) : ils passent à la ligne
   ensemble plutôt que de compresser le pseudo. L'inset qui empêche la pilule
   de déborder du coin arrondi du panneau (voir .profile-head-cta plus bas)
   doit rester sur le DERNIER bouton du groupe, pas sur chacun — sinon les
   deux pilules se collent l'une à l'autre ET la dernière déborde du coin. */
.profile-head-ctas { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.profile-head-ctas .profile-head-cta { margin-right: 0; }
.profile-head-ctas .profile-head-cta:last-child { margin-right: var(--space-3); }

/* ===== Modal profil ===== */
#profile-body { font-size: var(--text-md); }
.profile-head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-5); }
.profile-avatar { width: 56px; height: 56px; border-radius: 50%; flex-shrink: 0; border: 2px solid var(--border); }
.profile-avatar-empty { display: flex; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 50%; background: var(--surface-3); font-size: 1.6rem; }
.profile-head-txt { display: flex; flex-direction: column; gap: var(--space-1); flex: 1; min-width: 0; }
.profile-name { font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--text-main); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-head-sub { font-size: var(--text-sm); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* CTA « Proposer un thème » : poussé à droite par le flex:1 de .profile-head-txt,
   toujours au bout de la ligne du pseudo quelle que soit sa longueur.
   La marge droite l'aligne sur le ✕ qu'il a juste au-dessus : ce bouton fait
   44 px de large (cible tactile) pour un glyphe d'environ 18 px, donc son bord
   visible est rentré d'une douzaine de pixels. À ras du bord, la pilule semblait
   déborder du panneau — c'est sur le signe qu'on s'aligne, pas sur sa boîte. */
.profile-head-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    margin-right: var(--space-3);
    border: 1px solid var(--gold);
    background: color-mix(in srgb, var(--gold) 10%, transparent);
    color: var(--gold);
    border-radius: var(--radius-pill);
    padding: var(--space-2) var(--space-3);
    font-family: inherit;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.profile-head-cta:hover { background: color-mix(in srgb, var(--gold) 18%, transparent); }
.profile-head-cta:focus-visible { border-color: var(--gold); }
/* Icône seule sous 420px : le libellé complet n'a pas la place à côté d'un pseudo
   long, et aria-label porte déjà le nom accessible du bouton. */
@media (max-width: 420px) {
    .profile-head-cta-label { display: none; }
}
.profile-empty { text-align: center; padding: 1.8rem 1.2rem; margin-bottom: var(--space-5); background: var(--surface-1); border: 1px solid var(--surface-3); border-radius: var(--radius-md); }
.profile-empty-icon { font-size: 1.8rem; display: block; margin-bottom: var(--space-2); opacity: 0.85; }
.profile-empty-title { font-size: var(--text-base); font-weight: var(--weight-bold); color: white; margin: 0 0 var(--space-2); }
.profile-empty-sub { font-size: var(--text-sm); color: var(--text-muted); line-height: 1.45; margin: 0; max-width: 320px; margin-left: auto; margin-right: auto; }
.profile-account { margin-top: var(--space-5); padding-top: 1.1rem; border-top: 1px solid var(--border-subtle); text-align: center; }
.profile-logout { background: none; border: none; font: inherit; font-size: var(--text-sm); color: var(--text-muted); cursor: pointer; padding: var(--space-2) var(--space-3); transition: color var(--dur-fast); }
.profile-logout:hover { color: var(--wrong-color); }
.profile-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin-bottom: var(--space-5); }
.profile-kpi { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); background: var(--surface-1); border: 1px solid var(--surface-2); border-radius: var(--radius-md); padding: var(--space-4) var(--space-2); text-align: center; }
.profile-kpi-icon { font-size: var(--text-base); line-height: 1; }
.profile-kpi-label { display: block; font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-ui); color: var(--text-muted); }
.profile-kpi-val { font-size: var(--text-xl); font-weight: var(--weight-bold); color: var(--gold); line-height: 1.1; }
.profile-kpi-sub { display: block; font-size: var(--text-2xs); color: var(--text-muted); letter-spacing: 0; text-transform: none; }
.profile-section { margin-bottom: var(--space-5); }
.profile-section h4 { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 1.6px; color: var(--text-muted); margin: 0 0 var(--space-4); display: flex; align-items: center; gap: var(--space-2); }

/* Carte de section du dashboard profil : chaque bloc de stats respire dans
   sa propre surface au lieu de s'empiler sur le fond de la modale. */
.pf-card { background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-4) var(--space-5); }
.pf-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 var(--space-1); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--gold-tint) 20%, transparent); color: var(--gold); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0; }

/* Anneaux de réussite (conic-gradient + masque radial ; --pf-deg / --pf-col
   injectés inline par profile.js, valeurs calculées à l'exécution). */
.pf-donuts { display: flex; align-items: flex-start; justify-content: space-around; gap: var(--space-4); flex-wrap: wrap; padding: var(--space-2) 0; }
.pf-donut-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.pf-donut {
    --pf-size: 84px;
    --pf-ring: 9px;
    /* La portion vide doit se VOIR : sur --surface-3 (8 % de blanc) le tour
       disparaissait dans le fond de la carte, et chaque anneau se lisait comme
       un arc nu — donc comme une forme différente d'une manche à l'autre. */
    --pf-track: color-mix(in srgb, var(--gold-tint) 14%, var(--surface-3));
    width: var(--pf-size); height: var(--pf-size);
    border-radius: 50%;
    background: conic-gradient(var(--pf-col) var(--pf-deg), var(--pf-track) 0);
    display: flex; align-items: center; justify-content: center;
    position: relative;
}
.pf-donut::before {
    content: '';
    position: absolute;
    inset: var(--pf-ring);
    border-radius: 50%;
    background: var(--surface-solid-2);
}
/* Même diamètre pour les quatre anneaux : la hiérarchie se lit à la teinte
   (--gold pour Globale, --gold-tint pour les manches). Le diamètre spécial
   désalignait aussi les libellés, posés sous des anneaux de hauteurs différentes. */
.pf-donut-val { position: relative; z-index: var(--z-base); font-size: var(--text-md); font-weight: var(--weight-bold); color: var(--text-main); }
.pf-donut-val small { font-size: 0.6em; font-weight: var(--weight-medium); color: var(--text-muted); margin-left: 1px; }
.pf-donut-label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-ui); color: var(--text-muted); }
.pf-donut-sub { font-size: var(--text-2xs); color: var(--text-muted); opacity: 0.8; }

/* « J'ai un code éditeur » — encart repliable, sobre. */
.profile-claim { background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-4) var(--space-4); }
.profile-claim[open] { padding-bottom: var(--space-4); }
.profile-claim-summary { cursor: pointer; list-style: none; color: var(--gold); font-size: var(--text-sm); font-weight: var(--weight-bold); letter-spacing: 0.5px; }
.profile-claim-summary::-webkit-details-marker { display: none; }
.profile-claim-summary::after { content: '▾'; float: right; opacity: 0.5; transition: transform .2s ease; }
.profile-claim[open] .profile-claim-summary::after { transform: rotate(180deg); }
/* Carte « Votre pseudo », en tête du profil (profile.js, 2026-09-27) : bordure or, la
   seule carte du profil qui en porte une — c'est elle qu'on veut voir en premier. */
.pseudo-card { border-color: color-mix(in srgb, var(--gold) 45%, transparent); background: color-mix(in srgb, var(--gold) 6%, var(--surface-1)); margin-bottom: var(--space-5); }
.pseudo-card h4 { color: var(--gold); }
.pseudo-card h4 label { cursor: pointer; }
.pseudo-card-lead { font-size: var(--text-sm); color: var(--text-main); line-height: 1.45; margin: 0 0 var(--space-3); }
.pseudo-card-lead--welcome { font-weight: var(--weight-bold); color: var(--gold); }
.pseudo-row { display: flex; gap: var(--space-3); align-items: stretch; }
.pseudo-row .auth-field { flex: 1; min-width: 0; }
.pseudo-row .auth-field:read-only { color: var(--text-muted); cursor: default; }
.pseudo-save { flex-shrink: 0; }
.pseudo-save:disabled { cursor: not-allowed; opacity: 0.5; }
.pseudo-status { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); margin: var(--space-3) 0 0; min-height: 1.45em; }
.pseudo-status--ok { color: var(--success-alt); }
.pseudo-status--locked { color: var(--text-muted); }
@media (max-width: 480px) { .pseudo-row { flex-direction: column; } }
.profile-claim-hint { font-size: var(--text-sm); color: var(--text-muted); line-height: 1.45; margin: var(--space-3) 0 var(--space-3); }
.claim-code-field {
    width: 100%;
    box-sizing: border-box;
    padding: var(--space-3) var(--space-3);
    border-radius: var(--radius-btn);
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-family: var(--font-mono);
    letter-spacing: 3px;
    text-transform: uppercase;
    font-size: var(--text-base);
    text-align: center;
}
.claim-code-feedback {
    font-size: var(--text-sm);
    min-height: 1.1em;
    margin: var(--space-2) 0 0;
    text-align: center;
}
#claim-admin-code::placeholder { letter-spacing: 1px; opacity: 0.4; }
.profile-bar-row { display: grid; grid-template-columns: 110px 1fr 92px; align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); }
.profile-bar-row:last-child { margin-bottom: 0; }
.profile-bar-label { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: var(--tracking-chip); color: var(--text-main); }
.pf-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; background: var(--pf-mode, var(--gold)); }
.profile-bar-track { background: var(--surface-3); border-radius: var(--radius-pill); height: 12px; overflow: hidden; }
.profile-bar-fill { width: var(--pf-w, 0); height: 100%; border-radius: var(--radius-pill); background: var(--pf-mode, var(--gold)); transition: width .6s var(--ease-decelerate); }
/* Une teinte par mode, posée UNE fois sur la ligne : la pastille et la barre la
   lisent toutes les deux. Rampe d'or du plus clair au plus profond, le rouge
   réservé au seul mode qui peut retirer des points (Super Cash, −5). Les valeurs
   vivent dans tokens.css (--mode-*), jamais ici. */
.pf-mode--duo       { --pf-mode: var(--mode-duo); }
.pf-mode--carre     { --pf-mode: var(--mode-carre); }
.pf-mode--cash      { --pf-mode: var(--mode-cash); }
.pf-mode--supercash { --pf-mode: var(--mode-supercash); }
.profile-bar-val { display: flex; align-items: baseline; justify-content: flex-end; gap: var(--space-2); white-space: nowrap; }
.profile-bar-val strong { font-size: var(--text-sm); color: var(--text-main); }
.profile-bar-val small { font-size: var(--text-2xs); color: var(--text-muted); }
.profile-themes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.profile-themes-solo { grid-template-columns: 1fr; }
.pf-theme-row { margin-bottom: var(--space-3); }
/* Le seuil de 6 reponses (profile.js) doit se lire, sinon un theme joue 3 fois
   disparait sans explication. */
.pf-theme-hint { margin: calc(var(--space-2) * -1) 0 var(--space-4); font-size: var(--text-xs); color: var(--text-muted); text-align: center; }
.pf-theme-row:last-child { margin-bottom: 0; }
.pf-theme-line { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); margin-bottom: var(--space-1); }
.pf-theme-name { font-size: var(--text-sm); color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-theme-rate { font-size: var(--text-xs); font-weight: var(--weight-bold); color: var(--text-muted); flex-shrink: 0; }
.pf-theme-track { background: var(--surface-3); border-radius: var(--radius-pill); height: 6px; overflow: hidden; }
.pf-theme-fill { width: var(--pf-w, 0); height: 100%; border-radius: var(--radius-pill); background: var(--pf-theme-col, var(--gold)); transition: width .6s var(--ease-decelerate); }
/* Or = ce qui va bien, rouge = ce qui reste à travailler. Remplace le vert
   --correct-color et un var(--streak-orange) qui n'existait dans aucun fichier
   (barre sans fond, cf. profile.js). */
.pf-theme--good { --pf-theme-col: var(--gold); }
.pf-theme--bad  { --pf-theme-col: var(--wrong-soft); }
/* Pas de max-height ni d'overflow ici : un second ascenseur dans une modale qui
   défile déjà piégeait la molette. La liste est bornée à 8 lignes par profile.js. */
.profile-games { display: flex; flex-direction: column; gap: var(--space-2); }
.profile-game-row { display: grid; grid-template-columns: 72px 1fr 60px 96px; align-items: center; gap: var(--space-2); font-size: var(--text-xs); padding: var(--space-2) var(--space-3); background: var(--surface-2); border-radius: var(--radius-sm); }
.profile-game-date { white-space: nowrap; color: var(--text-muted); }
.profile-game-mode { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-muted); }
.profile-game-score { font-weight: var(--weight-bold); color: var(--gold); text-align: right; }
.profile-game-rate { color: var(--text-muted); display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); white-space: nowrap; }
.pf-mini-track { width: 44px; height: 5px; border-radius: var(--radius-pill); background: var(--surface-3); overflow: hidden; display: inline-block; }
.pf-mini-fill { display: block; width: var(--pf-w, 0); height: 100%; border-radius: var(--radius-pill); background: var(--gold-tint); }
.profile-action { width: 100%; margin-top: var(--space-2); }
/* Bloc connexion du hub « Mon compte » : Google + Email empilés sous un séparateur. */
.profile-login { margin-top: var(--space-4); }
.profile-login-sep { display: block; text-align: center; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-muted); margin: var(--space-2) 0; position: relative; }
.profile-login-sep::before, .profile-login-sep::after { content: ''; position: absolute; top: 50%; width: 28%; height: 1px; background: var(--surface-3); }
.profile-login-sep::before { left: 0; }
.profile-login-sep::after { right: 0; }
@media (max-width: 600px) {
    .profile-themes { grid-template-columns: 1fr; }
    .profile-kpis { grid-template-columns: repeat(2,1fr); }
    .pf-donuts { justify-content: center; }
    .pf-card { padding: var(--space-4); }
    .profile-bar-row { grid-template-columns: 92px 1fr 84px; }
    .profile-game-row { grid-template-columns: 72px 1fr 48px 70px; }
    .pf-mini-track { width: 28px; }
}

/* ===== Modale d'authentification (email+mdp / Google) ===== */
.auth-tabs { display: flex; gap: var(--space-2); background: var(--surface-2); border-radius: var(--radius-md); padding: var(--space-1); }
.auth-tab { flex: 1; padding: var(--space-2) var(--space-3); border: none; border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast); }
.auth-tab.active { background: color-mix(in srgb, var(--gold) 16%, transparent); color: var(--gold); }
.auth-tab:hover:not(.active) { color: white; }
.auth-or { display: flex; align-items: center; text-align: center; color: var(--text-muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 1.5px; margin: var(--space-4) 0; gap: var(--space-3); }
.auth-or::before, .auth-or::after { content: ''; flex: 1; height: 1px; background: var(--surface-3); }
.auth-perks { list-style: none; margin: var(--space-4) 0 0; padding: var(--space-3) var(--space-4); background: color-mix(in srgb, var(--gold) 7%, transparent); border: 1px solid color-mix(in srgb, var(--gold) 18%, transparent); border-radius: var(--radius-md); display: flex; flex-direction: column; gap: var(--space-2); }
.auth-perks li { font-size: var(--text-sm); color: var(--text-main); line-height: 1.35; }
/* Pseudo à l'inscription (auth.js, 2026-09-27) : libellé visible, une phrase d'usage. */
.auth-pseudo-block { display: flex; flex-direction: column; gap: var(--space-2); }
.auth-pseudo-label { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--gold); }
.auth-pseudo-hint { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.4; margin: 0; }
.auth-pseudo-hint--google { text-align: center; margin-top: var(--space-2); }
.auth-switch-line { text-align: center; font-size: var(--text-sm); color: var(--text-muted); margin: 1.1rem 0 0; }
.auth-switch-link { background: none; border: none; padding: 0; font: inherit; font-weight: var(--weight-bold); color: var(--gold); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.auth-switch-link:hover { color: var(--gold); }

/* ===== Bandeau « vérifie ton email » ===== */
.verify-banner { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space-3) var(--space-4); background: color-mix(in srgb, var(--gold) 12%, transparent); border: 1px solid color-mix(in srgb, var(--gold) 40%, transparent); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); margin: 0 auto var(--space-4); max-width: 760px; font-size: var(--text-sm); color: var(--text-main); }
.verify-banner .verify-text { flex: 1 1 320px; }
.verify-banner .verify-actions { display: flex; gap: var(--space-2); flex-shrink: 0; }
.verify-banner .verify-actions .btn { padding: var(--space-2) var(--space-4); font-size: var(--text-sm); }
#verify-note { font-weight: var(--weight-medium); }

/* ===== Dialog de confirmation custom ===== */
.confirm-overlay {
    position: fixed;
    inset: 0;
    background: color-mix(in srgb, var(--shadow-base) 72%, transparent);
    z-index: var(--z-confirm);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    visibility: hidden;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    /* visibility transitionnait en meme temps que l'opacite : bascule
       differee en 0s pour que le focus fonctionne des l'ouverture. */
    transition: opacity .18s ease, visibility 0s linear .18s;
}
.confirm-overlay.active {
    opacity: 1;
    visibility: visible;
    transition: opacity .18s ease, visibility 0s;
}
.confirm-card {
    background: color-mix(in srgb, var(--ink-14) 97%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 18%, transparent);
    border-radius: 18px;
    padding: var(--space-6) var(--space-6) var(--space-5);
    width: min(92vw, 400px);
    box-shadow: 0 32px 80px color-mix(in srgb, var(--shadow-base) 70%, transparent), 0 0 0 1px var(--surface-2);
    transform: scale(0.93) translateY(10px);
    transition: transform .22s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.confirm-overlay.active .confirm-card {
    transform: scale(1) translateY(0);
}
.confirm-msg {
    font-size: var(--text-md);
    color: var(--text-main);
    line-height: 1.6;
    margin: 0 0 var(--space-5);
    white-space: pre-line;
}
.confirm-actions {
    display: flex;
    gap: var(--space-3);
    justify-content: flex-end;
}
.confirm-actions .btn {
    min-width: 88px;
    padding: var(--space-2) 1.15rem;
    font-size: var(--text-sm);
}
.btn-danger {
    background: var(--danger-dark);
    color: var(--text-main);
    border-color: var(--danger-dark);
    box-shadow: 0 0 18px color-mix(in srgb, var(--danger-dark) 35%, transparent);
}
.btn-danger:hover {
    background: var(--danger-dark-hover);
    border-color: var(--danger-dark-hover);
    transform: translateY(-2px);
    box-shadow: 0 0 26px color-mix(in srgb, var(--danger-dark-hover) 45%, transparent);
}

/* ==========================================================================
   Backstage utilities — Pass 2
   ==========================================================================
   Replaces the inline style="…" attributes generated by admin.js (edit
   modal, daily-question editor, creation wizard, admin-access panel).
   These are admin-only surfaces: colors here follow the same tokens as
   the rest of the app (--gold accents, the neutral surface/border
   ladder), nothing re-hued. A few rgba(255,255,255, N) literals below
   are DELIBERATELY left raw — they fall in the 0.3–0.92 text-opacity
   band that has no --opacity-* token yet (documented gap, same as the
   credits-line color-mix(in srgb, var(--text-main) 35%, transparent) elsewhere in this file).
   ========================================================================== */

/* Form field (input/textarea), shared by the edit modal, the daily-question
   editor and the creation wizard. */
.admin-field {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--surface-3);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-family: inherit;
    font-size: var(--text-base);
}
/* Le menu déroulant natif d'un <select> est peint par l'OS. Sans `color-scheme`,
   Windows le rend clair et les <option> héritent du `color: var(--text-main)`
   ci-dessus (blanc) : le libellé sélectionné restait lisible, la liste était
   blanche sur blanc. On déclare le schéma sombre sur le champ (portée locale, le
   reste de la page n'y touche pas) et on repeint les options pour les moteurs
   qui ignorent `color-scheme`. */
select.admin-field { color-scheme: dark; }
select.admin-field option {
    /* Couleur OPAQUE : var(--surface-3) est un blanc à 8 %, invisible sur le fond
       clair d'un moteur qui ignorerait color-scheme. */
    background-color: var(--surface-solid-1);
    color: var(--text-main);
}
.admin-field--compact { padding: var(--space-2) var(--space-3); }
.admin-field--mt { margin-top: var(--space-1); }
.admin-field--plain { outline: none; }
/* Le champ e-mail admin est auto-focusé à l'ouverture (trapFocus). L'outline:none
   ci-dessus le laissait sans indicateur de focus visible — on rétablit l'anneau. */
.admin-field--plain:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
    box-shadow: 0 0 20px var(--gold-glow);
}

/* Field label. No `display` set on purpose — the parent forms
   (#admin-edit-form, #daily-q-edit-form) are flex columns, so each
   label is already its own stacked flex item. */
.admin-label {
    font-size: var(--text-sm);
    color: var(--gold);
    font-weight: var(--weight-bold);
    letter-spacing: 1px;
    text-transform: uppercase;
}
/* Same label, for the wizard body (#wz-body), which is a plain div —
   needs an explicit block display to stack above its field. */
.admin-label--block {
    display: block;
    font-size: var(--text-sm);
    color: var(--gold);
    font-weight: var(--weight-bold);
    letter-spacing: 1px;
    text-transform: uppercase;
    margin: var(--space-3) 0 var(--space-1);
}
.admin-label-optional {
    font-weight: var(--weight-body);
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.55;
}
.admin-label-optional--xs { font-size: var(--text-xs); }

.admin-summary-reset { cursor: pointer; list-style: revert; }

.admin-hint {
    font-size: var(--text-xs);
    color: color-mix(in srgb, var(--text-main) 35%, transparent); /* text-opacity band, no token — see file header */
    margin: var(--space-1) 0 var(--space-2);
}
.admin-hint--italic { font-style: italic; }

/* Pavé d'explication du réglage de tolérance CASH (admin.js, tolHintHtml).
   Décrit le niveau choisi et l'illustre avec la vraie réponse de la question ;
   les exemples sont passés par game.matchCash, donc ce qui est annoncé
   « accepté » l'est réellement en jeu. */
.admin-tol-desc {
    margin: var(--space-2) 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface-3);
    font-size: var(--text-xs);
    line-height: 1.5;
}
.admin-tol-desc p { margin: 0; }
.admin-tol-desc p + p { margin-top: var(--space-2); }
.admin-tol-lead { color: var(--text-main); }
.admin-tol-budget { color: var(--gold); font-weight: var(--weight-medium); }
.admin-tol-ex--ok { color: var(--correct-color); }
.admin-tol-ex--ko { color: var(--wrong-color); }
.admin-tol-desc .admin-tol-ex + .admin-tol-ex { margin-top: var(--space-1); }
.admin-hint--tight { margin: var(--space-1) 0 0; }

.dqe-master-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
    font-size: var(--text-sm);
    color: color-mix(in srgb, var(--text-main) 80%, transparent);
    cursor: pointer;
}
.dqe-master-label--disabled { color: color-mix(in srgb, var(--text-main) 35%, transparent); cursor: not-allowed; }
.admin-checkbox-lg { width: var(--space-4); height: var(--space-4); }

.admin-feedback { font-size: var(--text-sm); min-height: 1.2em; margin: 0 0 var(--space-4); }

/* Layout utilities used throughout the admin modals/wizard */
.admin-row { display: flex; align-items: center; gap: var(--space-3); }
.admin-row--wrap { flex-wrap: wrap; }
.admin-row-sm-gap { gap: var(--space-2); }
.admin-col { display: flex; flex-direction: column; }
.admin-gap-2 { gap: var(--space-2); }
.admin-gap-3 { gap: var(--space-3); }
.admin-flex-1 { flex: 1; }
.admin-w-full { width: 100%; }
.admin-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.admin-mt-1 { margin-top: var(--space-1); }
.admin-mt-2 { margin-top: var(--space-2); }
.admin-mt-3 { margin-top: var(--space-3); }
.admin-mt-4 { margin-top: var(--space-4); }
.admin-mb-2 { margin-bottom: var(--space-2); }
.admin-mb-3 { margin-bottom: var(--space-3); }
.admin-mb-4 { margin-bottom: var(--space-4); }
.admin-hidden { display: none; }

/* Muted helper text (feedback panels, empty states) */
.admin-muted { color: var(--text-muted); }
.admin-muted-block {
    color: var(--text-muted);
    font-size: var(--text-md);
    line-height: 1.5;
    margin: 0 0 var(--space-4);
}
.admin-empty-state { color: var(--text-muted); text-align: center; padding: var(--space-3); }
.admin-error-text { color: var(--wrong-color); }

/* Small danger action (e.g. "Retirer" on the admins list) */
.admin-danger-btn-sm {
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-xs);
    border-color: color-mix(in srgb, var(--wrong-soft) 50%, transparent);
    color: color-mix(in srgb, var(--wrong-pale) 90%, transparent);
}

/* Per-mode chip (DUO/CARRÉ/CASH badge in the wizard). Background/border/
   color are computed from the mode's own color at render time — same
   "data-driven value" exception as a dynamic width bar; the static
   shape lives here. */
.admin-chip {
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    padding: 3px var(--space-3);
    border-radius: var(--radius-pill);
    letter-spacing: 1px;
}

/* Muted helper text — grouped by (font-size bucket, alpha). The alpha
   values are raw on purpose (0.3–0.92 band, no --opacity-* token — see
   file header); font-size and margin are tokenized. */
.admin-subtitle { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 60%, transparent); margin: 0 0 var(--space-4); }
.admin-subtitle--mb3 { margin-bottom: var(--space-3); }
.admin-text-xs-35 { font-size: var(--text-xs); color: color-mix(in srgb, var(--text-main) 35%, transparent); }
.admin-status-ok { color: var(--correct-color); }
.admin-text-xs-40 { font-size: var(--text-xs); color: color-mix(in srgb, var(--text-main) 40%, transparent); }
.admin-text-sm-40 { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 40%, transparent); }
.admin-text-sm-45 { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 45%, transparent); }
.admin-text-sm-50 { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 50%, transparent); }
.admin-text-main { color: var(--text-main); }
.admin-theme-line { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 45%, transparent); margin-bottom: var(--space-2); }

.admin-mode-row { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.admin-wz-actions { display: flex; gap: var(--space-3); }
.admin-wz-actions--mt { margin-top: var(--space-4); }

.wz-image-preview {
    display: none;
    max-width: 100%;
    max-height: 170px;
    border-radius: var(--radius-btn);
    margin-top: var(--space-2);
    border: 1px solid var(--border);
}
.wz-image-preview--visible { display: block; }
.admin-image-remove-btn { display: none; padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }
.admin-image-remove-btn--visible { display: inline-flex; }
/* Image de la modale d'édition (admin.js, _adminEditImageBlock). */
.ae-image { display: flex; flex-direction: column; gap: var(--space-2); }
.ae-image .admin-hint { margin: 0; }
.admin-image-pick { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }

.admin-card-num { min-width: 36px; font-weight: var(--weight-bold); font-size: var(--text-xs); }
.admin-card-num--dim { opacity: 0.5; }
.admin-card-num--top { padding-top: 1px; }
.admin-card-text { flex: 1; font-size: var(--text-sm); }
.admin-card-text--italic { font-style: italic; }
.admin-card-text--preview { line-height: 1.4; }
.admin-card-action { font-size: var(--text-xs); }
.admin-card-trailing { font-size: var(--text-xs); color: color-mix(in srgb, var(--text-main) 50%, transparent); white-space: nowrap; }

/* Wizard progress bar */
.admin-progress-track {
    background: var(--surface-3);
    border-radius: var(--radius-sm);
    height: 4px;
    overflow: hidden;
}
.admin-progress-fill { height: 100%; background: var(--gold); transition: width var(--dur-base); }
.admin-progress-label { font-size: var(--text-sm); color: color-mix(in srgb, var(--text-main) 45%, transparent); margin-top: var(--space-1); text-align: right; }

/* Creation-type picker cards ("+ Créer" modal) */
.admin-choice-card {
    padding: var(--space-4) var(--space-3);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-family: inherit;
    cursor: pointer;
    text-align: left;
    line-height: 1.5;
}
.admin-choice-title { font-weight: var(--weight-bold); font-size: var(--text-md); color: var(--gold); }
.admin-choice-sub { font-size: var(--text-xs); color: color-mix(in srgb, var(--text-main) 50%, transparent); }

/* Wizard question cards (list of already-entered / pending questions) */
.admin-card-btn {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    text-align: left;
    font-family: inherit;
    cursor: pointer;
    border-radius: var(--radius-sm);
}
.admin-card-btn--ghost {
    padding: var(--space-2) var(--space-4);
    border: 1px dashed var(--border);
    background: transparent;
    color: color-mix(in srgb, var(--text-main) 28%, transparent);
}
.admin-card-btn--dashed {
    padding: var(--space-3) var(--space-4);
    border: 1px dashed var(--border-strong);
    background: transparent;
    color: color-mix(in srgb, var(--text-main) 40%, transparent);
}
.admin-card-btn--filled {
    align-items: flex-start;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    background: var(--surface-1);
    color: var(--text-main);
}
/* Carte de question en défaut au récapitulatif (relecture d'une proposition) */
.admin-card-btn--invalid {
    border-color: color-mix(in srgb, var(--danger-alt) 60%, transparent);
    background: color-mix(in srgb, var(--danger-alt) 8%, var(--surface-1));
}
.admin-card-err {
    display: block;
    margin-top: var(--space-1);
    font-size: var(--text-xs);
    color: var(--danger-alt);
}

/* Promo code display + admins list rows */
.admin-code-chip {
    flex: 1;
    font-family: var(--font-mono);
    font-weight: var(--weight-bold);
    letter-spacing: 2px;
    font-size: var(--text-lg);
    background: var(--surface-2);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    word-break: break-all;
}
.admin-list-item {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-2);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.admin-list-item-mono { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); word-break: break-all; }
.admin-list-name { font-weight: var(--weight-bold); flex: 1; }
.admin-section-title { margin: 0 0 var(--space-3); color: var(--gold); font-size: var(--text-sm); letter-spacing: 1px; }

/* Notes de version (modale admin, contenu dans changelog.js). */
/* Sans largeur bornee, la fenetre s etire jusqu a la plus longue ligne de note et
   deborde a droite du viewport : les notes etaient illisibles, coupees au bord.
   `.settings-modal` ne peut pas porter la borne (14 modales la partagent). */
#admin-releases-modal { width: min(94vw, 720px); max-width: 720px; }
.release-list li { overflow-wrap: anywhere; }
.release-entry + .release-entry { margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--border-subtle); }
.release-head { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-2); }
.release-version { margin: 0; font-size: var(--text-lg); font-weight: var(--weight-bold); }
.release-date { color: var(--text-muted); font-family: var(--font-mono); font-size: var(--text-xs); }
.release-title { margin: 0 0 var(--space-4); color: var(--text-muted); font-size: var(--text-sm); }
.release-section + .release-section { margin-top: var(--space-4); }
.release-list { margin: 0; padding-left: var(--space-5); font-size: var(--text-sm); line-height: 1.5; }
.release-list li + li { margin-top: var(--space-2); }
.admin-label-muted { display: block; font-size: var(--text-sm); color: var(--text-muted); margin: 0 0 var(--space-2); }
.admin-pad-3 { padding: var(--space-3); }
.admin-copy-btn { padding: var(--space-2) var(--space-4); white-space: nowrap; }
.admin-panel { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-4); }
.admin-icon-emoji { font-size: var(--text-base); }

/* index.html — admin-login-modal, admin-bar, admin-edit-modal,
   admin-catalogue-modal, daily-q-edit-modal and admin-create-modal shells. */
.modal--narrow { max-width: 400px; }
.admin-login-title { margin: 0 0 var(--space-2); }
.admin-login-hint { color: var(--text-muted); font-size: var(--text-sm); margin: 0 0 var(--space-4); }
.admin-login-error { color: var(--wrong-color); font-size: var(--text-sm); min-height: 1.2em; }

.admin-bar {
    display: none;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: color-mix(in srgb, var(--gold-tint) 15%, transparent);
    border-top: 1px solid var(--gold);
    padding: var(--space-2) var(--space-5);
    align-items: center;
    justify-content: space-between;
    z-index: var(--z-admin-bar);
    backdrop-filter: blur(var(--blur-sm));
    -webkit-backdrop-filter: blur(var(--blur-sm));
}
.admin-bar-label { font-size: var(--text-sm); color: var(--gold); font-weight: var(--weight-bold); letter-spacing: 1px; }
.admin-bar-actions { display: flex; gap: var(--space-3); flex-wrap: wrap; justify-content: flex-end; }
.admin-bar-btn { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }
/* Icônes de la barre admin : SVG au trait, couleur héritée du bouton (currentColor),
   pour qu'un état (danger, pulse) les emporte sans règle de plus. Remplacent les
   emojis, dont le rendu variait d'un OS à l'autre. */
.admin-bar-btn { display: inline-flex; align-items: center; gap: var(--space-2); }
.admin-bar-ico { width: 16px; height: 16px; flex: none; }
.admin-bar-count { font-variant-numeric: tabular-nums; }
.admin-bar-count[hidden] { display: none; }

/* Une file d'attente non traitée doit se voir sans lire le chiffre : pulsation lente
   de la bordure tant qu'au moins une proposition est en attente. Purement visuel —
   le compteur reste la source de vérité. */
.admin-bar-btn--alert { color: var(--gold); animation: admin-bar-pulse 2.4s ease-in-out infinite; }
/* La bordure pulse en plus du halo : un halo seul, sur un fond déjà doré, se voyait
   à peine — la barre admin baigne dans var(--gold-tint). */
@keyframes admin-bar-pulse {
    0%, 100% {
        border-color: color-mix(in srgb, var(--gold) 30%, transparent);
        box-shadow: 0 0 0 0 var(--gold-glow);
        background: transparent;
    }
    50% {
        border-color: var(--gold);
        box-shadow: 0 0 var(--space-4) var(--space-1) var(--gold-glow);
        background: color-mix(in srgb, var(--gold) 12%, transparent);
    }
}
@media (prefers-reduced-motion: reduce) {
    .admin-bar-btn--alert { animation: none; box-shadow: 0 0 var(--space-2) 0 var(--gold-glow); }
}
.admin-bar-btn--danger { border-color: color-mix(in srgb, var(--wrong-soft) 50%, transparent); color: color-mix(in srgb, var(--wrong-pale) 90%, transparent); }

.admin-field-feedback { color: var(--wrong-color); font-size: var(--text-sm); margin-top: var(--space-2); min-height: 1.2em; }
.admin-my-4 { margin: var(--space-4) 0; }
.admin-field--search { flex: 1; min-width: 180px; border-radius: var(--radius-btn); }
.admin-select {
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-btn);
    background: var(--surface-solid-1);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-family: inherit;
}
.admin-add-btn { padding: var(--space-3) var(--space-4); font-size: var(--text-sm); }
.admin-cat-list { overflow-y: auto; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--space-2); padding-right: var(--space-1); }
.admin-cat-footer { display: flex; justify-content: space-between; align-items: center; margin-top: var(--space-3); font-size: var(--text-sm); color: var(--text-muted); }
.admin-pager-btn { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }
.admin-page-indicator { line-height: 2; }
.admin-create-feedback { font-size: var(--text-sm); margin-top: var(--space-2); min-height: 1.2em; }


/* ==========================================================================
   HUD Simulation (Ctrl+Shift+D → onglet Simulation) — backstage
   ==========================================================================
   Remplace 29 attributs style="" construits dans simulation.js. Les 7 qui
   restent inline y portent une valeur calculée à l'exécution (largeur en %,
   couleur de badge), seule exception admise par CLAUDE.md.
   ========================================================================== */

.sim-empty {
    text-align: center;
    padding: var(--space-6);
    color: var(--text-muted);
    font-style: italic;
}

.sim-stack { display: flex; flex-direction: column; gap: var(--space-5); padding: var(--space-2); }

.sim-intro { font-size: var(--text-sm); color: var(--text-muted); line-height: 1.4; }

.sim-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    background: color-mix(in srgb, var(--shadow-base) 20%, transparent);
    padding: var(--space-5);
    border-radius: var(--radius-sm);
}

.sim-row-between { display: flex; justify-content: space-between; align-items: center; }

/* ── Anomalies ─────────────────────────────────────────── */
.sim-anomaly {
    background: color-mix(in srgb, var(--text-main) 2%, transparent);
    border-left: 4px solid var(--backstage);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    box-shadow: 0 2px 5px color-mix(in srgb, var(--shadow-base) 10%, transparent);
    margin-bottom: var(--space-2);
}

.sim-anomaly-type {
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-cta);
}

.sim-anomaly-badge {
    font-size: var(--text-2xs);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    font-weight: var(--weight-bold);
}

.sim-anomaly-msg { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-main); }

.sim-anomaly-path {
    font-size: var(--text-2xs);
    color: var(--text-muted);
    font-family: var(--font-mono, monospace);
    margin-top: var(--space-1);
}

/* ── Barres « crescendo » ──────────────────────────────── */
.sim-bar-head {
    display: flex;
    justify-content: space-between;
    font-size: var(--text-sm);
    margin-bottom: var(--space-1);
}

.sim-bar-label { font-weight: var(--weight-bold); }
.sim-bar-pct   { font-weight: var(--weight-bold); }

.sim-pct-duo   { color: var(--correct-color); }
.sim-pct-carre { color: var(--sim-carre-2); }
.sim-pct-cash  { color: var(--sim-cash-2); }
.sim-pct-super { color: var(--wrong-color); }

.sim-bar-track {
    height: 8px;
    background: color-mix(in srgb, var(--text-main) 5%, transparent);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.sim-bar-fill { height: 100%; border-radius: var(--radius-sm); }

.sim-fill-duo   { background: linear-gradient(90deg, var(--sim-duo-1), var(--correct-color)); }
.sim-fill-carre { background: linear-gradient(90deg, var(--sim-carre-1), var(--sim-carre-2)); }
.sim-fill-cash  { background: linear-gradient(90deg, var(--sim-cash-1), var(--sim-cash-2)); }
.sim-fill-super { background: linear-gradient(90deg, var(--sim-super-1), var(--wrong-color)); }

/* ── Liste des épisodes ────────────────────────────────── */
.sim-episode {
    background: color-mix(in srgb, var(--text-main) 1%, transparent);
    border: 1px solid color-mix(in srgb, var(--text-main) 3%, transparent);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-2);
}

.sim-episode-id    { font-weight: var(--weight-bold); color: var(--gold); font-size: var(--text-sm); }
.sim-episode-meta  { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--space-1); }
.sim-episode-right { text-align: right; }
.sim-episode-score { font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-main); }
.sim-episode-rate  { font-size: var(--text-2xs); color: var(--correct-color); font-weight: var(--weight-bold); }


/* Panneau Réglages sous 380 px : ancré en `top/right:20px` avec `min-width:320px`,
   son bord gauche tombait à -20px sur un écran de 320 (iPhone SE et consorts) —
   ni scroll ni repli, il sortait simplement du viewport. Correctif scopé par ID :
   `min-width` l'emporte sur `max-width`, il faut donc le relâcher explicitement,
   et la classe de base est partagée par 13 autres modales qu'on ne veut pas toucher. */
@media (max-width: 380px) {
    #settings-modal {
        min-width: 0;
        max-width: calc(100vw - 2 * var(--space-5));
    }
}

/* Propositions : dates, onglets, note admin, crédit communautaire */
.subm-tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); border-bottom: 1px solid var(--border-subtle); }
.subm-tab { background: none; border: 0; border-bottom: 2px solid transparent; color: var(--text-muted); font-family: inherit; font-size: var(--text-sm); font-weight: var(--weight-bold); letter-spacing: 0.5px; text-transform: uppercase; padding: var(--space-2) var(--space-3); cursor: pointer; }
.subm-tab:hover, .subm-tab:focus-visible { color: var(--text-main); }
.subm-tab--active { color: var(--gold); border-bottom-color: var(--gold); }
.subm-date { font-size: var(--text-xs); color: var(--text-muted); margin-bottom: var(--space-2); }
.subm-note { font-size: var(--text-sm); font-style: italic; color: color-mix(in srgb, var(--text-main) 60%, transparent); margin-bottom: var(--space-2); }
.subm-note-field { width: 100%; box-sizing: border-box; padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2); border-radius: var(--radius-sm); background: var(--surface-3); border: 1px solid var(--border); color: white; font-family: inherit; font-size: var(--text-sm); }
/* iOS zoome sur focus < 16px ; ce champ vit dans une modale position:fixed. */
@media (max-width: 767px) {
    .subm-note-field { font-size: var(--text-base); }
}
.prop-mine-date { flex-basis: 100%; font-size: var(--text-xs); color: var(--text-muted); }
.theme-announce-by { font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-2); }
.theme-announce-by strong { color: var(--gold); }
.admin-theme-line--sub { font-size: var(--text-sm); color: var(--text-muted); }

/* Propositions — revue admin : trois issues, chacune avec sa conséquence en clair.
   Le libellé seul induisait en erreur (« Accepter et relire » n'acceptait rien : il
   ouvrait l'éditeur). Colonne verticale, jamais une rangée de boutons équivalents. */
.subm-step { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--text-main); margin: var(--space-3) 0 var(--space-2); }
.subm-note-label { display: block; font-size: var(--text-xs); font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: 0.6px; color: var(--gold); margin-bottom: var(--space-1); }
.subm-note-hint { font-weight: var(--weight-medium); text-transform: none; letter-spacing: 0; color: var(--text-muted); }
.subm-choices { display: flex; flex-direction: column; gap: var(--space-2); }
.subm-choice { display: flex; align-items: center; gap: var(--space-3); }
.subm-choice .subm-btn { flex: 0 0 auto; min-width: 210px; }
.subm-choice-help { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.35; }
.subm-actions--view { margin-bottom: var(--space-2); }
/* Proposition acceptée : la programmer comme défi de demain. Rangée à part, au-dessus
   de « Remettre en attente » — c'est une mise en avant, pas une correction de verdict. */

/* Boutons d'une carte de proposition : tous la même allure. Le « défi de demain »
   était un btn-primary doré deux fois plus large que ses voisins, la carte n'avait
   plus de hiérarchie lisible — sur un onglet revu, aucune de ces actions n'est LE
   geste attendu. */
.subm-ico { width: 15px; height: 15px; flex: none; }
.subm-btn { display: inline-flex; align-items: center; gap: var(--space-2); }
.subm-actions--row { gap: var(--space-2); margin-bottom: var(--space-2); }
.subm-actions--row .subm-btn { flex: 0 0 auto; }

/* Carte repliée (onglets revus). Le triangle natif est remplacé par un chevron
   piloté en CSS : Safari n'expose pas ::-webkit-details-marker au même endroit que
   ::marker, on coupe les deux et on dessine le nôtre. */
.subm-card--fold { padding: 0; }
.subm-sum { cursor: pointer; list-style: none; padding: var(--space-3) var(--space-4); margin: 0; align-items: center; }
.subm-sum::-webkit-details-marker { display: none; }
.subm-sum::marker { content: ''; }
.subm-sum::before {
    content: '';
    flex: none;
    width: var(--space-2); height: var(--space-2);
    border-right: 2px solid var(--gold);
    border-bottom: 2px solid var(--gold);
    transform: rotate(-45deg);
    transition: transform var(--dur-fast) var(--ease-standard);
}
.subm-card--fold[open] > .subm-sum::before { transform: rotate(45deg); }
.subm-card--fold[open] > .subm-sum { border-bottom: 1px solid var(--border-subtle); }
.subm-sum:hover { background: var(--surface-2); }
.subm-fold-body { padding: var(--space-3) var(--space-4); }
.subm-card--fold .subm-booked { flex: 0 0 auto; font-size: var(--text-xs); }
@media (prefers-reduced-motion: reduce) {
    .subm-sum::before { transition: none; }
}
.subm-booked { flex: 1 1 auto; font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--gold); }
@media (max-width: 640px) {
    .subm-choice { flex-direction: column; align-items: stretch; gap: var(--space-1); }
    .subm-choice .subm-btn { min-width: 0; width: 100%; }
}

/* Propositions — côté joueur : la ligne « à corriger » est la seule où il a un geste
   à faire, elle porte donc la bordure or et le bouton. */
.prop-mine-changes { color: var(--gold); }
.prop-mine-row--todo { border: 1px solid var(--gold); background: color-mix(in srgb, var(--gold) 8%, var(--surface-1)); }
.prop-mine-help { flex-basis: 100%; font-size: var(--text-xs); color: var(--text-muted); }

/* Statistiques du thème publié, sur la ligne « Acceptée » (proposals.js,
   proposalStatsBlock). flex-basis 100% : le bloc prend sa propre ligne sous le
   statut, comme la note et l'aide, plutôt que de comprimer le nom du thème. */
.prop-stats { flex-basis: 100%; margin-top: var(--space-2); }
.prop-stats--empty { font-size: var(--text-xs); color: var(--text-muted); font-style: italic; }
.prop-stats-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
}
.prop-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-2);
    background: var(--surface-2);
    border-radius: var(--radius-sm);
    text-align: center;
}
.prop-stat-value { font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--gold); }
.prop-stat-label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 1px; color: var(--text-muted); }
.prop-stats-date { margin-top: var(--space-2); font-size: var(--text-2xs); color: var(--text-muted); text-align: right; }
.prop-mine-fix { flex-basis: 100%; margin-top: var(--space-1); }
.prop-fix-banner { border: 1px solid var(--gold); border-radius: var(--radius-md); background: color-mix(in srgb, var(--gold) 8%, transparent); padding: var(--space-3); margin-bottom: var(--space-3); }
.prop-fix-title { font-weight: var(--weight-bold); color: var(--gold); margin-bottom: var(--space-1); }
.prop-fix-note { font-style: italic; color: var(--text-main); margin: 0 0 var(--space-2); }
.prop-fix-help { font-size: var(--text-sm); color: var(--text-muted); margin: 0; }

/* --------------------------------------------------------------------
   Signalement de bug (bugs.js) — formulaire joueur et revue admin.
   Le formulaire n'a qu'un champ : tout l'espace visuel va à la
   description, la capture et le contexte restent secondaires.
   -------------------------------------------------------------------- */
.footer-bug-btn {
    background: color-mix(in srgb, var(--text-main) 6%, transparent);
    border: 1px solid var(--border);
    color: var(--text-muted);
    width: var(--control-icon);
    height: var(--control-icon);
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--dur-base) var(--ease-standard);
}
.footer-bug-btn:hover, .footer-bug-btn:focus-visible { color: var(--gold); border-color: var(--gold); }

.bug-label { display: block; font-size: var(--text-sm); color: var(--text-muted); margin: var(--space-4) 0 var(--space-2); }
.bug-desc { resize: vertical; min-height: 5.5rem; }
/* iOS zoome sur focus < 16px ; ce champ vit dans une modale position:fixed. */
@media (max-width: 767px) {
    .bug-desc { font-size: var(--text-base); }
}
.bug-shot-row { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-3); flex-wrap: wrap; }
.bug-shot-btn { padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
.bug-shot-hint { font-size: var(--text-xs); color: var(--text-muted); }
/* Le champ fichier natif n'est jamais montré : c'est le bouton ci-dessus qui
   l'ouvre. `display:none` le retirerait de l'arbre — il doit rester cliquable
   par programme, d'où la mise hors champ. */
.bug-shot-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.bug-shot-preview { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-3); flex-wrap: wrap; }
.bug-shot-thumb { max-width: 120px; max-height: 90px; border-radius: var(--radius-sm); border: 1px solid var(--border); display: block; }
.bug-shot-size { font-size: var(--text-xs); color: var(--text-muted); }
.bug-shot-drop { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); }
.bug-where-line { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-3) 0 0; }
.bug-where-line span { color: var(--gold); }
.bug-feedback { font-size: var(--text-sm); min-height: 1em; margin: var(--space-2) 0 0; }

.bug-card { background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); margin-bottom: var(--space-3); }
.bug-card-head { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-2); }
.bug-card-where { font-weight: var(--weight-bold); color: var(--gold); }
.bug-card-meta { font-size: var(--text-sm); color: var(--text-muted); }
.bug-card-desc { color: var(--text-main); margin: 0 0 var(--space-2); line-height: 1.4; white-space: pre-wrap; }
.bug-card-tech { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-2) 0 0; word-break: break-word; }
.bug-card-errs { font-size: var(--text-xs); color: var(--wrong-soft); margin: var(--space-2) 0 0; padding-left: var(--space-5); word-break: break-word; }
.bug-card-acts { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-3); }
.bug-act { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); }
.bug-act--danger { border-color: color-mix(in srgb, var(--wrong-soft) 50%, transparent); color: color-mix(in srgb, var(--wrong-pale) 90%, transparent); }
.bug-shot-open { background: none; border: 0; padding: 0; cursor: zoom-in; }

/* Réponse de l'admin à l'auteur du signalement (repliée par défaut : le triage se
   fait au statut, répondre est le geste rare). */
.bug-reply { margin-top: var(--space-3); border-top: 1px solid var(--border-subtle); padding-top: var(--space-2); }
.bug-reply-sum { font-size: var(--text-xs); color: var(--text-muted); cursor: pointer; }
.bug-reply-done { color: var(--correct-color); margin-left: var(--space-2); }
.bug-reply-input { width: 100%; margin-top: var(--space-2); resize: vertical; min-height: 4rem; font-size: var(--text-sm); }
.bug-reply-acts { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-2); }
.bug-reply-fb { font-size: var(--text-xs); min-height: 1em; }
.bug-card-anon { font-size: var(--text-xs); color: var(--text-muted); margin: var(--space-3) 0 0; font-style: italic; }

/* « Mes signalements » (profil joueur) — même grammaire que .prop-mine. */
.bug-mine { display: flex; flex-direction: column; gap: var(--space-2); }
.bug-mine-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: var(--text-sm); padding: var(--space-2); background: var(--surface-1); border-radius: var(--radius-sm); min-width: 0; }
.bug-mine-row--fresh { border: 1px solid var(--gold); background: color-mix(in srgb, var(--gold) 8%, var(--surface-1)); }
.bug-mine-desc { min-width: 0; overflow-wrap: anywhere; color: var(--text-main); }
.bug-mine-status { margin-left: auto; font-weight: var(--weight-bold); font-size: var(--text-xs); }
.bug-mine-new, .bug-mine-seen { color: var(--gold); }
.bug-mine-fixed { color: var(--correct-color); }
.bug-mine-wontfix { color: var(--wrong-color); }
.bug-mine-date { flex-basis: 100%; font-size: var(--text-xs); color: var(--text-muted); }
.bug-mine-reply { flex-basis: 100%; font-size: var(--text-xs); color: var(--text-main); overflow-wrap: anywhere; }

/* ==========================================================================
   Axe badges (I1) — bilan et profil
   ========================================================================== */
.bilan-badges {
    margin-top: var(--space-4);
    padding: var(--space-2) var(--space-3);
    background: color-mix(in srgb, var(--gold) 10%, transparent);
    border: 1px solid var(--gold-glow);
    border-radius: var(--radius-md);
    color: var(--gold);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.badge-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--space-3);
    margin-top: var(--space-3);
}

.badge {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    transition: border-color var(--dur-fast) var(--ease-standard);
}

.badge-body {
    flex: 1;
    min-width: 0;
}

/* Médaillon : le dessin du badge, doré une fois acquis, éteint tant qu'il est verrouillé. */
.badge-medal {
    flex: none;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-subtle);
    background: var(--surface-2);
    color: var(--text-muted);
    transition: color var(--dur-fast) var(--ease-standard),
                border-color var(--dur-fast) var(--ease-standard);
}

.badge-icon {
    width: 24px;
    height: 24px;
}

.badge:not(.badge--locked) {
    border-color: var(--gold-glow);
    background: color-mix(in srgb, var(--gold) 6%, var(--surface-1));
}

.badge:not(.badge--locked) .badge-medal {
    color: var(--gold);
    border-color: var(--gold-glow);
    background: color-mix(in srgb, var(--gold) 12%, var(--surface-2));
}

.badge-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-2);
    margin-bottom: var(--space-1);
}

.badge-name {
    margin-right: auto;
    font-weight: var(--weight-bold);
    color: var(--gold);
    font-size: var(--text-sm);
}

.badge-date {
    font-size: var(--text-2xs);
    color: var(--text-muted);
    white-space: nowrap;
}

/* Rareté d’un badge : puce de la ligne de titre, à droite de la date.
   Ne paraît qu’aux extrêmes (stats.js, badgeRarityChip) : un badge que 34 % des
   joueurs ont n’apprend rien, et vingt-trois nombres dans la grille, c’est la
   grille qu’on perd. Le doré est réservé au rare ; le commun reste éteint, il
   informe sans réclamer le regard que mérite le nom du badge. */
.badge-rarity {
    flex: none;
    padding: 0 var(--space-2);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.badge-rarity--rare {
    color: var(--gold);
    border-color: var(--gold-glow);
    background: color-mix(in srgb, var(--gold) 12%, transparent);
}

/* « Inédit » : badge verrouillé que personne ne détient dans l’instantané. Ce
   n’est pas un pourcentage, c’est une place à prendre — il lui faut donc sa
   propre marque, sinon il se lit comme une variante du rare. La palette est
   noir/rouge/or : une quatrième teinte n’existe pas. C’est donc le TRAIT et le
   MOUVEMENT qui distinguent — bordure pointillée (un emplacement à remplir, pas
   un trophée gagné) et une pulsation lente, la seule chose qui bouge dans une
   grille immobile. Lente exprès : 3,2 s, et l’opacité seule — un clignotement
   rapide sur une carte qu’on lit est une nuisance, pas une invitation. */
.badge-rarity--first {
    color: var(--gold);
    border-style: dashed;
    border-color: var(--gold-glow);
    background: transparent;
    animation: badge-first-pulse 3.2s ease-in-out infinite;
}
/* Plancher 0,65 : au creux, l'or reste au-dessus de 4,5:1 sur la carte (0,45
   tombait à 3,3:1, un chiffre illisible une demi-période sur deux). */
@keyframes badge-first-pulse {
    0%, 100% { opacity: 0.65; }
    50%      { opacity: 1; }
}
/* Sans mouvement, la puce doit rester lisible : elle se fige au maximum de la
   pulsation, jamais au plancher — figer la phase basse rendrait le chiffre plus
   discret que les autres puces, l’inverse de ce qu’il veut dire. */
@media (prefers-reduced-motion: reduce) {
    .badge-rarity--first { animation: none; opacity: 1; }
}

.badge-rarity--common {
    color: var(--text-muted);
    background: var(--surface-3);
}

.badge-desc {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.4;
}

/* Verrouillé : seul le médaillon s'éteint. Une opacité sur toute la carte ramenait
   le texte à 3,2:1 et se multipliait avec la pulsation de la puce « 0 % » (1,9:1
   au creux) : le texte garde ses couleurs, déjà atténuées ci-dessous. */
.badge--locked .badge-medal {
    opacity: 0.55;
}

.badge--locked .badge-name {
    color: var(--text-muted);
}

/* Jauge d'un badge verrouillé : même grammaire que .profile-bar-track (piste
   creusée, remplissage doré), en plus discret — c'est un encouragement, pas
   une statistique. La largeur passe en --pf-w, calculée à l'exécution. */
.badge-prog {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.badge-prog-track {
    flex: 1;
    min-width: 0;
    height: 4px;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    overflow: hidden;
}

.badge-prog-fill {
    height: 100%;
    width: var(--pf-w, 0%);
    border-radius: var(--radius-pill);
    background: var(--gold-tint);
}

.badge-prog-val {
    flex: none;
    font-size: var(--text-2xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* ===== Scan des alternatives (admin-scan-alts.js) ===== */
/* Sous-modale ouverte par-dessus « Partie du jour » ou le catalogue. Même charpente que
   #admin-daily-modal : en-tête fixe, région scrollable, pied d'actions. */

#scan-alts-modal {
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -45%) scale(0.97);
    width: min(96vw, 860px);
    height: min(88vh, 820px);
    height: min(88svh, 820px);
    max-height: calc(100vh - 32px);
    max-height: calc(100svh - 32px);
    min-width: 0;
    padding: 0;
    overflow: hidden;
    display: none;
    flex-direction: column;
    background: color-mix(in srgb, var(--ink-18) 98%, transparent);
    border-color: var(--border);
    border-radius: 18px;
}
#scan-alts-modal.active {
    display: flex;
    transform: translate(-50%, -50%) scale(1);
}

.sa-sub { margin: var(--space-1) 0 0; font-size: var(--text-xs); color: var(--text-muted); overflow-wrap: anywhere; }

/* Rien à l'écran ne disait ce qu'EST une alternative : une phrase, une seule, en tête. */
.sa-intro {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    font-size: var(--text-sm);
    line-height: 1.5;
    color: color-mix(in srgb, var(--text-main) 82%, transparent);
}
.sa-intro strong { color: var(--text-main); font-weight: var(--weight-bold); }

/* Avertissement : troncature du lot, ou passe IA absente. Jamais silencieux. */
.sa-warn {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--warn-soft) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn-soft) 34%, transparent);
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--warn-soft);
    overflow-wrap: anywhere;
}

.sa-summary { margin: 0 0 var(--space-4); font-size: var(--text-xs); color: var(--text-muted); }

/* Trois sections, trois rangs de confiance. La teinte se porte par le glyphe, le compteur et un
   contour fin — pas par un aplat, qui écraserait la hiérarchie sur trois blocs empilés. */
.sa-section {
    margin: 0 0 var(--space-4);
    padding: var(--space-4);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
}
.sa-section--auto   { border-color: color-mix(in srgb, var(--correct-color) 32%, transparent); }
.sa-section--ia     { border-color: color-mix(in srgb, var(--gold) 30%, transparent); }
.sa-section--review { border-color: color-mix(in srgb, var(--warn-soft) 32%, transparent); }

.sa-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); }
.sa-section-title {
    display: flex; align-items: center; gap: var(--space-2);
    margin: 0; font-size: var(--text-sm); font-weight: var(--weight-bold);
    letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-main);
}
.sa-section-glyph {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: var(--radius-sm); font-size: var(--text-xs);
}
.sa-section-count { font-size: var(--text-xs); font-weight: var(--weight-bold); border-radius: var(--radius-pill); padding: 2px var(--space-2); }
.sa-section--auto   .sa-section-glyph, .sa-section--auto   .sa-section-count { color: var(--correct-color); background: color-mix(in srgb, var(--correct-color) 16%, transparent); }
.sa-section--ia     .sa-section-glyph, .sa-section--ia     .sa-section-count { color: var(--gold);          background: color-mix(in srgb, var(--gold) 16%, transparent); }
.sa-section--review .sa-section-glyph, .sa-section--review .sa-section-count { color: var(--warn-soft);     background: color-mix(in srgb, var(--warn-soft) 16%, transparent); }

.sa-section-hint { margin: var(--space-2) 0 0; font-size: var(--text-xs); line-height: 1.5; color: var(--text-muted); max-width: 62ch; }

/* Le libellé porte l'ACTION à venir : un bouton « TOUT » ne disait pas s'il cochait ou décochait. */
.sa-allbtn {
    flex-shrink: 0;
    min-height: var(--control-h-md);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-btn);
    border: 1px solid var(--border);
    background: var(--surface-2);
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    cursor: pointer;
    transition: background var(--dur-fast);
}
.sa-allbtn:hover { background: var(--surface-3); }

.sa-rows { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }

/* Ligne sur trois niveaux : de quelle question on parle, la décision, puis le motif en retrait. */
.sa-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-rows: auto auto auto;
    gap: var(--space-1) var(--space-3);
    align-items: center;
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    cursor: pointer;
    transition: background var(--dur-fast);
}
.sa-row:hover { background: var(--surface-2); }
.sa-row[data-full="1"] { opacity: 0.45; cursor: default; }
.sa-check { grid-column: 1; grid-row: 1 / span 3; width: 20px; height: 20px; align-self: start; margin-top: 3px; accent-color: var(--gold); }
.sa-row-q { grid-column: 2 / span 2; grid-row: 1; display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; font-size: var(--text-xs); color: var(--text-muted); }
.sa-row-num { flex-shrink: 0; font-weight: var(--weight-bold); border-radius: var(--radius-sm); padding: 2px var(--space-2); background: var(--surface-2); }
.sa-row-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sa-row-change { grid-column: 2; grid-row: 2; min-width: 0; font-size: var(--text-md); color: var(--text-muted); overflow-wrap: anywhere; line-height: 1.4; }
.sa-row-change strong { color: var(--text-main); font-weight: var(--weight-bold); }
.sa-arrow { padding: 0 var(--space-2); opacity: 0.6; }
.sa-trust {
    grid-column: 3; grid-row: 2;
    flex-shrink: 0; white-space: nowrap;
    font-size: var(--text-xs); font-weight: var(--weight-medium);
    border-radius: var(--radius-pill); padding: 4px var(--space-3);
    border: 1px solid var(--border-subtle);
}
.sa-trust--high { color: var(--correct-color); background: color-mix(in srgb, var(--correct-color) 14%, transparent); border-color: color-mix(in srgb, var(--correct-color) 32%, transparent); }
.sa-trust--mid  { color: var(--gold);          background: color-mix(in srgb, var(--gold) 14%, transparent);          border-color: color-mix(in srgb, var(--gold) 30%, transparent); }
.sa-trust--low  { color: var(--text-muted);    background: var(--surface-2); }
.sa-why { grid-column: 2 / span 2; grid-row: 3; font-size: var(--text-xs); color: var(--text-muted); overflow-wrap: anywhere; }

.sa-foot-note { flex: 1 1 auto; min-width: 0; font-size: var(--text-xs); color: var(--text-muted); }

/* Loupe du catalogue : même géométrie que la corbeille voisine, teinte neutre (l'accent reste
   réservé à l'action en cours, pas à un outil toujours présent). */
.cat-theme-scan {
    flex-shrink: 0;
    margin-left: var(--space-2);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-btn);
    color: var(--text-muted);
    cursor: pointer;
    padding: var(--space-2);
    display: inline-flex;
    align-items: center;
    transition: background var(--dur-fast), color var(--dur-fast);
}
.cat-theme-scan:hover { background: var(--surface-3); color: var(--gold); }

@media (max-width: 640px) {
    .sa-section-head { flex-direction: column; gap: var(--space-2); }
    .sa-allbtn { width: 100%; }
    .sa-row { grid-template-columns: auto 1fr; }
    .sa-row-q, .sa-why { grid-column: 2; }
    .sa-row-change { grid-column: 2; }
    .sa-trust { grid-column: 2; grid-row: 4; justify-self: start; }
}
/* ══════════════════════════════════════════════════════════════════════════
   Défi entre amis (challenge.js) — barre à checkpoints, choix du thème, bloc
   du bilan, carte « Mes défis » du profil. L'accueil n'a plus de carte de défi
   (2026-09-10) : l'entrée vit en tête du profil.
   ══════════════════════════════════════════════════════════════════════════ */
/* Icône d'interface (ui.js, uiIcon) : tracée en currentColor, calée sur la ligne de
   texte. 1em, pas une taille fixe : une icône dans un bouton --text-xs doit rétrécir
   avec lui. */
.ui-icon { width: 1.15em; height: 1.15em; flex-shrink: 0; vertical-align: -0.16em; }

/* Barre à checkpoints du défi (challenge.js, challengeBarHtml). Trois états : faite,
   en cours, à venir. La ligne qui relie les pastilles est un pseudo-élément — pas un
   trait dessiné entre deux éléments, qui se décalerait au retour à la ligne. */
.chk-bar {
    display: flex; align-items: flex-start; justify-content: center;
    gap: 0; margin: 0 0 var(--space-5); padding: 0; list-style: none;
}
.chk-step {
    position: relative; flex: 1 1 0; min-width: 0; max-width: 180px;
    display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
    text-align: center;
}
/* Le trait s'arrête à 20 px de chaque pastille au lieu de courir de centre à centre :
   les étapes se peignent dans l'ordre du DOM, et un trait qui va jusqu'au centre passe
   PAR-DESSUS la pastille précédente, quel que soit son z-index (autre contexte
   d'empilement). Rogner le trait règle le problème sans empiler quoi que ce soit. */
.chk-step::before {
    content: ''; position: absolute; top: 13px;
    left: calc(-50% + 20px); width: calc(100% - 40px); height: 2px;
    background: var(--border);
}
.chk-step:first-child::before { display: none; }
.chk-step--done::before, .chk-step--now::before { background: var(--gold); }
.chk-dot {
    position: relative; z-index: var(--z-raised);
    width: 28px; height: 28px; border-radius: var(--radius-pill);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--text-xs); font-weight: var(--weight-bold);
    border: 2px solid var(--border); background: var(--surface-2); color: var(--text-muted);
}
.chk-label { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.25; }
.chk-step--done .chk-dot { border-color: var(--gold); background: var(--gold); color: var(--on-gold); }
.chk-step--done .chk-label { color: var(--text-muted); }
.chk-step--now .chk-dot { border-color: var(--gold); color: var(--gold); background: color-mix(in srgb, var(--gold) 14%, transparent); }
.chk-step--now .chk-label { color: var(--gold); font-weight: var(--weight-bold); }

/* Règles du défi : un lien discret qui ouvre la modale d'information. C'était un
   <details> — dans un écran qui défile, l'ouvrir poussait les thèmes (et au bilan les
   boutons) hors de vue. Une modale ne déplace rien sous les doigts (2026-09-10). */
.chk-rules-link {
    display: inline-block; margin: var(--space-4) auto 0;
    background: none; border: none; padding: var(--space-2) var(--space-3);
    font-family: inherit; font-size: var(--text-sm); color: var(--text-muted);
    text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
    transition: color var(--dur-fast);
}
.chk-rules-link:hover { color: var(--gold); }

/* Le score serveur tarde : dit sous le bouton, pas à sa place. */
.challenge-bilan-wait { margin: var(--space-3) 0 0; font-size: var(--text-xs); color: var(--text-muted); }

/* Comparatif des six questions (challengeCompareHtml) : deux colonnes, vous et
   l'adversaire, une ligne par question. Table et non grille de <div> : ce sont des
   données tabulaires, et un lecteur d'écran doit pouvoir annoncer « ligne 3, colonne
   Marie ». `table-layout: fixed` pour que la colonne 1 ne s'élargisse pas sur un nom long. */
.cmp-wrap { max-width: 520px; margin: var(--space-5) auto 0; overflow-x: auto; }
.cmp-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.cmp-table thead th {
    padding: var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-chip); text-transform: uppercase; color: var(--gold);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmp-table thead td { width: 2.2rem; }
.cmp-num {
    width: 2.2rem; padding: var(--space-2); text-align: center;
    font-size: var(--text-xs); font-weight: var(--weight-bold); color: var(--text-muted);
}
.cmp-cell {
    padding: var(--space-2); text-align: center; vertical-align: middle;
    border-top: 1px solid var(--border-subtle);
    font-size: var(--text-xs); line-height: 1.35;
}
.cmp-cell--ok { color: var(--correct-color); }
.cmp-cell--ko { color: var(--wrong-color); }
.cmp-mark { display: block; }
.cmp-mark .ui-icon { width: 1.2em; height: 1.2em; }
.cmp-mode { display: block; color: var(--text-main); font-weight: var(--weight-bold); }
.cmp-time { display: block; color: var(--text-muted); }

/* La règle d'égalité au bilan : en clair, jamais derrière un clic. */
.chk-tie {
    max-width: 520px; margin: var(--space-3) auto 0;
    padding: var(--space-2) var(--space-4);
    border-left: 3px solid var(--gold); border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--gold) 8%, transparent);
    font-size: var(--text-sm); color: var(--text-main); text-align: left;
}

/* Badge à décrocher, étape 1 seulement et seulement s'il manque au joueur. */
.chk-badge {
    display: flex; align-items: center; justify-content: center; gap: var(--space-2);
    max-width: 520px; margin: var(--space-4) auto 0;
    padding: var(--space-2) var(--space-4);
    border: 1px dashed var(--border); border-radius: var(--radius-pill);
    font-size: var(--text-sm); color: var(--text-muted);
}
.chk-badge-txt { flex: 1 1 auto; min-width: 0; }
.chk-badge-name { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--gold); }
.chk-badge .badge-icon { width: 1.25em; height: 1.25em; flex-shrink: 0; vertical-align: -0.15em; }
.chk-badge-prog { font-size: var(--text-xs); color: var(--text-muted); opacity: .8; }

@media (max-width: 420px) {
    .chk-label { font-size: var(--text-2xs); }
    .chk-badge { flex-wrap: wrap; border-radius: var(--radius-md); }
}

/* Choix du thème : la grille des sélecteurs de manche, sans catalogue ni recherche. */
.challenge-pick { width: 100%; }
.challenge-pick-hint {
    max-width: 640px;
    margin: 0 auto var(--space-5);
    font-size: var(--text-sm);
    color: var(--text-muted);
    text-align: center;
}

/* Bloc du bilan : rempli par le flux du doc (verdict serveur). */
.challenge-bilan {
    margin: 0 auto var(--space-5);
    padding: var(--space-4) var(--space-5);
    border: 1px solid color-mix(in srgb, var(--gold-tint) 30%, transparent);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--gold-tint) 6%, transparent);
    text-align: center;
}
.challenge-bilan-title { margin: 0 0 var(--space-2); font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--gold); }
.challenge-bilan-note { margin: 0; font-size: var(--text-sm); color: var(--text-muted); }
.challenge-bilan-note strong { color: var(--text-main); }
.challenge-bilan-link { margin: var(--space-3) 0 0; font-size: var(--text-xs); color: var(--text-muted); overflow-wrap: anywhere; }
.challenge-bilan-link code { font-family: inherit; }
.challenge-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); margin-top: var(--space-4); }

/* Profil : « Mes défis ». */
.challenge-mine { display: flex; flex-direction: column; gap: var(--space-3); }
.challenge-list-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.challenge-list-title { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 1.6px; color: var(--text-muted); }
.challenge-row-btn { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); flex-shrink: 0; }
.challenge-list { display: flex; flex-direction: column; gap: var(--space-2); }
.challenge-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--surface-2);
    border-radius: var(--radius-sm);
    min-width: 0;
}
.challenge-row-main { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; flex: 1; }
.challenge-row-theme { font-weight: var(--weight-medium); color: var(--text-main); font-size: var(--text-sm); overflow-wrap: anywhere; }
.challenge-row-meta { font-size: var(--text-xs); color: var(--text-muted); }
.challenge-hist-summary { cursor: pointer; font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 1.6px; color: var(--text-muted); padding: var(--space-2) 0; }
.challenge-hist-list { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.challenge-hist-row {
    display: grid;
    grid-template-columns: auto 1fr auto auto auto;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-xs);
    color: var(--text-muted);
    border-radius: var(--radius-sm);
}
.challenge-hist-label { font-weight: var(--weight-bold); min-width: 3.2em; }
.challenge-hist--won .challenge-hist-label { color: var(--correct-color); }
.challenge-hist--lost .challenge-hist-label { color: var(--wrong-color); }
.challenge-hist--none .challenge-hist-label { color: var(--text-muted); }
.challenge-hist-theme { color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.challenge-hist-score { font-variant-numeric: tabular-nums; white-space: nowrap; }
.challenge-hist-who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 9em; }
.challenge-hist-date { white-space: nowrap; }
@media (max-width: 520px) {
    .challenge-hist-row { grid-template-columns: auto 1fr auto; }
    .challenge-hist-who, .challenge-hist-date { grid-column: 2 / -1; }
}

/* ─── Relecteur (2026-09-11, reviewer.js) ───────────────────────────────────────
   Le bandeau reprend l'allure du bandeau admin (mêmes classes) ; sa visibilité tient
   dans une classe, pas un style inline. Le panneau réutilise les cartes et champs des
   propositions (.subm-*, .prop-input). */
.admin-bar--on { display: flex; }
.admin-bar--reviewer .admin-bar-label { color: var(--mode-carre); }
.admin-bar--reviewer { border-top-color: var(--mode-carre); background: color-mix(in srgb, var(--mode-carre) 10%, transparent); }
.rv-form { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.rv-field { display: grid; gap: var(--space-1); }
.rv-label { font-size: var(--text-xs); color: var(--text-muted); letter-spacing: 0.5px; text-transform: uppercase; }
.rv-q { border-top: 1px solid var(--border-subtle); padding-top: var(--space-3); display: grid; gap: var(--space-2); }
.rv-q-head { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--gold); }
.rv-q .prop-input { font-size: var(--text-sm); }
.rv-q textarea.prop-input { min-height: 3.2em; }
.rv-answers { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.rv-answers .prop-input { flex: 1 1 160px; }
.rv-answers .prop-input--correct { border-color: color-mix(in srgb, var(--correct-color) 60%, transparent); }
.rv-state { font-size: var(--text-sm); margin-top: var(--space-2); }
.rv-state--busy { color: var(--gold); }
.rv-state--ok { color: var(--correct-color); }
.rv-state--err { color: var(--wrong-color); }
.rv-choices { margin-top: var(--space-3); }

/* ───── Barre d'onglets du site et volets Duels / Classements (2026-09-17) ─────
   Trois vues de #screen-home. En haut sur ordinateur ; en bas sur mobile, `sticky` et non
   `fixed` : #screen-home garde le `transform` de son animation d'entrée (fill forwards), qui
   en ferait le bloc conteneur d'un enfant fixe — la barre se poserait au bas de la PAGE. */
.site-tabs {
    display: flex;
    justify-content: center;
    gap: var(--space-2);
    margin: 0 auto var(--space-5);
    padding: var(--space-1);
    width: fit-content;
    max-width: 100%;
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
}
.site-tabs[hidden] { display: none; }
.site-tabs--bottom { display: none; }
.site-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 44px;
    padding: var(--space-2) var(--space-5);
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    letter-spacing: 0.4px;
    cursor: pointer;
    transition: color var(--dur-fast), background var(--dur-fast);
}
.site-tab:hover { color: var(--text-main); background: var(--surface-2); }
.site-tab[aria-current="page"] { color: var(--on-gold); background: var(--gold); }
.site-tab:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--wrong-color);
    color: var(--on-gold);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    font-style: normal;
}
.tab-badge[hidden] { display: none; }

/* Hors de l'accueil, le fauteuil et le titre cèdent la place : le volet commence en haut. */
#screen-home[data-tab="duels"] .logo-container,
#screen-home[data-tab="ranks"] .logo-container,
#screen-home[data-tab="duels"] .home-header-divider,
#screen-home[data-tab="ranks"] .home-header-divider { display: none; }
#screen-home[data-tab="duels"] .home-header,
#screen-home[data-tab="ranks"] .home-header { min-height: 44px; margin-bottom: var(--space-4); }

.site-pane { max-width: 760px; margin: 0 auto; }
.site-pane[hidden] { display: none; }
.duels-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-4); }
.duels-title { margin: 0 0 var(--space-3); font-size: var(--text-xl); font-weight: var(--weight-display); letter-spacing: 1px; }
.duels-head .duels-title { margin: 0; }
.duels-elo { margin: 0; color: var(--gold); font-size: var(--text-sm); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; }
.duels-tabs { margin-bottom: var(--space-4); }
.duels-tabs .adp-tab { min-height: 44px; }
.duels-tabs .adp-tab .tab-badge { position: static; transform: none; margin-left: var(--space-2); }
/* `.adp-tab b` (panneau admin) recolore tout <b> : sur la pastille rouge cela donnait 2,35:1
   (onglet actif) et 1,59:1. On rend sa couleur au jeton, à une spécificité qui gagne. */
.duels-tabs .adp-tab .tab-badge,
.duels-tabs .adp-tab.is-active .tab-badge { color: var(--on-gold); }
/* `.prop-mine-empty` porte opacity .6 (3,86:1) : ici ce sont des phrases qui expliquent. */
.site-pane .prop-mine-empty { opacity: 1; }
.duels-pane { min-height: 12rem; }
.duels-pane:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: var(--radius-sm); }
.duels-section { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-5) 0 var(--space-2); font-size: var(--text-2xs); font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: 1.6px; color: var(--text-muted); }
.duels-section:first-child { margin-top: 0; }
.duels-hint { margin: 0 0 var(--space-3); font-size: var(--text-xs); color: var(--text-muted); }
.duels-all-players { display: inline-block; margin-top: var(--space-2); }
.duels-pitch { text-align: center; max-width: 520px; margin: var(--space-6) auto; color: var(--text-muted); }
.duels-foot { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--border-subtle); text-align: center; }
.duels-foot .challenge-actions { margin-top: 0; }
.duels-available { display: block; margin: var(--space-4) 0 var(--space-2); font-size: var(--text-sm); cursor: pointer; }
.duels-available input { width: 24px; height: 24px; margin-right: var(--space-2); vertical-align: -6px; accent-color: var(--gold); }
.duels-available-hint { display: block; margin-top: var(--space-1); font-size: var(--text-xs); color: var(--text-muted); }
.site-pane .challenge-row { flex-wrap: wrap; }
.site-pane .challenge-row-btn { min-height: 44px; }
.site-pane .challenge-hist-row { grid-template-columns: auto 1fr auto auto; }

.duel-delta { margin: var(--space-2) 0 0; font-size: var(--text-lg); font-variant-numeric: tabular-nums; }
.duel-delta--up strong { color: var(--correct-color); }
.duel-delta--down strong { color: var(--wrong-color); }
.duel-delta--flat strong { color: var(--text-muted); }

.duel-ranks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.duel-rank { display: grid; grid-template-columns: 2.4em 1fr auto 3.4em; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--surface-1); font-size: var(--text-sm); }
.duel-rank--me { background: color-mix(in srgb, var(--gold-tint) 14%, transparent); outline: 1px solid color-mix(in srgb, var(--gold-tint) 45%, transparent); }
.duel-rank-pos { color: var(--text-muted); font-variant-numeric: tabular-nums; text-align: right; }
.duel-rank-name { overflow-wrap: anywhere; min-width: 0; }
.duel-rank-record { color: var(--text-muted); font-size: var(--text-xs); white-space: nowrap; }
.duel-rank-elo { color: var(--gold); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; text-align: right; }
.duel-ranks--me { margin-top: var(--space-3); }

@media (max-width: 640px) {
    /* Sur mobile, c'est le SECOND exemplaire de la barre qui s'affiche (index.html) : placé
       après les volets dans le DOM, donc en bas à l'écran ET en fin de tabulation. */
    .site-tabs--top { display: none; }
    body.has-site-tabs .site-tabs--bottom {
        display: flex;
        position: sticky;
        bottom: var(--space-2);
        z-index: var(--z-raised);
        width: 100%;
        margin: var(--space-5) 0 0;
        justify-content: space-between;
        background: var(--bg-deep);
        border-color: var(--border);
    }
    body.has-site-tabs .site-tab { flex: 1; justify-content: center; padding: var(--space-2); }
    /* La barre admin est fixe en bas : sous `admin-active` c'est l'exemplaire du HAUT qui sert. */
    body.has-site-tabs.admin-active .site-tabs--top { display: flex; width: 100%; justify-content: space-between; margin-bottom: var(--space-4); }
    body.has-site-tabs.admin-active .site-tabs--bottom { display: none; }
    /* Le navigateur amène l'élément focalisé à l'écran sans savoir qu'une barre collante le
       recouvre : la marge de défilement lui réserve la place (WCAG 2.4.11). */
    html.has-site-tabs { scroll-padding-bottom: calc(var(--space-8) + var(--space-4)); }
    /* Le bilan V/N/D passe sous le nom au lieu de disparaître : à 200 % de zoom un écran
       d'ordinateur tombe sous 640 px, et l'information doit rester (WCAG 1.4.10). */
    .duel-rank { grid-template-columns: 2em 1fr 3.2em; align-items: start; }
    .duel-rank-record { grid-column: 2; grid-row: 2; font-size: var(--text-2xs); }
    .site-pane .challenge-hist-row { grid-template-columns: auto 1fr auto; }
}
@media (prefers-reduced-motion: reduce) {
    .site-tab { transition: none; }
}

/* Arbitre des duels (tableau de bord AUDIENCE, onglet Duels). */
.duel-ref-list { display: flex; flex-direction: column; gap: var(--space-1); }
.duel-ref-row { border-radius: var(--radius-sm); background: var(--surface-1); }
.duel-ref-row.is-open { background: var(--surface-2); }
.duel-ref-head { display: grid; grid-template-columns: 1fr; gap: var(--space-1); width: 100%; min-height: 44px; padding: var(--space-2) var(--space-3); border: 0; background: transparent; color: var(--text-main); font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer; border-radius: var(--radius-sm); }
.duel-ref-head:hover { background: var(--surface-2); }
.duel-ref-head:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.duel-ref-names strong { color: var(--gold); font-variant-numeric: tabular-nums; }
.duel-ref-meta { font-size: var(--text-xs); color: var(--text-muted); }
.duel-ref-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.duel-ref-chips:empty { display: none; }
.aud-chip { display: inline-block; padding: 0 var(--space-2); border-radius: var(--radius-pill); font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: 0.4px; border: 1px solid var(--border); color: var(--text-muted); }
.aud-chip--warn { border-color: color-mix(in srgb, var(--gold-tint) 55%, transparent); color: var(--gold); }
.duel-ref-detail { padding: var(--space-2) var(--space-3) var(--space-3); }
.duel-ref-runs { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-3); }
.duel-ref-run { padding: var(--space-3); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); }
.duel-ref-flags { margin: var(--space-2) 0; padding-left: var(--space-4); font-size: var(--text-xs); color: var(--text-muted); overflow-wrap: anywhere; }
.duel-ref-flags--warn { color: var(--gold); }
.duel-ref-btn { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); min-height: 44px; }
.duel-season { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); font-size: var(--text-sm); }
.duel-season-select { width: auto; min-width: 16rem; margin: 0; }

/* ══════════ Défi spécial (special.js, special-admin.js — 2026-10-15) ══════════
   Écran d'arrivée par le lien /e/<id>, bilan, panneau admin. Planche :
   scratch/proto-defi-special.html (écran L1). Les lignes de classement réutilisent
   .daily-lb-row (daily.js, dailyLbRowHtml). */
.special-emblem { width: 112px; height: 112px; margin: 0 auto var(--space-3); filter: drop-shadow(0 8px 24px color-mix(in srgb, var(--bg-deep) 70%, transparent)); }
.special-emblem svg { display: block; width: 100%; height: 100%; }
.special-meta { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2) var(--space-4); margin-top: var(--space-3); color: var(--text-muted); font-size: var(--text-xs); }
.special-meta strong { color: var(--gold); font-weight: var(--weight-bold); }
.special-rules { margin: var(--space-3) 0 0; color: var(--text-muted); font-size: var(--text-xs); line-height: 1.5; text-align: center; }
.special-board { margin-top: var(--space-5); margin-bottom: var(--space-4); text-align: left; }
.special-board .daily-lb-title { text-align: center; }
.special-board-empty { margin: 0; color: var(--text-muted); font-size: var(--text-sm); text-align: center; }
.special-more { display: block; margin: var(--space-2) auto 0; padding: var(--space-1) var(--space-2); border: 0; background: none; color: var(--gold); font: inherit; font-size: var(--text-xs); letter-spacing: 1px; text-transform: uppercase; cursor: pointer; }
.special-more:hover { text-decoration: underline; }
.special-rank { margin: var(--space-4) auto 0; max-width: 420px; padding: var(--space-4); border: 1px solid color-mix(in srgb, var(--gold) 32%, transparent); border-radius: var(--radius-md); background: color-mix(in srgb, var(--gold) 6%, transparent); text-align: center; }
.special-rank-label { color: var(--text-muted); font-size: var(--text-xs); letter-spacing: 1.5px; text-transform: uppercase; }
.special-rank-value { display: block; margin: var(--space-1) 0; color: var(--gold); font-size: var(--text-2xl); font-weight: var(--weight-impact); }
.special-rank-value sup { font-size: 0.5em; }
.special-rank p { margin: 0; color: var(--text-muted); font-size: var(--text-sm); }
.special-claim { max-width: 420px; margin: var(--space-4) auto 0; padding: var(--space-3) var(--space-4); border-left: 2px solid var(--gold); background: linear-gradient(90deg, color-mix(in srgb, var(--gold) 12%, transparent), transparent); font-size: var(--text-sm); line-height: 1.5; text-align: left; }
.special-claim strong { color: var(--gold); }
.special-next { max-width: 420px; margin: var(--space-4) auto 0; padding: var(--space-4); border-radius: var(--radius-md); background: var(--surface-2); text-align: center; }
.special-next p { margin: 0 0 var(--space-3); font-size: var(--text-sm); line-height: 1.5; }
.special-next small { display: block; margin-top: var(--space-1); color: var(--text-muted); font-size: var(--text-xs); }
.special-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-top: var(--space-4); }
.special-actions--start { justify-content: flex-start; margin-top: var(--space-3); }
.special-bilan { margin-bottom: var(--space-5); }

/* Panneau admin */
/* Quatre onglets sur une ligne (.adp-tabs en pose trois). */
#spa-tabs { grid-template-columns: repeat(4, 1fr); }
#spa-tabs .adp-tab { padding-top: var(--space-2); padding-bottom: var(--space-2); }
@media (max-width: 640px) { #spa-tabs { grid-template-columns: repeat(2, 1fr); } }
.spa-context { display: flex; align-items: center; gap: var(--space-3); color: var(--text-muted); font-size: var(--text-sm); }
.spa-ctx-emblem, .spa-row-emblem { display: block; flex: 0 0 auto; width: 40px; height: 40px; }
.spa-ctx-emblem svg, .spa-row-emblem svg, .spa-emblem-preview svg { display: block; width: 100%; height: 100%; }
.spa-ctx-link { color: var(--text-main); font-family: var(--font-mono); }
.spa-chip { display: inline-block; padding: 2px var(--space-2); border-radius: var(--radius-pill); background: var(--surface-3); color: var(--text-muted); font-size: var(--text-2xs); letter-spacing: 0.8px; text-transform: uppercase; white-space: nowrap; }
.spa-chip--live { background: color-mix(in srgb, var(--gold) 18%, transparent); color: var(--gold); }
.spa-chip--closed { background: var(--surface-2); }
.spa-chip--warn { background: color-mix(in srgb, var(--wrong-soft) 18%, transparent); color: var(--wrong-soft); }
.spa-empty { margin: var(--space-6) 0; color: var(--text-muted); font-size: var(--text-sm); text-align: center; }
.spa-note { margin: 0 0 var(--space-4); color: var(--text-muted); font-size: var(--text-xs); line-height: 1.5; }
.spa-link { padding: 0; border: 0; background: none; color: var(--gold); font: inherit; text-decoration: underline; cursor: pointer; }
.spa-list { display: flex; flex-direction: column; gap: var(--space-2); }
.spa-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
.spa-row-main { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; }
.spa-row-main strong { overflow: hidden; font-size: var(--text-sm); text-overflow: ellipsis; white-space: nowrap; }
.spa-row-main small { overflow: hidden; color: var(--text-muted); font-size: var(--text-xs); text-overflow: ellipsis; white-space: nowrap; }
.spa-row-nums { flex: 0 0 auto; color: var(--text-muted); font-size: var(--text-xs); white-space: nowrap; }
.spa-row-nums b { color: var(--gold); }
.spa-row-open { flex: 0 0 auto; }
.spa-editor { display: flex; flex-direction: column; gap: var(--space-4); }
.spa-head-fields, .spa-q { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); align-items: end; }
.spa-q { margin: 0; padding: var(--space-4); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
.spa-q legend { padding: 0 var(--space-2); color: var(--gold); font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: 1.5px; text-transform: uppercase; }
.spa-field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.spa-field--wide { grid-column: 1 / -1; }
.spa-field > span { color: var(--text-muted); font-size: var(--text-xs); }
.spa-field small { color: var(--text-muted); font-size: var(--text-2xs); }
.spa-field input, .spa-field textarea, .spa-field select { width: 100%; padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-1); color: var(--text-main); font: inherit; font-size: var(--text-sm); }
.spa-field input[readonly] { opacity: 0.7; }
.spa-emblem-preview { display: block; width: 72px; height: 72px; }
.spa-scores { display: flex; flex-direction: column; gap: var(--space-1); }
.spa-score { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); }
.spa-score.is-excluded { opacity: 0.55; }
.spa-score summary { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); cursor: pointer; font-size: var(--text-sm); }
.spa-score-rank { min-width: 3em; color: var(--text-muted); }
.spa-score-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spa-score-flags { color: var(--text-muted); font-size: var(--text-xs); }
.spa-score-flags.has-flags { color: var(--wrong-soft); }
.spa-score-time { color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.spa-score-pts { color: var(--gold); font-weight: var(--weight-bold); white-space: nowrap; }
.spa-score-detail { padding: 0 var(--space-3) var(--space-3); color: var(--text-muted); font-size: var(--text-xs); }
.spa-score-detail p { margin: 0 0 var(--space-2); }
.spa-answers { margin: 0 0 var(--space-3); padding-left: var(--space-5); }
.spa-answers .is-ok { color: var(--correct-color); }
.spa-answers .is-ko { color: var(--wrong-soft); }
.spa-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
.spa-tile { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-4); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface-1); }
.spa-tile strong { color: var(--gold); font-size: var(--text-xl); }
.spa-tile span { font-size: var(--text-sm); }
.spa-tile small { color: var(--text-muted); font-size: var(--text-2xs); line-height: 1.4; }
#spa-feedback.is-err { color: var(--wrong-soft); }
#spa-feedback.is-ok { color: var(--gold); }
@media (max-width: 640px) {
    .spa-head-fields, .spa-q { grid-template-columns: 1fr; }
    .spa-row { flex-wrap: wrap; }
    .spa-row-nums { order: 3; width: 100%; white-space: normal; }
}
