/* ============================================================================
   LE LABORATOIRE · interface B, « le pupitre du professeur » · LE SOCLE
   ----------------------------------------------------------------------------
   Feuille de la page d'essai public/pupitre.html (SPECS 2.12,
   docs/interface-b/plan-de-bascule.md, étape 0). Elle NE SERT PAS à la page du
   jeu (index.html garde style.css) ni à l'admin.

   Portée du socle des maquettes (data/maquettes-2026-10-07/B-suite/commun.css),
   et branchée sur les identifiants et les classes du VRAI jeu : la page porte
   les mêmes identifiants que index.html, et app.js y écrit comme avant.

   Ce que cette feuille contient, et rien d'autre :
     - ce qui est commun à tous les écrans (thème, unité, grille, barre du haut,
       cadrans, étiquettes, bulle du professeur, composants) ;
     - un HABILLAGE DE BASE de chaque écran, pour que tout soit utilisable dès
       maintenant, même sans mise en page soignée.
   La mise en page soignée de chaque écran vit dans SA feuille, chargée après
   celle-ci : manche.css, par-dessus.css, ouverture.css, fin.css,
   hors-partie.css, tutoriel.css, partenaire.css. Une feuille d'étape ne
   retouche pas ce fichier : elle redéfinit, pour ses écrans, ce qu'elle veut.

   SOMMAIRE
     1. Police Cinzel
     2. Thème Laboratoire, et les couleurs de sens (les mêmes sous tous les thèmes)
     3. L'unité « u », les marges de sécurité, les réglages des trois rangements
     4. Base de la page, fond d'ambiance
     5. Matières : verre fumé cerclé (.verre), rivets (.rivete), verre simple
     6. La grille de page (.pupitre), ses emplacements, et qui se montre sur quel écran
     7. Barre du haut : plaque du titre (.titre), touches de verre (.commandes)
     8. Rampe de cadrans (.rail, .instruments, .cadran…)
     9. Étiquettes de verre (.etiquette…)
    10. Panneau riveté (.panneau), question (.question), touches de réponse (.reponse)
    11. Professeur et bulle (.professeur, .bulle)
    12. Composants : textes, titres, boutons, champs, case, onglets, listes,
        tuiles, bandeaux, voile, pastilles, barre de votes, compte à rebours,
        couleurs des rangs, rayons, pied
    13. Habillage de base des écrans, un par un
    14. Fenêtres, message bref, pavé de développement, anciens éléments non montrés
    15. Replis pour les navigateurs anciens
    16. Mouvements réduits

   LES TROIS RANGEMENTS (les mêmes conditions partout, à recopier telles quelles)
     téléphone debout : la base, sans condition (toute fenêtre étroite ou debout)
     téléphone couché : @media (orientation: landscape) and (max-height: 560px)
     ordinateur       : @media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px)

   CE QUE LA PAGE DIT À LA FEUILLE (posé par pupitre/pupitre.js)
     body[data-ecran="jeu"]       l'écran affiché : auth, salon, regles, roue, tuto, sponsor,
                                  annonce, jeu, resultats, fin, lot, profil, stats
     body[data-moment="partie"]   partie (regles, roue, tuto, sponsor, annonce, jeu, resultats),
                                  fin (fin, lot), hors (auth, salon, profil, stats)
     body.sans-compte             personne n'est connecté
     .pupitre.sans-lot            aucun jeu du soir à afficher

   « ÇA SE TOUCHE » ET « C'EST UNE INFORMATION » : DEUX LANGAGES, PARTOUT LES MÊMES
   (consigne de Gautier du 2026-10-08, section 5 bis ; gardé par
   test/pupitre-cliquable.test.js)
     - ce qui se touche est une TOUCHE : elle tient debout sur un PIED de laiton
       (une tranche nette sous elle, var(--socle-laiton) ou var(--socle-verre)),
       elle se soulève sous la souris, S'ENFONCE sous le doigt (le pied
       s'écrase : --pied), porte l'anneau du clavier (var(--anneau-clavier)) et
       le curseur en main ; 44 px au moins sur téléphone. Un lien dans une
       phrase est souligné ;
     - une information est en VERRE, à plat ou gravée en creux : jamais de pied,
       jamais de curseur en main. Les titres de section sont des plaques gravées
       en creux (var(--plaque-fond)), pas des plaques de laiton en relief.

   RÈGLES D'ÉCRITURE (gardées par test/pupitre-feuilles.test.js)
     - tout se mesure en « u » : calc(12 * var(--u)) ; plancher permis pour ce qui se lit ;
     - aucune couleur de thème en dur : var(--accent), rgba(var(--accent-rvb), 0.4) ;
     - pas de color-mix(), pas de :has(), pas de « inset: », pas de dvh hors de @supports.
   ========================================================================== */


/* ============================================================================
   1. POLICE CINZEL, auto-hébergée (les mêmes fichiers que public/polices/)
   ========================================================================== */
@font-face { font-family: 'Cinzel'; font-style: normal; font-weight: 600 900; font-display: swap;
  src: url('cinzel-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Cinzel'; font-style: normal; font-weight: 600 900; font-display: swap;
  src: url('cinzel-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* LA POLICE DU TEXTE (2026-10-16, Gautier : « changer la police de texte car celle-ci ne tape pas à l'œil et est
   trop fade »). Le texte (réponses, boutons de verre, phrases) était la police du système. Trois polices libres
   (SIL Open Font License, licence à côté des fichiers), auto-hébergées dans public/polices/, sous-ensemble latin
   (outils/alleger-les-polices.py, SPECS 2.12) ; une seule est montrée : celle que nomme --police-texte
   (section 3). Un navigateur ne télécharge que la police qu'il affiche : les deux autres ne coûtent rien.
   Les titres et le bouton principal restent en Cinzel. */
@font-face { font-family: 'Outfit'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('../polices/outfit-latin.woff2') format('woff2'); }
@font-face { font-family: 'Exo 2'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('../polices/exo2-latin.woff2') format('woff2'); }
@font-face { font-family: 'Alegreya Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../polices/alegreya-sans-400-latin.woff2') format('woff2'); }
@font-face { font-family: 'Alegreya Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../polices/alegreya-sans-500-latin.woff2') format('woff2'); }
@font-face { font-family: 'Alegreya Sans'; font-style: normal; font-weight: 600 700; font-display: swap;
  src: url('../polices/alegreya-sans-700-latin.woff2') format('woff2'); }
@font-face { font-family: 'Alegreya Sans'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('../polices/alegreya-sans-800-latin.woff2') format('woff2'); }


/* ============================================================================
   2. THÈME, ET COULEURS DE SENS
   ----------------------------------------------------------------------------
   UN THÈME = un fond, un accent, un métal, un verre, un texte. Un
   seul thème pour l'instant (Laboratoire) ; les autres viendront à l'étape 8,
   chacun dans un bloc [data-theme="…"] comme celui-ci.
     --accent…      la couleur qui luit (chrono, choix, titres)
     --metal…       le cerclage et les pièces de laiton, du plus clair au plus sombre
     --sur-accent, --sur-metal : le texte posé SUR ces couleurs
     --verre-haut, --verre-bas, --verre-milieu : le verre fumé (trois nombres,
                    pour rgba(var(--verre-haut), 0.8))
     --texte, --texte-doux : le texte courant et le texte secondaire
   Les variables « …-rvb » portent la même couleur en trois nombres, pour la
   rendre transparente sans color-mix() : rgba(var(--accent-rvb), 0.4).
     --fond-haut, --fond-milieu, --fond-bas : le fond d'ambiance, du haut de la
                    page au bas (aucune image : section 4)
     --fond-lueur : la lueur posée derrière la scène (trois nombres)
   ========================================================================== */
:root, [data-theme="laboratoire"] {
  --fond-haut: #141925; --fond-milieu: #0a0c12; --fond-bas: #040508;
  --fond-lueur: 255, 181, 69;
  --accent: #ffb545; --accent-rvb: 255, 181, 69;
  --accent-vif: #ffe0a3; --accent-sombre: #c9731f; --sur-accent: #2a1704;
  --metal-vif: #f0dca8; --metal-vif-rvb: 240, 220, 168;
  --metal-clair: #d8b877; --metal-clair-rvb: 216, 184, 119;
  --metal-sombre: #a07b3a; --metal-creux: #8d6a30; --metal-pied: #5e431c;
  --sur-metal: #261705;
  --verre-haut: 26, 31, 44; --verre-bas: 9, 11, 17; --verre-milieu: 18, 21, 31;
  --texte: #eef0f5; --texte-doux: #a9b0c0; --texte-doux-rvb: 169, 176, 192;
}

/* LES COULEURS DE SENS : les mêmes sous TOUS les thèmes (plan de bascule,
   décision 4). Un joueur qui a appris que le vert veut dire « bon » ne le
   réapprend pas un soir d'octobre. Un thème ne les redéfinit jamais.
     --ok       « qualifié », « il fallait répondre » (réservé à cela)
     --alerte   le danger : urgence, vie perdue, élimination, panne
     --vie      les cœurs
     --moi      « ta réponse »
   Les quatre métaux des rangs de la roue sont plus bas (section 12). */
:root {
  --ok: #3ecf7a; --ok-rvb: 62, 207, 122; --ok-vif: #b9f5d0; --ok-sombre: #227243; --sur-ok: #06210f;
  --alerte: #ff5d6c; --alerte-rvb: 255, 93, 108; --alerte-claire: #ff7a86; --sur-alerte: #2a0607;
  --vie: #ff5d6c; --vie-rvb: 255, 93, 108; --vie-eteinte: #984f56;
  --moi: #5aa9ff; --moi-rvb: 90, 169, 255; --moi-vif: #a8d3ff; --sur-moi: #04162b;
  /* Les deux noms que app.js emploie lui-même (fond du message bref) */
  --erreur: var(--alerte);
  --info: var(--moi);
}


/* ============================================================================
   3. L'UNITÉ « u », LES MARGES DE SÉCURITÉ, LES RÉGLAGES DES TROIS RANGEMENTS
   ----------------------------------------------------------------------------
   Tout se dimensionne en « u » : calc(12 * var(--u)). Un u vaut 1 px sur un
   téléphone de 375 px de large ou sur un ordinateur de 1280 x 726, et grandit
   avec la fenêtre. Aucun élément n'est posé au pixel : la grille range les
   blocs, et l'unité garantit que l'ensemble tient dans la hauteur, sans défiler.

   --hauteur-ecran : la hauteur RÉELLE de la fenêtre. 100dvh quand le navigateur
   le connaît ; sinon pupitre.js la mesure et la pose ici (sur téléphone, 100vh
   compte la barre d'adresse : le bas de la page passerait dessous).
   --sur-haut, --sur-bas, --sur-gauche, --sur-droite : les marges de sécurité
   d'un téléphone à encoche (0 ailleurs). La grille les réserve.

   Les réglages ci-dessous changent d'un rangement à l'autre. Une feuille
   d'étape s'en sert (font-size: var(--taille-texte)) et peut en redéfinir un
   POUR SES ÉCRANS, sur l'écran lui-même (#ecran-jeu { --hauteur-touche: … }) ou,
   pour une pièce hors de l'écran, sous body[data-ecran="…"] : la valeur vaut
   alors pour tout ce que l'écran contient. JAMAIS sur :root dans une feuille
   d'étape : elle changerait aussi sur les écrans des autres étapes, sans que
   rien le dise (test/pupitre-feuilles.test.js le refuse). Deux précisions :
   un réglage calculé ici à partir d'un autre (--ecart, à partir de --u) ne suit
   pas une redéfinition de celui-ci plus bas dans la page ; et un réglage
   redéfini sur un écran l'emporte sur les trois rangements, sauf à l'écrire
   lui aussi dans les mêmes conditions @media.
   ========================================================================== */
:root {
  --police-plateau: 'Cinzel', Georgia, 'Times New Roman', serif;
  /* LA POLICE DU TEXTE : une ligne à changer pour poser l'une des trois (section 1) : 'Outfit', 'Exo 2' ou
     'Alegreya Sans' ; la police du système reste derrière, le temps qu'elle arrive */
  --police-texte: 'Exo 2', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --hauteur-ecran: 100vh;
  --sur-haut: 0px; --sur-bas: 0px; --sur-gauche: 0px; --sur-droite: 0px;
  --hauteur-utile: calc(var(--hauteur-ecran) - var(--sur-haut) - var(--sur-bas));
  --largeur-utile: calc(100vw - var(--sur-gauche) - var(--sur-droite));

  /* ---------- téléphone debout (la base) ---------- */
  --u: min(calc(var(--largeur-utile) / 375), calc(var(--hauteur-utile) / 732));
  --ecart: calc(8 * var(--u));                     /* entre deux rangées de la grille */
  --ecart-colonnes: calc(12 * var(--u));           /* entre deux colonnes de la grille */
  --marge-page: calc(12 * var(--u));               /* marge de la page, à gauche et à droite */
  --marge-panneau: calc(18 * var(--u)) calc(26 * var(--u));
  --taille-question: calc(24 * var(--u));
  --taille-reponse: max(16px, calc(17.5 * var(--u)));
  --hauteur-touche: calc(56 * var(--u));
  --pastille-touche: calc(36 * var(--u));
  --ecart-touches: calc(9 * var(--u));
  /* La bulle du professeur : hauteur FIXE, en lignes (--bulle-lignes). Une
     réplique plus longue passe en pages (pupitre.js, decouperEnPages) : la bulle
     ne grandit jamais, la scène ne « saute » pas pendant qu'il parle. */
  --taille-bulle: max(16px, calc(16 * var(--u)));
  --interligne-bulle: 1.36;
  --bulle-lignes: 4;
  --bulle-haut: calc(13 * var(--u)); --bulle-cote: calc(14 * var(--u)); --bulle-bas: calc(10 * var(--u));
  --largeur-professeur: calc(88 * var(--u));
  --etoile: calc(13 * var(--u));
  --taille-texte: max(16px, calc(16 * var(--u)));  /* tout ce qui se lit : 16 px au moins sur téléphone */
  --taille-note: max(16px, calc(16 * var(--u)));   /* texte secondaire : même taille, couleur plus douce */
  --taille-etiquette: max(9.5px, calc(10.5 * var(--u)));  /* petites capitales qui nomment une case */
  --taille-surtitre: max(10px, calc(11.5 * var(--u)));
  --taille-plaque: max(11px, calc(13 * var(--u)));
  --taille-pastille: max(10px, calc(11 * var(--u)));
  --taille-titre: calc(30 * var(--u));             /* grand titre d'un écran */
  --taille-bouton: max(16px, calc(16 * var(--u)));
  --hauteur-bouton: max(44px, calc(48 * var(--u)));  /* zone à toucher : 44 px au moins */
  --taille-rebours: calc(76 * var(--u));           /* compte à rebours géant */
  /* La hauteur d'une case de la roue, en pixels ENTIERS : app.js la relit pour
     arrêter la bande pile sur la case tirée (pupitre.js la tient à jour) */
  --roue-case: 64px;
}
@supports (height: 100dvh) {
  :root { --hauteur-ecran: 100dvh; }
}
@supports (padding: env(safe-area-inset-top)) {
  :root {
    --sur-haut: env(safe-area-inset-top, 0px); --sur-bas: env(safe-area-inset-bottom, 0px);
    --sur-gauche: env(safe-area-inset-left, 0px); --sur-droite: env(safe-area-inset-right, 0px);
  }
}

/* ---------- téléphone couché ---------- */
@media (orientation: landscape) and (max-height: 560px) {
  :root {
    --u: min(calc(var(--largeur-utile) / 812), calc(var(--hauteur-utile) / 345));
    --ecart: calc(6 * var(--u));
    --taille-question: calc(21 * var(--u));
    --taille-reponse: calc(14.5 * var(--u));
    --hauteur-touche: calc(44 * var(--u));
    --pastille-touche: calc(27 * var(--u));
    --ecart-touches: calc(7 * var(--u));
    --bulle-lignes: 2;
    --largeur-professeur: calc(74 * var(--u));
    --taille-titre: calc(24 * var(--u));
    --hauteur-bouton: max(44px, calc(44 * var(--u)));
    --taille-rebours: calc(52 * var(--u));
  }
}

/* ---------- ordinateur ---------- */
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  :root {
    --u: min(calc(var(--largeur-utile) / 1280), calc(var(--hauteur-utile) / 726));
    --ecart: calc(14 * var(--u));
    --ecart-colonnes: calc(14 * var(--u));
    --marge-page: calc(16 * var(--u));
    --col-etiquette: calc(248 * var(--u));         /* largeur d'une étiquette de la rampe (236 avant le 2026-10-16 : les cadrans ont rétréci) */
    /* (2026-10-16, Gautier : « réduire l'interface haute qui donne les chrono, les vies, etc. pour gagner de la
       place » : 112 et 148 avant ; la place gagnée va à la question et aux réponses) */
    --col-cadran: calc(90 * var(--u));             /* diamètre d'un petit cadran */
    --col-chrono: calc(120 * var(--u));            /* diamètre du grand cadran */
    --marge-panneau: calc(22 * var(--u)) calc(56 * var(--u));
    --taille-question: calc(42 * var(--u));
    --taille-reponse: calc(24 * var(--u));
    --hauteur-touche: calc(84 * var(--u));
    --pastille-touche: calc(48 * var(--u));
    --ecart-touches: calc(14 * var(--u));
    --taille-bulle: max(13px, calc(18 * var(--u)));
    --bulle-lignes: 2;
    --bulle-haut: calc(18 * var(--u)); --bulle-cote: calc(24 * var(--u)); --bulle-bas: calc(14 * var(--u));
    --largeur-professeur: calc(184 * var(--u));
    --etoile: calc(19 * var(--u));
    --taille-texte: max(14px, calc(18 * var(--u)));
    --taille-note: max(12.5px, calc(15 * var(--u)));
    --taille-etiquette: max(9.5px, calc(11.5 * var(--u)));
    --taille-surtitre: max(10px, calc(13 * var(--u)));
    --taille-plaque: max(11px, calc(15 * var(--u)));
    --taille-pastille: max(10px, calc(12.5 * var(--u)));
    --taille-titre: calc(52 * var(--u));
    --taille-bouton: max(13px, calc(18 * var(--u)));
    --hauteur-bouton: calc(54 * var(--u));
    --taille-rebours: calc(120 * var(--u));
  }
}


/* ============================================================================
   4. BASE DE LA PAGE, FOND D'AMBIANCE
   ========================================================================== */
* { box-sizing: border-box; }
[hidden] { display: none !important; }            /* l'attribut hidden gagne toujours */
html, body { height: 100%; margin: 0; }
body {
  overflow: hidden;                               /* la page ne défile jamais : tout tient */
  background: #07080c;
  color: var(--texte);
  font-family: var(--police-texte);
  font-size: var(--taille-texte);
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
}
:where(button, input, select, textarea) { font: inherit; color: inherit; }
h1, h2, h3, p, ul, ol { margin: 0; }
.pictos { position: absolute; }
.non-selectionnable { user-select: none; -webkit-user-select: none; }

/* .fond : le fond d'ambiance. AUCUNE IMAGE (décision de Gautier du
   2026-10-15 : « supprimer l'image du laboratoire avec les machines en fond,
   pour faire une interface plus moderne ») : un noir bleuté qui s'assombrit
   vers le bas et vers les bords, et une lueur de laiton très douce derrière la
   scène, là où se tient le héros de chaque écran. Rien n'y bouge, rien n'y
   attire l'œil : le pupitre (verre, laiton) se détache sur un fond calme.
   Deux autres fonds ont été essayés et écartés (captures dans
   data/captures-2026-10-15/E/) : une trame de carnet de laboratoire, plus
   chargée ; un projecteur venu du haut, qui tirait l'œil vers la barre du
   haut plutôt que vers la scène. */
/* FOND:DEBUT */
.fond {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 0;
  background:
    radial-gradient(ellipse 58% 46% at 50% 46%, rgba(var(--fond-lueur), 0.075), rgba(var(--fond-lueur), 0) 72%),
    linear-gradient(180deg, var(--fond-haut) 0%, var(--fond-milieu) 52%, var(--fond-bas) 100%);
  background-color: var(--fond-bas);
}
/* les bords s'assombrissent : le regard revient au centre */
.fond::after {
  content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: radial-gradient(ellipse 85% 80% at 50% 48%, rgba(2, 3, 5, 0) 55%, rgba(2, 3, 5, 0.6) 100%);
}
/* FOND:FIN */


/* ============================================================================
   5. MATIÈRES
   ----------------------------------------------------------------------------
   .verre : le verre fumé cerclé de métal. Son cerclage est un pseudo-élément
   découpé en anneau : il ne convient PAS à une pièce qui défile à l'intérieur
   (l'anneau défilerait avec le contenu). Pour une pièce qui défile : le
   « verre simple » (variables --verre-fond et --verre-anneau), un filet de
   métal posé en ombre intérieure, qui ne bouge pas.

   Donner le verre cerclé à une pièce fabriquée par app.js (qui n'a pas la
   classe .verre) : recopier dans SA feuille les deux règles ci-dessous sur son
   sélecteur, comme .reponse le fait en section 10.
   ========================================================================== */
:root {
  --verre-opaque-haut: 0.8; --verre-opaque-bas: 0.9;
  --verre-fond:
    linear-gradient(118deg, rgba(255, 255, 255, 0.085) 0%, rgba(255, 255, 255, 0) 24%),
    linear-gradient(180deg, rgba(var(--verre-haut), var(--verre-opaque-haut)), rgba(var(--verre-bas), var(--verre-opaque-bas)));
  --verre-flou: blur(9px) saturate(1.25);
  --verre-ombre:
    0 0 0 1px rgba(0, 0, 0, 0.75),
    0 calc(12 * var(--u)) calc(34 * var(--u)) rgba(0, 0, 0, 0.55),
    inset 0 0 calc(30 * var(--u)) rgba(0, 0, 0, 0.42);
  /* le filet du verre simple : métal, puis un liseré sombre */
  --verre-anneau:
    inset 0 0 0 max(1.5px, calc(2 * var(--u))) var(--metal-sombre),
    inset 0 0 0 max(2.5px, calc(3 * var(--u))) rgba(0, 0, 0, 0.55);
  --cerclage-metal: linear-gradient(152deg,
    var(--metal-vif) 0%, var(--metal-clair) 14%, var(--metal-creux) 42%,
    var(--metal-pied) 58%, var(--metal-sombre) 80%, var(--metal-vif) 100%);
  --laiton: linear-gradient(170deg, var(--metal-vif) 0%, var(--metal-clair) 34%, var(--metal-sombre) 78%, var(--metal-creux) 100%);
}

/* .verre : la matière de tous les panneaux (réglages : --rayon, --cerclage) */
.verre, .reponse {
  position: relative;
  border-radius: var(--rayon, calc(16 * var(--u)));
  background: var(--verre-fond);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  box-shadow: var(--verre-ombre);
}
/* le cerclage : un dégradé de métal, découpé en anneau */
.verre::before, .reponse::before {
  content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; border-radius: inherit; pointer-events: none;
  padding: var(--cerclage, max(1.5px, calc(2 * var(--u))));
  background: var(--cerclage-metal);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
/* .rivete : quatre rivets aux coins d'un grand panneau de verre (à poser avec .verre) */
.rivete::after {
  content: ''; position: absolute; top: calc(8 * var(--u)); right: calc(8 * var(--u)); bottom: calc(8 * var(--u)); left: calc(8 * var(--u));
  pointer-events: none;
  --rivet: radial-gradient(circle at 38% 34%, var(--metal-vif) 0 16%, var(--metal-clair) 32%, var(--metal-creux) 60%, rgba(0, 0, 0, 0.85) 70%, transparent 74%);
  background: var(--rivet) left top, var(--rivet) right top, var(--rivet) left bottom, var(--rivet) right bottom;
  background-size: calc(8 * var(--u)) calc(8 * var(--u)); background-repeat: no-repeat;
  opacity: 0.9;
}


/* ============================================================================
   5 bis. « ÇA SE TOUCHE » : LE PIED, LA COURSE, L'ANNEAU DU CLAVIER
   ----------------------------------------------------------------------------
   Consigne de Gautier du 2026-10-08 : « si tu intègres des éléments cliquables,
   le joueur sache bien que c'est cliquable ». Sept feuilles avaient chacune
   leur idée d'un bouton ; le verre d'un bouton secondaire était celui d'une
   plaque d'information, à un liseré noir près, invisible sur le fond.
   UN SEUL LANGAGE, écrit ici, que toutes les feuilles citent :
     LA TOUCHE tient debout sur un PIED : une tranche nette sous elle, sans
       flou, en laiton sombre sous une touche de laiton (--socle-laiton), en
       laiton sous une touche de verre (--socle-verre). C'est le pied qui dit
       « ça se touche » : aucune information n'en a.
     SOUS LA SOURIS elle se soulève. SOUS LE DOIGT elle S'ENFONCE : elle descend
       de sa course (--course) et son pied s'écrase (--pied), le bas de la
       touche ne bouge pas. Une touche éteinte (disabled) perd son pied.
     AU CLAVIER, le même anneau partout : var(--anneau-clavier).
     Le curseur est une main sur tout ce qui répond, une flèche ailleurs.
   L'INFORMATION est en verre, à plat ou GRAVÉE EN CREUX (--plaque-fond,
   --plaque-ombre) : les titres de section (« Classement », « Activer ton
   compte »…) étaient des plaques de laiton en relief, du même métal que les
   boutons ; l'une d'elles se lisait juste au-dessus du bouton du même nom.
   Gardé par test/pupitre-cliquable.test.js ; relevé dans un vrai navigateur
   par « npm run pupitre:mesurer -- --inventaire ».
   ========================================================================== */
:root {
  --anneau-clavier: 2px solid var(--accent-vif);
  /* la plaque gravée en creux d'un titre de section : une information */
  --plaque-fond: linear-gradient(180deg, rgba(0, 0, 0, 0.66), rgba(var(--verre-bas), 0.74));
  --plaque-ombre: inset 0 calc(2 * var(--u)) calc(4 * var(--u)) rgba(0, 0, 0, 0.85), 0 0 0 max(1px, calc(1.2 * var(--u))) var(--metal-sombre);
  --plaque-encre: var(--metal-vif);
  /* LA MATIÈRE D'UNE TOUCHE (2026-10-16, Gautier : « tous les boutons ne sont pas jolis, ils sont fades (par
     exemple le bouton Apprendre à jouer) »). Le laiton était un dégradé terne, le verre celui d'une plaque
     d'information : rien n'appelait le doigt. Une touche a maintenant LA LUMIÈRE d'une pièce polie : un reflet
     franc sur sa moitié haute (la ligne nette du reflet, à mi-hauteur, fait le bombé), un laiton qui va du
     clair à l'ambre (l'accent du thème), une lueur à l'accent autour d'elle, plus forte sous la souris. Le
     verre d'une touche a le même reflet, une lueur d'ambre venue du haut, et un filet de laiton clair qui
     s'allume à l'accent sous la souris. Une plaque d'information n'a rien de tout cela (section 5 bis). */
  --laiton-touche:
    linear-gradient(180deg, rgba(255, 255, 255, 0.52) 0%, rgba(255, 255, 255, 0.18) 44%, rgba(255, 255, 255, 0) 50%),
    linear-gradient(180deg, var(--metal-vif) 0%, var(--accent-vif) 18%, var(--accent) 60%, var(--accent-sombre) 100%);
  --verre-touche:
    linear-gradient(180deg, rgba(255, 255, 255, 0.13) 0%, rgba(255, 255, 255, 0.035) 46%, rgba(255, 255, 255, 0) 50%),
    radial-gradient(120% 85% at 50% 0%, rgba(var(--accent-rvb), 0.13), rgba(var(--accent-rvb), 0) 72%),
    linear-gradient(180deg, rgba(var(--verre-haut), 0.94), rgba(var(--verre-bas), 0.97));
  --plaque-rivets:
    radial-gradient(circle at calc(8 * var(--u)) 50%, var(--metal-clair) 0 calc(1.4 * var(--u)), transparent calc(2 * var(--u))),
    radial-gradient(circle at calc(100% - 8 * var(--u)) 50%, var(--metal-clair) 0 calc(1.4 * var(--u)), transparent calc(2 * var(--u)));
}
/* Le pied se règle SUR la touche elle-même : une variable qui en cite une autre
   est calculée là où elle est écrite (posées sur :root, les ombres ne
   suivraient pas le pied qui s'écrase). :where() : ces règles ne pèsent rien,
   n'importe quelle feuille change la hauteur du pied ou sa teinte pour SA pièce. */
.bouton, :where(.pupitre, dialog) :where(button, summary, a, label) {
  --pied: calc(4 * var(--u));
  --course: calc(3 * var(--u));
  --socle-teinte: var(--metal-sombre);
  --socle-laiton: 0 var(--pied) 0 0 var(--metal-pied), 0 var(--pied) 0 max(1px, calc(1.5 * var(--u))) rgba(14, 8, 2, 0.92);
  --socle-verre: 0 var(--pied) 0 0 var(--socle-teinte), 0 var(--pied) 0 1px rgba(0, 0, 0, 0.85);
  /* la lumière d'une touche (voir --laiton-touche) : sa lueur, et le filet d'une touche de verre ; la
     souris les allume (sous elle, la lueur monte et le filet passe à l'accent) */
  --lueur-laiton: 0.26;
  --lueur-verre: 0.08;
  --filet-touche: var(--metal-clair);
  --ombre-laiton:
    0 0 0 max(1px, calc(1.5 * var(--u))) rgba(14, 8, 2, 0.92),
    var(--socle-laiton),
    0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), var(--lueur-laiton)),
    0 calc(12 * var(--u)) calc(20 * var(--u)) rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 0 0 1px rgba(255, 236, 190, 0.28),
    inset 0 calc(-3 * var(--u)) calc(5 * var(--u)) rgba(70, 30, 0, 0.3);
  --ombre-verre:
    inset 0 0 0 max(1.2px, calc(1.6 * var(--u))) var(--filet-touche),
    inset 0 max(2px, calc(2.6 * var(--u))) 0 max(1.2px, calc(1.6 * var(--u))) rgba(255, 255, 255, 0.07),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre),
    0 0 calc(18 * var(--u)) rgba(var(--accent-rvb), var(--lueur-verre)),
    0 calc(12 * var(--u)) calc(20 * var(--u)) rgba(0, 0, 0, 0.45);
}
/* une touche éteinte ne se touche plus : son pied redevient une ombre */
:where(.pupitre, dialog) :where(button:disabled) { --socle-teinte: rgba(3, 4, 7, 0.95); }
/* le curseur : une main sur tout ce qui répond à un clic, et sur rien d'autre */
:where(.pupitre, dialog) :where(button, summary, a[href], select, input[type="checkbox"], label.case, label.lot-majeur) { cursor: pointer; }
:where(.pupitre, dialog) :where(button:disabled, input:disabled) { cursor: default; }
/* l'anneau du clavier : le même partout (une feuille n'en change que l'écart). Un champ de saisie ou une
   liste déroulante montre qu'il a la main autrement : son cerclage s'allume à l'accent (section 12). */
:where(.pupitre, dialog) :where(button, summary, a, input[type="checkbox"]):focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }


/* ============================================================================
   6. LA GRILLE DE PAGE ET SES EMPLACEMENTS
   ----------------------------------------------------------------------------
   <main class="pupitre"> porte toute la page. Ses enfants directs sont les
   EMPLACEMENTS, toujours dans cet ordre dans la page :

     .rampe-haute        barre du haut : la plaque du titre et les quatre boutons
     .bandeaux           bandeaux d'information (réseau, version, démonstration)
     .rail, .instruments la rampe de cadrans (vies, chrono, joueurs en lice)
     .etiquette-gauche   étiquette de verre (sur téléphone : fine bande au-dessus de la scène)
     .scene              LA ZONE PRINCIPALE : les treize écrans (section#ecran-…),
                         un seul montré à la fois ; elle prend la place qui reste
     .etiquette-droite   étiquette de verre (sur téléphone : fine bande sous la scène)
     .pied               liens légaux (hors partie seulement)
     .rampe-basse        le professeur et sa bulle
     .voile-pupitre      voile et sa carte centrale (pause, « partie suivie ailleurs »)

   Un emplacement caché (attribut hidden, ou display: none) referme sa rangée :
   la scène récupère la place. L'écart entre rangées est une MARGE posée sur
   chaque emplacement, pas un « gap » de la grille : ne la remets pas à zéro, et
   n'écris pas la propriété abrégée « margin » sur un emplacement.
   ========================================================================== */
.pupitre {
  position: relative; z-index: 1;
  height: var(--hauteur-ecran);
  display: grid; margin: 0 auto;
  /* ---------- téléphone debout : tout en une colonne ---------- */
  width: min(100vw, calc(430 * var(--u) + var(--sur-gauche) + var(--sur-droite)));
  padding: calc(8 * var(--u) + var(--sur-haut)) calc(var(--marge-page) + var(--sur-droite)) var(--sur-bas) calc(var(--marge-page) + var(--sur-gauche));
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto auto minmax(0, 1fr) auto auto auto;
  grid-template-areas: "haut" "bandeaux" "instruments" "eg" "scene" "ed" "pied" "bas";
}
/* LE PROFESSEUR ET SA BULLE REMONTENT (2026-10-16, Gautier : « je trouve la mascotte et sa ligne de texte trop
   basses dans l'interface ») : la page garde une marge en bas, le professeur ne s'appuie plus sur le bord de
   l'écran. Sur téléphone, 14 u (la bande du professeur et sa bulle) ; sur ordinateur, 34 u. */
.pupitre { padding-bottom: calc(14 * var(--u) + var(--sur-bas)); }

/* l'écart entre rangées : une marge en tête de chaque emplacement (sauf la barre du haut) */
.bandeaux, .rail, .instruments, .etiquette-gauche, .scene, .etiquette-droite, .pied, .rampe-basse { margin-top: var(--ecart); }

/* .rampe-haute : la barre du haut (plaque du titre à gauche, boutons à droite) */
.rampe-haute { grid-area: haut; display: flex; align-items: center; justify-content: space-between; gap: calc(8 * var(--u)); min-width: 0; }
/* .bandeaux : l'emplacement des bandeaux d'information, sous la barre du haut */
.bandeaux { grid-area: bandeaux; display: flex; flex-direction: column; gap: calc(6 * var(--u)); min-width: 0; z-index: 3; }
/* .instruments : la rangée des cadrans, montés sur le .rail */
.instruments { position: relative; grid-area: instruments; display: flex; align-items: center; justify-content: center; gap: calc(20 * var(--u)); }
/* .scene : la zone principale ; une colonne souple, l'écran y pose ce qu'il veut.
   Habillage de base (section 13) : un panneau de verre simple, qui défile à
   l'intérieur si son contenu est trop haut. La page, elle, ne défile jamais. */
.scene { grid-area: scene; display: flex; flex-direction: column; gap: var(--ecart); min-width: 0; min-height: 0; }
/* .scene-a s'étire (elle prend la hauteur qui reste), .scene-b garde sa hauteur */
.scene-a { flex: 1 1 0; min-height: 0; min-width: 0; }
.scene-b { flex: none; min-width: 0; }
/* .rampe-basse : le professeur à gauche, sa bulle à droite */
.rampe-basse { grid-area: bas; display: flex; align-items: flex-end; gap: calc(4 * var(--u)); min-width: 0; padding-top: calc(5 * var(--u)); }
/* .voile-pupitre : il couvre tout ce qui est sous la barre du haut et les bandeaux (voir section 12) */
.voile-pupitre {
  grid-row: 3 / -1; grid-column: 1 / -1;
  top: calc(4 * var(--u)); right: calc(-1 * var(--marge-page)); bottom: 0; left: calc(-1 * var(--marge-page));
}

/* ---------- téléphone couché : deux colonnes ---------- */
@media (orientation: landscape) and (max-height: 560px) {
  .pupitre {
    width: min(100vw, calc(900 * var(--u) + var(--sur-gauche) + var(--sur-droite)));
    padding-top: calc(6 * var(--u) + var(--sur-haut));
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr) auto;
    grid-template-areas: "haut instruments" "bandeaux bandeaux" "eg ed" "scene scene" "bas pied";
    column-gap: var(--ecart-colonnes);
  }
  .rampe-haute { align-self: center; }
  .rail, .instruments { margin-top: 0; }
  .pied { align-self: end; }
  .voile-pupitre { grid-row: 2 / -1; top: calc(3 * var(--u)); }
}

/* ---------- ordinateur : une colonne centrale, le professeur à gauche, les boutons à droite ---------- */
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .pupitre {
    width: 100%;
    padding-top: calc(14 * var(--u) + var(--sur-haut));
    padding-bottom: calc(34 * var(--u) + var(--sur-bas));
    grid-template-columns:
      minmax(0, 1fr) var(--col-etiquette) var(--col-cadran) var(--col-chrono) var(--col-cadran) var(--col-etiquette) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr) auto;
    grid-template-areas:
      "bandeaux titre titre titre titre titre cmd"
      "bandeaux eg    cg    cc    cd    ed    cmd"
      "prof     scene scene scene scene scene cmd"
      "prof     bulle bulle bulle bulle bulle pied";
    column-gap: var(--ecart-colonnes);
  }
  /* les rampes ne sont plus des boîtes : leurs pièces rejoignent la grille */
  .rampe-haute, .instruments, .rampe-basse { display: contents; }
  /* dans le coin en haut à gauche ; hauteur nulle pour qu'une pile de bandeaux ne pousse pas la rampe vers le bas */
  .bandeaux { margin-top: 0; align-self: start; height: 0; }
  .pied { margin-top: 0; align-self: end; }
  .voile-pupitre {
    grid-area: 2 / 2 / -1 / 7;
    top: calc(6 * var(--u)); right: calc(-6 * var(--u)); bottom: calc(6 * var(--u)); left: calc(-6 * var(--u));
  }
}

/* ---------- QUI SE MONTRE SUR QUEL ÉCRAN ----------
   La rampe de cadrans et les deux étiquettes : pendant la partie seulement.
   Les liens légaux : hors partie seulement (et avant le premier écran).
   Le professeur et sa bulle : partout. Une feuille d'étape peut en décider
   autrement pour ses écrans (body[data-ecran="…"] .rail { … }). */
body:not([data-moment="partie"]) .rail,
body:not([data-moment="partie"]) .instruments,
body:not([data-moment="partie"]) .pupitre > .etiquette { display: none; }
body[data-moment="partie"] .pied,
body[data-moment="fin"] .pied { display: none; }


/* ============================================================================
   7. BARRE DU HAUT
   ========================================================================== */

/* .titre : la plaque du titre (avec .verre) ; dedans le nom du jeu et le pseudo */
.titre {
  display: inline-flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: calc(2 * var(--u));
  height: calc(38 * var(--u)); padding: 0 calc(13 * var(--u)); min-width: 0;
  --rayon: 999px;
  white-space: nowrap; line-height: 1;
  font-family: var(--police-plateau); font-weight: 900; letter-spacing: 0.07em; text-transform: uppercase;
  font-size: max(10.5px, calc(12 * var(--u)));
}
.titre h1 { font: inherit; letter-spacing: inherit; }
.titre .accent { color: var(--accent); }
/* #menu-compte : le conteneur du pseudo (app.js le montre une fois connecté).
   Les trois anciens boutons qu'il porte ne sont plus montrés (section 14). */
#menu-compte { display: contents; }
/* .titre-pseudo : le pseudo du joueur (ordinateur seulement, la place manque sur téléphone) */
.titre-pseudo { display: none; font-weight: 700; font-size: 0.88em; color: var(--metal-vif); }

@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .titre {
    grid-area: titre; justify-self: center;
    flex-direction: row; align-items: center; gap: calc(12 * var(--u));
    height: calc(42 * var(--u)); padding: 0 calc(20 * var(--u));
    font-size: max(11px, calc(16 * var(--u))); letter-spacing: 0.09em;
  }
  .titre-pseudo {
    display: inline;
    padding-left: calc(12 * var(--u));
    border-left: 1px solid rgba(var(--metal-clair-rvb), 0.5);
    letter-spacing: inherit;
  }
  .titre-pseudo:empty { display: none; }
}

/* BOUTONS:DEBUT ---------------------------------------------------------------
   Les quatre boutons du haut (profil, menu, son, quitter) : « TOUCHES DE VERRE »
   (proposition C du 2026-10-15, livrée). Gautier : « faire des nouveaux boutons
   qui se mêlent mieux au nouveau design ». Les molettes de laiton de l'ancien
   plateau télé sont remplacées par des touches du même verre que les autres
   touches de la page (« Apprendre à jouer », les tuiles) : verre fumé, filet de
   laiton clair, PIED de laiton (section 5 bis), pictogramme au trait à l'accent.
     téléphone : une rangée de quatre touches carrées de 44 px, pictogramme seul ;
     ordinateur : une colonne de touches larges, pictogramme et nom côte à côte.
   SON COUPÉ (aria-pressed="true", posé par son.js) : la touche RESTE ENFONCÉE
   (pied écrasé, verre assombri), le haut-parleur est barré et s'éteint, et sur
   ordinateur son nom devient « Son coupé ». Au clavier : l'anneau commun.
   Le comportement ne change pas : mêmes identifiants, « tele:action » (pupitre.js).
   Bloc remplaçable d'un seul tenant (de BOUTONS:DEBUT à BOUTONS:FIN) : les deux
   autres propositions (A, la barre de verre ; B, les pastilles plates) sont
   rangées à part, prêtes à prendre sa place.
   -------------------------------------------------------------------------- */

/* .commandes : la rangée (téléphone) ou la colonne (ordinateur) des quatre touches */
.commandes { display: flex; flex: none; align-items: center; gap: calc(5 * var(--u)); }
/* .commande : une touche de verre debout sur son pied de laiton */
.commande {
  display: flex; align-items: center; justify-content: center; gap: calc(10 * var(--u));
  min-width: max(44px, calc(44 * var(--u))); min-height: max(44px, calc(44 * var(--u)));
  padding: 0;
  border: 0; border-radius: calc(12 * var(--u)); cursor: pointer;
  color: var(--metal-vif);
  --pied: calc(3 * var(--u)); --course: calc(2 * var(--u));
  /* (2026-10-16 : la même matière que toutes les touches de verre de la page, --verre-touche et
     --ombre-verre, section 5 bis : le reflet, la lueur d'ambre, le filet qui s'allume sous la souris) */
  background: var(--verre-touche);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  box-shadow: var(--ombre-verre);
  transition: transform 0.1s ease, filter 0.15s ease, box-shadow 0.15s ease;
  -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
/* .commande-disque : la place du pictogramme (le nom de classe vient des anciennes molettes) */
.commande-disque { display: grid; place-items: center; flex: none; width: calc(22 * var(--u)); height: calc(22 * var(--u)); }
.commande-disque svg {
  width: 100%; height: 100%;
  fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
/* SOUS LA SOURIS elle se soulève ; SOUS LE DOIGT elle s'enfonce (son pied s'écrase) ; AU CLAVIER, l'anneau commun */
.commande:hover { transform: translateY(calc(-1.5 * var(--u))); filter: brightness(1.1); --lueur-verre: 0.36; --filet-touche: var(--accent-vif); }
.commande:active { --pied: calc(1 * var(--u)); transform: translateY(var(--course)); filter: brightness(0.96); }
.commande:focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
/* .commande-nom : le nom de la touche (ordinateur seulement : sur téléphone, le pictogramme seul) */
.commande-nom {
  display: none;
  font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  font-size: max(11px, calc(12 * var(--u))); line-height: 1; color: var(--metal-vif); white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
/* son coupé : la touche reste enfoncée, le haut-parleur est barré et s'éteint */
.commande .son-barre { display: none; }
.commande[aria-pressed="true"] .son-ondes { display: none; }
.commande[aria-pressed="true"] .son-barre { display: inline; }
.commande[aria-pressed="true"] {
  --pied: calc(1 * var(--u)); transform: translateY(var(--course));
  background: linear-gradient(180deg, rgba(var(--verre-bas), 0.96), rgba(var(--verre-bas), 0.9));
  box-shadow:
    inset 0 0 0 max(1.2px, calc(1.4 * var(--u))) var(--metal-sombre),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre),
    inset 0 calc(3 * var(--u)) calc(6 * var(--u)) rgba(0, 0, 0, 0.85);
}
.commande[aria-pressed="true"]:hover { transform: translateY(calc(0.5 * var(--u))); }
.commande[aria-pressed="true"] svg { stroke: var(--texte-doux); }
.commande[aria-pressed="true"] .commande-nom { color: var(--texte-doux); }

@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .commandes {
    grid-area: cmd; flex-direction: column; justify-self: center; align-self: start; align-items: stretch;
    gap: calc(10 * var(--u)); width: calc(146 * var(--u)); padding-top: calc(2 * var(--u));
  }
  .commande { justify-content: flex-start; min-height: calc(46 * var(--u)); padding: 0 calc(14 * var(--u)); }
  .commande-disque { width: calc(20 * var(--u)); height: calc(20 * var(--u)); }
  .commande-nom { display: block; }
}
/* BOUTONS:FIN */


/* ============================================================================
   8. RAMPE DE CADRANS
   ----------------------------------------------------------------------------
   Un cadran = une PLACE (.cadran-gauche, .cadran-centre, .cadran-droite) et un
   CONTENU (.cadran-vies, .cadran-chrono, .cadran-lice). Le cadran du centre est
   le grand. pupitre.js les tient à jour (TeleScene.majStats, majChrono,
   etatSalon) : .est-eteint = rien à mesurer pour l'instant.
   ========================================================================== */

/* .rail : le rail de laiton sur lequel les instruments sont montés (décor, aria-hidden) */
.rail {
  grid-area: instruments; align-self: center; z-index: 0;
  height: calc(7 * var(--u)); margin-left: calc(6 * var(--u)); margin-right: calc(6 * var(--u)); border-radius: 999px;
  background: linear-gradient(180deg, var(--metal-vif) 0%, var(--metal-clair) 22%, var(--metal-creux) 62%, var(--metal-pied) 100%);
  box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.9), 0 calc(3 * var(--u)) calc(8 * var(--u)) rgba(0, 0, 0, 0.6);
}
.instruments, .etiquette, .cadran { z-index: 1; }

/* .cadran : un instrument rond, couronne de métal et face de verre (réglage : --diametre) */
.cadran {
  position: relative; flex: none;
  width: var(--diametre); height: var(--diametre); border-radius: 50%;
  padding: calc(var(--diametre) * 0.075);
  background: var(--laiton);
  background: conic-gradient(from 205deg, var(--metal-pied), var(--metal-vif) 13%, var(--metal-clair) 24%, var(--metal-creux) 42%,
    var(--metal-pied) 54%, var(--metal-clair) 69%, var(--metal-vif) 77%, var(--metal-sombre) 90%, var(--metal-pied));
  box-shadow:
    0 0 0 max(1px, calc(1.5 * var(--u))) rgba(14, 8, 2, 0.92),
    0 calc(8 * var(--u)) calc(22 * var(--u)) rgba(0, 0, 0, 0.6),
    inset 0 1px 1px rgba(255, 255, 255, 0.5);
  transition: filter 0.3s ease;
}
/* les trois places : gauche et droite sont les petits cadrans, le centre est le grand */
/* (2026-10-16 : la rampe est resserrée, 78 et 104 avant, 70 et 92 maintenant ; le chrono reste le plus grand, et son chiffre grandit dans sa face) */
.cadran-gauche, .cadran-droite { --diametre: calc(70 * var(--u)); }
.cadran-centre { --diametre: calc(92 * var(--u)); }
/* .cadran.est-eteint : un instrument au repos (rien à mesurer pour l'instant) */
.cadran.est-eteint { filter: saturate(0.35) brightness(0.72); }

/* .cadran-face : la face de verre ; dedans .cadran-chiffre, .cadran-nom, un svg.anneau, ou .vies */
.cadran-face {
  position: relative; width: 100%; height: 100%; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 30%, rgb(var(--verre-haut)) 0%, rgb(var(--verre-bas)) 72%);
  box-shadow:
    0 0 0 max(1px, calc(1.5 * var(--u))) rgba(10, 6, 2, 0.95),
    inset 0 calc(4 * var(--u)) calc(12 * var(--u)) rgba(0, 0, 0, 0.9);
  overflow: hidden;
}
/* reflet du verre */
.cadran-face::after {
  content: ''; position: absolute; left: 12%; right: 12%; top: 5%; height: 40%;
  border-radius: 50%; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0));
}
/* .cadran-nom : le libellé gravé au bas de la face (« Vies », « sec », « en lice ») */
.cadran-nom {
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: max(8.5px, calc(var(--diametre) * 0.105)); color: var(--metal-clair);
  line-height: 1;
}
/* .cadran-chiffre : le nombre affiché par le cadran */
.cadran-chiffre {
  font-family: var(--police-plateau); font-weight: 900; line-height: 0.95;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--texte); min-height: 0.95em;
}
/* svg.anneau : l'anneau qui se vide ; cercles .piste (le fond) et .reste (pathLength="100", stroke-dasharray="64 100") */
.cadran svg.anneau { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.anneau circle { fill: none; }
.anneau .piste { stroke: rgba(255, 255, 255, 0.08); stroke-width: 5.5; }
.anneau .reste { stroke: var(--accent); stroke-width: 5.5; stroke-linecap: round; filter: drop-shadow(0 0 2.5px var(--accent)); }
.anneau .graduation { stroke: rgba(var(--metal-clair-rvb), 0.75); stroke-width: 1.3; }

/* .cadran-chrono : un compte à rebours (grand chiffre, anneau épais) ; .urgent le fait rougir */
.cadran-chrono .cadran-chiffre { font-size: calc(var(--diametre) * 0.4); margin-top: calc(var(--diametre) * 0.02); text-shadow: 0 0 calc(14 * var(--u)) rgba(var(--accent-rvb), 0.55); }
.cadran-chrono .cadran-nom { margin-top: calc(var(--diametre) * 0.012); font-size: max(8px, calc(var(--diametre) * 0.08)); letter-spacing: 0.2em; margin-right: -0.2em; }
.cadran-chrono.urgent .reste { stroke: var(--alerte); filter: drop-shadow(0 0 3px var(--alerte)); }
.cadran-chrono.urgent .cadran-chiffre { color: var(--alerte); text-shadow: 0 0 calc(16 * var(--u)) var(--alerte); }
/* .cadran-plaque : « Temps écoulé ! », à cheval sur le bas du cadran du chrono */
.cadran-plaque {
  position: absolute; z-index: 2; left: 50%; bottom: 0; transform: translate(-50%, 45%);
  padding: calc(2.5 * var(--u)) calc(9 * var(--u)); border-radius: calc(4 * var(--u));
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.08em;
  font-size: max(9.5px, calc(10.5 * var(--u))); line-height: 1.2; white-space: nowrap;
  color: var(--sur-alerte);
  background: linear-gradient(180deg, var(--alerte-claire), var(--alerte));
  box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.85), 0 2px 5px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
/* .cadran-vies : des cœurs ; .vies porte --nombre (2 au moins), chaque svg est .pleine ou .perdue.
   Un libellé (« — ») peut remplacer les cœurs : .vies-libelle */
.vies { display: flex; gap: calc(var(--diametre) * 0.035); margin-bottom: calc(var(--diametre) * 0.06); min-height: calc(var(--diametre) * 0.2); align-items: center; }
.vies svg { --cote: calc(var(--diametre) * min(0.27, 0.66 / var(--nombre, 2))); width: var(--cote); height: var(--cote); }
.vies .pleine { fill: var(--vie); filter: drop-shadow(0 0 calc(4 * var(--u)) rgba(var(--vie-rvb), 0.8)); }
.vies .perdue { fill: none; stroke: var(--vie-eteinte); stroke-width: 1.6; }
.vies-libelle { font-family: var(--police-plateau); font-weight: 900; font-size: calc(var(--diametre) * 0.24); line-height: 1; color: var(--texte-doux); }
/* .cadran-lice : un nombre et son libellé, anneau fin qui dit une part (joueurs en lice) */
.cadran-lice .cadran-chiffre { font-size: calc(var(--diametre) * 0.34); margin-top: calc(var(--diametre) * 0.01); margin-bottom: calc(var(--diametre) * 0.02); }
.cadran-lice .cadran-nom { letter-spacing: 0.06em; font-size: max(8px, calc(var(--diametre) * 0.098)); }
.cadran-lice .anneau .piste, .cadran-lice .anneau .reste { stroke-width: 3; }
.cadran-lice .anneau .reste { stroke: var(--metal-clair); filter: none; }

@media (orientation: landscape) and (max-height: 560px) {
  .cadran-gauche, .cadran-droite { --diametre: calc(68 * var(--u)); }
  .cadran-centre { --diametre: calc(76 * var(--u)); }
  .cadran-nom { font-size: max(7.5px, calc(var(--diametre) * 0.105)); }
  .cadran-lice .cadran-nom { font-size: max(7.5px, calc(var(--diametre) * 0.098)); }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .rail { grid-area: 2 / 2 / 3 / 7; margin-left: calc(10 * var(--u)); margin-right: calc(10 * var(--u)); height: calc(9 * var(--u)); }
  /* sans jeu du soir, le rail n'a rien à rejoindre à droite : il s'arrête un peu après le dernier cadran */
  .pupitre.sans-lot > .rail { margin-right: calc(218 * var(--u)); }
  .cadran { align-self: center; justify-self: center; margin-top: var(--ecart); }
  .cadran-gauche { grid-area: cg; --diametre: var(--col-cadran); }
  .cadran-centre { grid-area: cc; --diametre: var(--col-chrono); }
  .cadran-droite { grid-area: cd; --diametre: var(--col-cadran); }
}


/* ============================================================================
   9. ÉTIQUETTES DE VERRE
   ----------------------------------------------------------------------------
   Une étiquette = .verre.etiquette, une PLACE (.etiquette-gauche ou -droite) et
   un CONTENU (.etiquette-manche ou .etiquette-lot). Sur ordinateur elles
   encadrent les cadrans ; sur téléphone ce sont deux fines bandes, au-dessus et
   au-dessous de la scène. pupitre.js les écrit (majStats, majLot, etatSalon,
   afficherPartenaire).
   ========================================================================== */

/* .etiquette : la petite plaque de verre ; dedans un ou deux .etiquette-bloc (.etiquette-nom + .etiquette-valeur) */
.etiquette {
  display: flex; align-items: center; justify-content: center; min-width: 0;
  padding: 0 calc(14 * var(--u));
  --rayon: calc(10 * var(--u)); --cerclage: max(1px, calc(1.2 * var(--u)));
}
.etiquette-gauche { grid-area: eg; height: calc(30 * var(--u)); }
.etiquette-droite { grid-area: ed; height: calc(32 * var(--u)); }
.etiquette-bloc { display: flex; align-items: center; gap: calc(7 * var(--u)); min-width: 0; }
/* .etiquette-nom : ce que la case nomme (« Manche », « Jeu du soir ») */
.etiquette-nom {
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em;
  font-size: var(--taille-etiquette);
  color: var(--metal-clair); white-space: nowrap;
}
/* .etiquette-valeur : sa valeur */
.etiquette-valeur { font-family: var(--police-plateau); font-weight: 900; color: var(--texte); }
/* .difficulte : quatre étoiles (svg, la classe .pleine allume) */
.difficulte { display: inline-flex; gap: calc(3 * var(--u)); }
.difficulte svg { width: var(--etoile); height: var(--etoile); fill: rgba(255, 255, 255, 0.13); }
.difficulte svg.pleine { fill: var(--accent); filter: drop-shadow(0 0 calc(3 * var(--u)) rgba(var(--accent-rvb), 0.7)); }

/* .etiquette-manche : deux informations courtes côte à côte (manche et difficulté), valeur en grand chiffre */
.etiquette-manche { justify-content: space-between; gap: calc(10 * var(--u)); }
.etiquette-manche .etiquette-valeur { font-size: calc(15 * var(--u)); line-height: 1; }
/* .etiquette-libelle : un libellé seul, à la place de la manche (« EN ATTENTE », « TUTORIEL », un partenaire) */
.etiquette-libelle {
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.14em;
  font-size: calc(var(--taille-etiquette) * 1.15); color: var(--metal-vif);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.etiquette-libelle:empty { display: none; }
/* .etiquette-mode : la manche spéciale (« BONNE RÉPONSE », « VITESSE », « FINALE »), à la place des étoiles */
.etiquette-mode {
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: calc(var(--taille-etiquette) * 1.15); color: var(--accent); white-space: nowrap;
  text-shadow: 0 0 calc(10 * var(--u)) rgba(var(--accent-rvb), 0.5);
}
/* .etiquette-lot : une seule information au texte long (le jeu du soir), abrégée si elle ne tient pas */
.etiquette-lot { justify-content: flex-start; }
.etiquette-lot .etiquette-bloc { flex: 1; gap: calc(9 * var(--u)); }
.etiquette-lot .etiquette-valeur {
  flex: 1; min-width: 0; text-align: right; font-weight: 700; font-size: calc(13.5 * var(--u));
  color: var(--accent-vif); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* (Assemblage des étapes.) LE JEU DU SOIR EN ENTIER : .etiquette-lot.entier.
   Sur l'écran de l'annonce (une manche, la finale), les annonces ne redisent
   plus le jeu du soir dans leur carton (« Ce soir : … », étapes 1 et 3), et
   sur téléphone un titre long était abrégé dans son étiquette (« Ori and the
   Will of the… ») : il ne se lisait alors nulle part sur cet écran. Le décor
   (pupitre.js, deplierLeJeuDuSoir) pose donc la classe « entier » sur
   l'étiquette pendant l'annonce : un titre court reste sur la ligne de « Jeu
   du soir » ; un titre long passe dessous, sur deux lignes au plus, et
   l'étiquette grandit d'autant. Cette hauteur est prise au carton de
   l'annonce : le décor ne pose la classe que s'il a la place (une feuille ne
   sait pas mesurer). Jamais sur téléphone couché, où la hauteur manque
   toujours ; sur la question et les résultats, le titre reste abrégé sur une
   ligne. */
.etiquette-lot.entier {
  height: auto; min-height: calc(32 * var(--u));
  padding-top: calc(6 * var(--u)); padding-bottom: calc(6 * var(--u));
}
.etiquette-lot.entier .etiquette-bloc { flex-wrap: wrap; row-gap: calc(3 * var(--u)); }
.etiquette-lot.entier .etiquette-valeur {
  flex: 1 1 auto; white-space: normal; text-wrap: balance; overflow-wrap: anywhere; line-height: 1.18;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

@media (orientation: landscape) and (max-height: 560px) {
  /* côte à côte sur une même rangée : même hauteur */
  .etiquette-gauche, .etiquette-droite { height: calc(28 * var(--u)); }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .etiquette {
    align-self: center; height: var(--col-cadran); padding: 0 calc(16 * var(--u));
    --rayon: calc(14 * var(--u)); --cerclage: max(1.5px, calc(1.8 * var(--u)));
  }
  .etiquette-bloc { flex-direction: column; align-items: center; gap: calc(7 * var(--u)); }
  .etiquette-manche { justify-content: center; gap: calc(20 * var(--u)); }
  .etiquette-manche .etiquette-valeur { font-size: calc(36 * var(--u)); line-height: 0.9; }
  .etiquette-manche .etiquette-bloc + .etiquette-bloc:not(.etiquette-libelle) {
    padding-left: calc(20 * var(--u)); border-left: 1px solid rgba(var(--metal-clair-rvb), 0.4);
    align-self: stretch; justify-content: center; margin-top: calc(14 * var(--u)); margin-bottom: calc(14 * var(--u));
  }
  .etiquette-libelle { font-size: calc(16 * var(--u)); white-space: normal; text-align: center; line-height: 1.15; }
  /* (« width: min-content » : un mode en deux mots, « BONNE RÉPONSE », passe sur deux lignes ; sans cela son bloc
     gardait la largeur d'une seule ligne, et repoussait « MANCHE » contre le bord gauche de l'étiquette) */
  .etiquette-mode { width: min-content; font-size: calc(15 * var(--u)); white-space: normal; text-align: center; line-height: 1.15; }
  /* un libellé à la place de la manche (« TUTORIEL », un partenaire) : il prend sa ligne, la difficulté passe dessous */
  .etiquette-manche.a-libelle { flex-direction: column; gap: calc(8 * var(--u)); }
  .etiquette-manche.a-libelle .etiquette-bloc + .etiquette-bloc:not(.etiquette-libelle) {
    flex-direction: row; align-self: center; padding-left: 0; border-left: 0; margin-top: 0; margin-bottom: 0;
  }
  .etiquette-lot { justify-content: center; }
  .etiquette-lot .etiquette-bloc { flex: 1; gap: calc(8 * var(--u)); }
  .etiquette-lot .etiquette-valeur {
    flex: none; max-width: 100%; text-align: center; white-space: normal; text-wrap: balance;
    font-size: calc(17 * var(--u)); line-height: 1.12;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* (le jeu du soir en entier, sur l'écran de l'annonce : l'étiquette garde sa place à côté des cadrans, et sa
     hauteur ; le titre y prend une troisième ligne s'il est long) */
  .etiquette-lot.entier { height: var(--col-cadran); min-height: 0; padding-top: 0; padding-bottom: 0; }
  .etiquette-lot.entier .etiquette-bloc { flex-wrap: nowrap; }
  .etiquette-lot.entier .etiquette-valeur { flex: none; overflow-wrap: normal; line-height: 1.12; -webkit-line-clamp: 3; }
}


/* ============================================================================
   10. PANNEAU RIVETÉ, QUESTION, TOUCHES DE RÉPONSE
   ========================================================================== */

/* .panneau : le grand panneau riveté (avec .verre.rivete) ; il centre son contenu et ne déborde jamais */
.panneau {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 0; min-width: 0; overflow: hidden;
  padding: var(--marge-panneau);
}
/* .panneau-haut : le contenu part du haut du panneau au lieu d'être centré (listes, formulaires) */
.panneau-haut { justify-content: flex-start; }
/* .question : le texte de la question, dans un .panneau. Longue, sa police
   rétrécit juste assez pour tenir, et elle seule (pupitre.js, ajusterQuestion). */
.question p {
  margin: 0; text-align: center; text-wrap: balance;
  font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.012em; line-height: 1.2;
  font-size: var(--taille-question); color: var(--texte);
  text-shadow: 0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), 0.22), 0 0 calc(2 * var(--u)) rgba(255, 255, 255, 0.25), 0 2px 0 rgba(0, 0, 0, 0.7);
}
/* LA QUESTION ET SES RÉPONSES, HÉROS DE L'ÉCRAN DE MANCHE (2026-10-16, Gautier : « les questions/réponses ne
   sont pas assez mises en valeur [...] ça ne saute pas aux yeux au premier coup d'œil que c'est là que tout se
   passe »). Le panneau de la question est le seul de l'écran à porter cette lumière : un cerclage de laiton
   plus épais et plus clair, un filet d'ambre en dedans, la lueur d'un projecteur venue du haut, deux filets de
   laiton qui encadrent le texte, et une lueur d'ambre autour de lui. (#pupitre-question : la question d'une
   manche ; #pupitre-question-partenaire, celle d'un partenaire, garde le panneau ordinaire.) */
#pupitre-question {
  --cerclage: max(2px, calc(3 * var(--u)));
  background:
    linear-gradient(90deg, rgba(var(--metal-clair-rvb), 0), rgba(var(--metal-clair-rvb), 0.55), rgba(var(--metal-clair-rvb), 0)) 50% calc(16 * var(--u)) / 46% max(1px, calc(1.2 * var(--u))) no-repeat,
    linear-gradient(90deg, rgba(var(--metal-clair-rvb), 0), rgba(var(--metal-clair-rvb), 0.55), rgba(var(--metal-clair-rvb), 0)) 50% calc(100% - 16 * var(--u)) / 46% max(1px, calc(1.2 * var(--u))) no-repeat,
    radial-gradient(ellipse 70% 60% at 50% 0%, rgba(var(--accent-rvb), 0.17), rgba(var(--accent-rvb), 0) 100%),
    var(--verre-fond);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.75),
    0 0 calc(34 * var(--u)) rgba(var(--accent-rvb), 0.2),
    0 calc(14 * var(--u)) calc(34 * var(--u)) rgba(0, 0, 0, 0.6),
    inset 0 0 0 calc(6 * var(--u)) rgba(0, 0, 0, 0.25),
    inset 0 0 0 calc(7 * var(--u)) rgba(var(--accent-rvb), 0.22),
    inset 0 0 calc(30 * var(--u)) rgba(0, 0, 0, 0.42);
}
#pupitre-question::before {
  background: linear-gradient(152deg, var(--accent-vif) 0%, var(--metal-vif) 12%, var(--metal-clair) 30%, var(--metal-creux) 50%,
    var(--metal-sombre) 70%, var(--metal-vif) 88%, var(--accent-vif) 100%);
}

/* .touches : la grille des réponses (une colonne debout, deux ailleurs) */
.touches { display: grid; grid-auto-rows: 1fr; gap: var(--ecart-touches); grid-template-columns: minmax(0, 1fr); }
/* .reponse : une touche de réponse. app.js réécrit sa classe à chaque question
   (« reponse », « reponse choisie ») et la désactive une fois la réponse donnée :
   la touche choisie s'enfonce et s'allume, les autres passent en veilleuse.
   Dedans : .touche-lettre (A, B, C, D) et .reponse-texte. */
.reponse {
  --rayon: calc(14 * var(--u)); --cerclage: max(1.5px, calc(2 * var(--u)));
  display: flex; align-items: center; gap: calc(12 * var(--u));
  min-height: var(--hauteur-touche); padding: calc(6 * var(--u)) calc(14 * var(--u)) calc(6 * var(--u)) calc(10 * var(--u));
  border: 0; cursor: pointer; text-align: left; color: var(--texte);
  /* UNE GRANDE TOUCHE (2026-10-16) : le reflet d'une pièce polie sur sa moitié haute, une lueur d'ambre
     derrière sa lettre, un pied de laiton ; sous la souris, une lueur à l'accent tout autour */
  --pied: calc(4 * var(--u));
  --lueur-verre: 0;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.025) 48%, rgba(255, 255, 255, 0) 52%),
    radial-gradient(circle at calc(10 * var(--u) + var(--pastille-touche) / 2) 50%, rgba(var(--accent-rvb), 0.16), rgba(var(--accent-rvb), 0) calc(var(--pastille-touche) * 1.6)),
    linear-gradient(180deg, rgba(var(--verre-haut), 0.94), rgba(var(--verre-bas), 0.97));
  /* (le pied de laiton d'une touche de verre : section 5 bis) */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre),
    0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), var(--lueur-verre)),
    0 calc(12 * var(--u)) calc(22 * var(--u)) rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
  transition: transform 0.1s ease, box-shadow 0.15s ease, opacity 0.2s ease, filter 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}
/* .touche-lettre : la pastille de laiton A, B, C, D */
.touche-lettre {
  flex: none; display: grid; place-items: center;
  width: var(--pastille-touche); height: var(--pastille-touche); border-radius: 50%;
  font-family: var(--police-plateau); font-weight: 900; font-size: calc(var(--pastille-touche) * 0.52);
  color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
  /* une médaille de laiton poli : le reflet en haut, l'ambre en bas, un liseré clair en dedans */
  background:
    radial-gradient(circle at 38% 28%, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 42%),
    linear-gradient(175deg, var(--metal-vif) 0%, var(--accent-vif) 30%, var(--accent) 66%, var(--accent-sombre) 100%);
  box-shadow:
    inset 0 0 0 max(1px, calc(1.5 * var(--u))) rgba(255, 236, 190, 0.45),
    inset 0 calc(-2 * var(--u)) calc(4 * var(--u)) rgba(70, 30, 0, 0.4),
    0 0 0 1px rgba(14, 8, 2, 0.85),
    0 calc(2 * var(--u)) calc(5 * var(--u)) rgba(0, 0, 0, 0.6),
    0 0 calc(12 * var(--u)) rgba(var(--accent-rvb), 0.25);
}
/* LE TEXTE D'UNE RÉPONSE : en lettres courantes, grasses (2026-10-16). En Cinzel, police de capitales, une
   réponse longue se lisait en petites capitales serrées ; le texte courant se lit d'un coup d'œil, même long,
   et laisse la question (Cinzel) être le titre de l'écran. */
.reponse-texte {
  flex: 1; min-width: 0; text-wrap: balance; overflow-wrap: anywhere;
  font-family: var(--police-texte); font-weight: 700; letter-spacing: 0.005em; line-height: 1.18;
  font-size: var(--taille-reponse); color: var(--texte);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}
/* la coche de la touche choisie (dessinée : app.js ne pose aucun élément pour elle) */
.reponse::after {
  content: ''; flex: none; width: calc(var(--pastille-touche) * 0.24); height: calc(var(--pastille-touche) * 0.46);
  margin-right: calc(var(--pastille-touche) * 0.2); margin-bottom: calc(var(--pastille-touche) * 0.1);
  border: solid var(--accent-vif); border-width: 0 max(2px, calc(2.6 * var(--u))) max(2px, calc(2.6 * var(--u))) 0;
  transform: rotate(42deg); opacity: 0;
}
.reponse:hover:not(:disabled):not(.choisie) { transform: translateY(calc(-2 * var(--u))); filter: brightness(1.14); --lueur-verre: 0.42; }
/* sous le doigt, avant même que la réponse soit prise : la touche s'enfonce, son pied s'écrase */
.reponse:active:not(:disabled):not(.choisie) { --pied: calc(1 * var(--u)); transform: translateY(calc(var(--course) + 1 * var(--u))); filter: brightness(1.04); --lueur-verre: 0.3; }
.reponse:focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
/* la touche choisie : enfoncée, et allumée en ambre (choix de la maquette, plan de bascule, décision 5) */
.reponse.choisie {
  transform: translateY(calc(3 * var(--u)));
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.14) 0%, rgba(255, 255, 255, 0.03) 48%, rgba(255, 255, 255, 0) 52%),
    linear-gradient(90deg, rgba(var(--accent-rvb), 0.42), rgba(var(--accent-rvb), 0.18) 60%, rgba(var(--accent-rvb), 0.12)),
    linear-gradient(180deg, rgb(var(--verre-haut)), rgb(var(--verre-bas)));
  box-shadow:
    0 0 0 max(2px, calc(2.5 * var(--u))) var(--accent),
    0 calc(1 * var(--u)) 0 rgba(3, 4, 7, 0.95),
    0 0 calc(30 * var(--u)) rgba(var(--accent-rvb), 0.6),
    inset 0 0 calc(26 * var(--u)) rgba(var(--accent-rvb), 0.26);
}
.reponse.choisie .reponse-texte { color: var(--accent-vif); text-shadow: 0 0 calc(12 * var(--u)) rgba(var(--accent-rvb), 0.45), 0 1px 2px rgba(0, 0, 0, 0.8); }
.reponse.choisie::before { opacity: 0; }
.reponse.choisie .touche-lettre {
  color: var(--sur-accent);
  background: radial-gradient(circle at 40% 32%, #fff 0%, var(--accent-vif) 22%, var(--accent) 62%, var(--accent-sombre) 100%);
  box-shadow: 0 0 calc(12 * var(--u)) var(--accent), 0 0 0 1px rgba(14, 8, 2, 0.8);
}
.reponse.choisie::after { opacity: 1; }
/* les autres touches s'éteignent : le verre reste, le contenu passe en veilleuse */
.reponse:disabled { cursor: default; }
.reponse:disabled:not(.choisie) { --socle-teinte: rgba(3, 4, 7, 0.95); }
.reponse:disabled:not(.choisie)::before { opacity: 0.4; }
.reponse:disabled:not(.choisie) .reponse-texte { opacity: 0.45; }
.reponse:disabled:not(.choisie) .touche-lettre { opacity: 0.5; filter: saturate(0.5); box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.85); }

@media (orientation: landscape) and (max-height: 560px) {
  .touches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .reponse { padding: calc(4 * var(--u)) calc(10 * var(--u)); gap: calc(9 * var(--u)); }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .panneau { --rayon: calc(20 * var(--u)); }
  .touches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .reponse { padding: calc(8 * var(--u)) calc(22 * var(--u)) calc(8 * var(--u)) calc(16 * var(--u)); gap: calc(18 * var(--u)); --rayon: calc(16 * var(--u)); --pied: calc(5 * var(--u)); }
  .reponse { background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.025) 48%, rgba(255, 255, 255, 0) 52%),
    radial-gradient(circle at calc(16 * var(--u) + var(--pastille-touche) / 2) 50%, rgba(var(--accent-rvb), 0.16), rgba(var(--accent-rvb), 0) calc(var(--pastille-touche) * 1.6)),
    linear-gradient(180deg, rgba(var(--verre-haut), 0.94), rgba(var(--verre-bas), 0.97)); }
}


/* ============================================================================
   11. LE PROFESSEUR ET SA BULLE
   ----------------------------------------------------------------------------
   Le professeur (#mascotte) est fabriqué par mascotte.js ; pupitre.js le range
   dans .professeur. Il ne quitte jamais sa place : pas de premier plan.
   La bulle est le cadre où mascotte.js écrit (TeleScene.dialogueEl). Elle a une
   hauteur FIXE (--bulle-lignes) et garde sa place même quand il se tait
   (invisible, pas retirée) : rien ne bouge quand il prend la parole. Une
   réplique trop longue passe en pages (pupitre.js, decouperEnPages).
   Une feuille d'étape règle le nombre de lignes pour ses écrans, sur la bulle
   elle-même : body[data-ecran="jeu"] .bulle { --bulle-lignes: 2; }
   ========================================================================== */

/* .professeur : la place du professeur, accoudé en bas à gauche */
.professeur { position: relative; pointer-events: none; flex: none; width: var(--largeur-professeur); margin-left: calc(-6 * var(--u)); }
#mascotte { display: block; }
#mascotte[hidden] { display: none; }
.mascotte-perso { display: block; transform-origin: 50% 100%; }
.mascotte-perso canvas { display: block; width: 100%; height: auto; filter: drop-shadow(0 calc(6 * var(--u)) calc(14 * var(--u)) rgba(0, 0, 0, 0.65)); }
/* (2026-10-16) Le professeur remonte : il ne s'appuie plus sur le bord de l'écran, et le bas de son buste, coupé net
   par l'image, se fond dans le fond au lieu de tracer une ligne droite. Sa toile a pile les pixels de l'écran
   (mascotte.js, « la netteté du professeur ») : plus de crénelage. */
.mascotte-perso canvas {
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 80%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 80%, transparent 100%);
}
/* l'ancienne bulle flottante et son voile sombre : jamais montrés (la bulle du pupitre les remplace) */
.mascotte-bulle, #mascotte-fond { display: none !important; }
/* il vit : un rebond quand il parle, un ricanement quand il se moque, immobile quand il se tait */
#mascotte.etat-parle .mascotte-perso { animation: professeur-parle 0.46s ease-in-out infinite; }
#mascotte.etat-moqueur .mascotte-perso { animation: professeur-ricane 0.5s ease-in-out 3; }
#mascotte.etat-dort .mascotte-perso { filter: saturate(0.7) brightness(0.85); }
@keyframes professeur-parle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(calc(-2.5 * var(--u))); } }
@keyframes professeur-ricane { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(-2.5deg); } 70% { transform: rotate(2.5deg); } }

/* .bulle : sa barre de dialogue (avec .verre) ; dedans .bulle-queue, .bulle-nom et le paragraphe .bulle-texte */
.bulle {
  display: flex; align-items: center; flex: 1; min-width: 0; z-index: 2;
  height: calc(var(--bulle-lignes) * var(--interligne-bulle) * var(--taille-bulle) + var(--bulle-haut) + var(--bulle-bas));
  margin-bottom: calc(10 * var(--u));
  padding: var(--bulle-haut) var(--bulle-cote) var(--bulle-bas);
  --rayon: calc(13 * var(--u));
  visibility: hidden;                              /* il se tait : la place reste, la bulle s'efface */
}
.bulle.est-ouverte { visibility: visible; }
/* Le texte de la bulle se SUIT, comme sur la maquette : mascotte.js sépare les
   phrases par un retour à la ligne, qui se lit ici comme une espace (les pages
   d'une réplique longue se coupent toujours là d'abord). Une phrase par ligne
   convenait à la large barre de dialogue de l'ancien plateau ; dans une bulle
   de hauteur fixe elle coûte des pages. Mesuré dans Chrome sur 549 répliques :
   une phrase par ligne, 86 % tiennent en une page sur téléphone et 83 % sur
   ordinateur ; en texte suivi, 95 % et 100 % (les chiffres du plan de bascule,
   décision 3). Pas de « text-wrap » : les lignes ne bougent pas pendant la frappe. */
.bulle-texte {
  margin: 0; min-width: 0; max-height: 100%; overflow: hidden;
  font-size: var(--taille-bulle); line-height: var(--interligne-bulle); color: var(--texte);
  white-space: normal;
  overflow-wrap: anywhere;
}
/* ce que mascotte.js met en couleur dans une réplique */
.bulle-texte .pseudo-cite { color: var(--accent); font-weight: 700; }
.bulle-texte .citation-reponse { color: var(--accent-vif); }
.bulle-texte .dialogue-fin { color: var(--metal-clair); letter-spacing: 0.1em; }
/* .bulle-nom : la plaquette de laiton qui dit qui parle (« LE PROFESSEUR », « L'ÉQUIPE DU LABO ») */
.bulle-nom {
  position: absolute; z-index: 1; left: calc(16 * var(--u)); top: 0; transform: translateY(-55%);
  padding: calc(2.5 * var(--u)) calc(9 * var(--u));
  border-radius: calc(4 * var(--u));
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: max(9px, calc(9.5 * var(--u)));
  color: var(--sur-metal); white-space: nowrap;
  background: linear-gradient(180deg, var(--metal-vif), var(--metal-clair) 40%, var(--metal-sombre));
  box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.85), 0 2px 5px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
/* l'équipe prend la parole (SPECS 13) : sa plaquette est au bleu de l'information, pas au laiton du professeur */
.bulle.bulle-equipe .bulle-nom { color: var(--sur-moi); background: linear-gradient(180deg, var(--moi-vif), var(--moi)); }
/* .bulle-queue : la petite queue de la bulle, tournée vers le professeur (décor, aria-hidden) */
.bulle-queue {
  position: absolute; left: calc(-6.5 * var(--u)); bottom: calc(18 * var(--u));
  width: calc(13 * var(--u)); height: calc(13 * var(--u)); transform: rotate(45deg);
  background: rgb(var(--verre-bas));
  border-left: var(--cerclage, 2px) solid var(--metal-clair);
  border-bottom: var(--cerclage, 2px) solid var(--metal-sombre);
  border-bottom-left-radius: calc(3 * var(--u));
}

@media (orientation: landscape) and (max-height: 560px) {
  .bulle { margin-bottom: calc(8 * var(--u)); }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .professeur { grid-area: prof; align-self: end; justify-self: end; margin: 0 calc(-8 * var(--u)) 0 0; z-index: 2; }
  .bulle { grid-area: bulle; margin-top: var(--ecart); margin-bottom: calc(16 * var(--u)); --rayon: calc(16 * var(--u)); }
  .bulle-nom { left: calc(26 * var(--u)); font-size: max(9.5px, calc(11 * var(--u))); padding: calc(3 * var(--u)) calc(11 * var(--u)); }
}


/* ============================================================================
   12. COMPOSANTS
   ----------------------------------------------------------------------------
   Les pièces communes, dans la même matière. Elles s'appliquent aux classes du
   socle des maquettes (.bouton, .note, .surtitre…) ET aux éléments du vrai jeu
   qui jouent le même rôle (tout <button> de la page est un bouton de laiton,
   .secondaire un bouton de verre, .lien un geste discret…).
   ========================================================================== */

/* ---------- Textes ---------- */
/* .texte : le texte courant, celui qui se lit (16 px au moins sur téléphone) */
.texte { margin: 0; font-size: var(--taille-texte); line-height: 1.42; color: var(--texte); text-wrap: pretty; }
/* .note : le texte secondaire (précision, mention), en couleur plus douce */
.note { margin: 0; font-size: var(--taille-note); line-height: 1.4; color: var(--texte-doux); text-wrap: pretty; }
/* un lien dans une phrase : SOULIGNÉ, c'est ce qui le distingue d'un mot mis en valeur
   (qui s'écrit en gras, jamais souligné). Sous la souris il s'éclaircit et son trait
   s'épaissit ; sous le doigt il passe à l'accent. */
.pupitre a, dialog a { color: var(--accent-vif); text-decoration: underline; text-underline-offset: 0.18em; cursor: pointer; }
.pupitre a:hover, dialog a:hover { color: var(--texte); text-decoration-thickness: max(2px, 0.11em); }
.pupitre a:active, dialog a:active { color: var(--accent); }
.pupitre a:focus-visible, dialog a:focus-visible { outline: var(--anneau-clavier); outline-offset: 2px; border-radius: 3px; }

/* ---------- Titres ---------- */
/* .grand-titre : le grand titre d'un écran, qui luit (« Résultats », « Finale », le nom du gagnant) */
.grand-titre, .scene > h2, .resultats-titre, .lot-titre, .annonce-manche, .fin-gagnant, .sponsor-nom, .regles-titre {
  margin: 0; text-align: center; text-wrap: balance; overflow-wrap: anywhere;
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.05em; line-height: 1.04;
  font-size: var(--taille-titre); color: var(--accent);
  text-shadow: 0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), 0.55), 0 2px 0 rgba(0, 0, 0, 0.6);
}
/* .surtitre : la petite ligne en capitales au-dessus d'un titre. Dans le vrai
   jeu, le texte porte ses deux tirets (« — Tutoriel — ») : ils restent écrits. */
.surtitre, .annonce-surtitre, .regles-surtitre, .tuto-surtitre, .fin-surtitre, .rebours-label {
  display: flex; align-items: center; justify-content: center; gap: calc(10 * var(--u));
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.2em;
  font-size: var(--taille-surtitre); line-height: 1.2; color: var(--metal-clair); text-align: center;
  text-shadow: 0 1px 3px #000;
}
/* .plaque-section : la plaque qui titre une section (« Classement », « Dernières parties »).
   GRAVÉE EN CREUX, lettres de laiton sur verre sombre, deux rivets : c'est une
   information (section 5 bis). Elle était en laiton plein et en relief, comme
   un bouton : le joueur pouvait la prendre pour une touche. */
.plaque-section, .scene > h3 {
  display: inline-flex; align-items: center; justify-content: center; align-self: center;
  padding: calc(5 * var(--u)) calc(20 * var(--u));
  border-radius: calc(5 * var(--u));
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.16em;
  font-size: var(--taille-plaque); line-height: 1.2;
  color: var(--plaque-encre); white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  background: var(--plaque-rivets), var(--plaque-fond);
  box-shadow: var(--plaque-ombre);
}

/* ---------- Boutons ----------
   Tout <button> de la page et des fenêtres est une touche de laiton, SAUF ceux
   qui ont leur propre dessin (.commande, .reponse, .onglet, .lien, le bouton
   d'un bandeau, les onglets des documents légaux). :where() : cette règle ne
   pèse presque rien, n'importe quelle classe la redéfinit. */
.bouton,
:where(.pupitre, dialog) button:where(:not(.commande):not(.reponse):not(.onglet):not(.lien):not(.bandeau-action)) {
  display: inline-flex; align-items: center; justify-content: center; gap: calc(9 * var(--u));
  min-height: var(--hauteur-bouton); padding: calc(6 * var(--u)) calc(22 * var(--u));
  border: 0; border-radius: calc(12 * var(--u)); cursor: pointer;
  font-family: var(--police-plateau); font-weight: 900; font-size: var(--taille-bouton);
  letter-spacing: 0.07em; text-transform: uppercase; line-height: 1.12; text-align: center; text-decoration: none; text-wrap: balance;
  color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);
  background: var(--laiton-touche);
  /* LE PIED (section 5 bis) : la tranche de laiton sombre sous la touche. (Il était écrit
     SOUS son liseré noir, qui le couvrait en entier : on ne voyait qu'un trait sombre.)
     Sa lumière : --ombre-laiton (section 5 bis). */
  --pied: calc(5 * var(--u));
  box-shadow: var(--ombre-laiton);
  transition: transform 0.1s ease, filter 0.15s ease, box-shadow 0.15s ease;
  -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
.bouton:hover,
:where(.pupitre, dialog) button:where(:not(.commande):not(.reponse):not(.onglet):not(.lien):not(.bandeau-action)):hover { transform: translateY(calc(-2 * var(--u))); filter: brightness(1.07) saturate(1.08); --lueur-laiton: 0.6; --lueur-verre: 0.36; --filet-touche: var(--accent-vif); }
/* ENFONCÉE : la touche descend de sa course, son pied s'écrase d'autant (le bas ne bouge pas) */
.bouton:active,
:where(.pupitre, dialog) button:where(:not(.commande):not(.reponse):not(.onglet):not(.lien):not(.bandeau-action)):active { --pied: calc(1 * var(--u)); transform: translateY(calc(var(--course) + 1 * var(--u))); filter: brightness(0.94); --lueur-laiton: 0.16; --lueur-verre: 0.2; }
.bouton:focus-visible,
:where(.pupitre, dialog) button:where(:not(.commande):not(.reponse):not(.onglet):not(.lien):not(.bandeau-action)):focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
.bouton:disabled, .bouton[aria-disabled="true"],
:where(.pupitre, dialog) button:where(:not(.commande):not(.reponse):not(.onglet):not(.lien):not(.bandeau-action)):disabled { cursor: default; transform: none; filter: saturate(0.3) brightness(0.62); --lueur-laiton: 0; --lueur-verre: 0; }
/* .bouton-secondaire : le bouton secondaire, une touche de VERRE (dans le vrai jeu : la classe .secondaire).
   Son verre est celui des plaques d'information : c'est son PIED DE LAITON qui dit
   qu'elle se touche (il était noir sur fond noir : la touche se confondait avec une
   plaque), et son cerclage est du laiton clair des touches, pas du laiton sombre des plaques. */
.bouton-secondaire, button.secondaire, .menu-liste button {
  font-weight: 700; color: var(--metal-vif); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  background: var(--verre-touche);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  box-shadow: var(--ombre-verre);
}
/* .bouton-danger : un geste qui ne se défait pas (dans le vrai jeu : .danger, .menu-danger, .bouton-danger) */
.bouton-danger, button.danger, button.menu-danger { color: var(--alerte); }
button.danger, button.bouton-danger {
  font-weight: 700; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.085) 0%, rgba(255, 255, 255, 0) 24%),
    linear-gradient(180deg, rgba(var(--verre-haut), 0.86), rgba(var(--verre-bas), 0.92));
  box-shadow:
    inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) rgba(var(--alerte-rvb), 0.7),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre),
    0 calc(12 * var(--u)) calc(20 * var(--u)) rgba(0, 0, 0, 0.45);
}
button.menu-danger { box-shadow:
    inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) rgba(var(--alerte-rvb), 0.7),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre); }
/* (le pied d'un geste qui ne se défait pas est à l'alerte, comme son cerclage) */
button.danger, button.bouton-danger, button.menu-danger { --socle-teinte: var(--vie-eteinte); }
/* .bouton-grand : le bouton d'appel d'un écran (« Entrer dans le salon », « Se connecter ») */
.bouton-grand, .auth-grand, #btn-rejoindre { min-height: calc(var(--hauteur-bouton) * 1.22); font-size: calc(var(--taille-bouton) * 1.18); padding-left: calc(28 * var(--u)); padding-right: calc(28 * var(--u)); }
/* .bouton-large : le bouton prend toute la largeur de son conteneur */
.bouton-large { width: 100%; }
/* .bouton-lien : un geste discret, écrit comme un lien mais avec une vraie zone à toucher (dans le vrai jeu : button.lien) */
.bouton-lien, button.lien {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--hauteur-bouton); padding: 0 calc(10 * var(--u));
  border: 0; background: none; cursor: pointer;
  font-family: var(--police-texte); font-size: var(--taille-texte); color: var(--accent-vif);
  text-decoration: underline; text-underline-offset: 0.18em;
}
/* (les mêmes états que le lien d'une phrase) */
.bouton-lien:hover, button.lien:hover { color: var(--texte); text-decoration-thickness: max(2px, 0.11em); }
.bouton-lien:active, button.lien:active { color: var(--accent); }
.bouton-lien:focus-visible, button.lien:focus-visible { outline: var(--anneau-clavier); outline-offset: 2px; border-radius: 4px; }
/* .actions : une rangée de boutons (elle passe à la ligne si la place manque) */
.actions, .barre-outils, .dialogue-actions, .salon-rappels, .auth-accueil {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: calc(12 * var(--u)) calc(12 * var(--u));
}

/* ---------- Champs de saisie ----------
   Dans le vrai jeu, un champ est un <label> qui porte son nom puis son <input> */
.champ, :where(.pupitre, dialog) form label:where(:not(.case)) {
  display: flex; flex-direction: column; gap: calc(5 * var(--u)); min-width: 0; text-align: left;
  font-size: var(--taille-texte); line-height: 1.3; color: var(--texte-doux);
}
.champ-saisie, :where(.pupitre, dialog) :where(input:not([type="checkbox"]):not([type="radio"]), select, textarea) {
  width: 100%; min-height: var(--hauteur-bouton); padding: 0 calc(14 * var(--u));
  border: 0; border-radius: calc(10 * var(--u)); outline: none;
  -webkit-appearance: none; appearance: none;
  font-family: var(--police-texte); font-size: var(--taille-texte); color: var(--texte);
  background-color: rgb(var(--verre-bas));
  background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.12));
  box-shadow:
    inset 0 calc(2 * var(--u)) calc(6 * var(--u)) rgba(0, 0, 0, 0.85),
    0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-sombre),
    0 0 0 max(2.2px, calc(2.5 * var(--u))) rgba(0, 0, 0, 0.75);
}
:where(.pupitre, dialog) :where(input, select, textarea)::placeholder { color: rgba(var(--texte-doux-rvb), 0.72); }
:where(.pupitre, dialog) :where(input:not([type="checkbox"]):not([type="radio"]), select, textarea):focus-visible {
  box-shadow:
    inset 0 calc(2 * var(--u)) calc(6 * var(--u)) rgba(0, 0, 0, 0.85),
    0 0 0 max(1.5px, calc(2 * var(--u))) var(--accent),
    0 0 calc(14 * var(--u)) rgba(var(--accent-rvb), 0.45);
}
/* un champ rempli par le navigateur : pas de fond jaune, le verre reste */
:where(.pupitre, dialog) input:-webkit-autofill {
  -webkit-text-fill-color: var(--texte);
  box-shadow:
    inset 0 0 0 100px rgb(var(--verre-bas)),
    0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-clair),
    0 0 0 max(2.2px, calc(2.5 * var(--u))) rgba(0, 0, 0, 0.75);
}
/* la flèche d'une liste déroulante, dessinée (aucune image) */
:where(.pupitre, dialog) select {
  padding-right: calc(38 * var(--u)); cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--metal-clair) 50%),
    linear-gradient(135deg, var(--metal-clair) 50%, transparent 50%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.12));
  background-position: calc(100% - 20 * var(--u)) 52%, calc(100% - 14 * var(--u)) 52%, 0 0;
  background-size: calc(6 * var(--u)) calc(6 * var(--u)), calc(6 * var(--u)) calc(6 * var(--u)), 100% 100%;
  background-repeat: no-repeat;
}
:where(.pupitre, dialog) select option { background: rgb(var(--verre-bas)); color: var(--texte); }

/* .case : une case à cocher et sa phrase, sur <label> ; dedans <input type="checkbox"> puis <span> */
.case, .lot-majeur {
  display: flex; align-items: center; gap: calc(12 * var(--u));
  min-height: var(--hauteur-bouton); cursor: pointer; text-align: left;
  font-size: var(--taille-texte); line-height: 1.35; color: var(--texte);
}
:where(.pupitre, dialog) input[type="checkbox"] {
  -webkit-appearance: none; appearance: none; position: relative; flex: none; margin: 0; cursor: pointer;
  width: calc(26 * var(--u)); height: calc(26 * var(--u)); min-height: 0; padding: 0; border: 0; border-radius: calc(6 * var(--u));
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), rgb(var(--verre-bas)));
  box-shadow:
    inset 0 calc(2 * var(--u)) calc(5 * var(--u)) rgba(0, 0, 0, 0.85),
    0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-clair),
    0 0 0 max(2.2px, calc(2.5 * var(--u))) rgba(0, 0, 0, 0.75);
  transition: background 0.15s ease;
}
:where(.pupitre, dialog) input[type="checkbox"]::after {
  content: ''; position: absolute; left: 33%; top: 11%; width: 30%; height: 58%;
  border: solid var(--sur-accent); border-width: 0 calc(3.2 * var(--u)) calc(3.2 * var(--u)) 0;
  transform: rotate(42deg) scale(0); transition: transform 0.12s ease;
}
:where(.pupitre, dialog) input[type="checkbox"]:checked {
  background: radial-gradient(circle at 40% 30%, var(--accent-vif), var(--accent) 60%, var(--accent-sombre));
  box-shadow:
    0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-clair),
    0 0 0 max(2.2px, calc(2.5 * var(--u))) rgba(0, 0, 0, 0.75),
    0 0 calc(12 * var(--u)) rgba(var(--accent-rvb), 0.6);
}
:where(.pupitre, dialog) input[type="checkbox"]:checked::after { transform: rotate(42deg) scale(1); }
/* sous la souris (sur la case ou sur sa phrase) son cerclage s'éclaire ; sous le doigt elle s'enfonce */
:where(.pupitre, dialog) input[type="checkbox"]:hover:not(:disabled),
:where(.pupitre, dialog) label:hover > input[type="checkbox"]:not(:disabled) { filter: brightness(1.3); }
:where(.pupitre, dialog) input[type="checkbox"]:active:not(:disabled),
:where(.pupitre, dialog) label:active > input[type="checkbox"]:not(:disabled) { transform: scale(0.9); }
:where(.pupitre, dialog) input[type="checkbox"]:focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
:where(.pupitre, dialog) input[type="checkbox"]:disabled { cursor: default; filter: saturate(0.6); }

/* ---------- Onglets ---------- */
/* .onglets : un choix entre deux ou trois vues (« Connexion » / « Inscription ») ; chaque bouton est un .onglet */
.onglets, .legal-onglets {
  display: flex; gap: calc(3 * var(--u)); padding: calc(3 * var(--u));
  border-radius: calc(13 * var(--u));
  background: rgba(0, 0, 0, 0.5);
  box-shadow: inset 0 calc(2 * var(--u)) calc(5 * var(--u)) rgba(0, 0, 0, 0.85), 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-sombre), 0 0 0 max(2.2px, calc(2.5 * var(--u))) rgba(0, 0, 0, 0.75);
}
/* UN ONGLET FERMÉ SE TOUCHE : c'est une petite touche de verre, debout sur un pied
   court (section 5 bis). Il n'était qu'un mot posé dans la glissière : rien ne
   disait qu'on pouvait le toucher. L'onglet OUVERT est la touche enfoncée, en
   laiton, sans pied : on y est déjà, il ne répond plus (curseur en flèche). */
.onglet, .legal-onglets button {
  --pied: calc(2 * var(--u)); --course: calc(1.5 * var(--u));
  flex: 1; min-width: 0; min-height: var(--hauteur-bouton); padding: 0 calc(10 * var(--u));
  border: 0; border-radius: calc(10 * var(--u)); cursor: pointer;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.085), rgba(255, 255, 255, 0.02));
  box-shadow: inset 0 0 0 max(1px, calc(1.2 * var(--u))) rgba(var(--metal-clair-rvb), 0.55), var(--socle-verre);
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  font-size: var(--taille-bouton); color: var(--metal-vif); text-shadow: none;
  transition: transform 0.1s ease, filter 0.15s ease;
}
.onglet:hover, .legal-onglets button:hover { transform: none; filter: brightness(1.25); }
.onglet:active, .legal-onglets button:active { --pied: calc(0.5 * var(--u)); transform: translateY(var(--course)); filter: brightness(0.96); }
/* l'onglet ouvert : la classe .actif (ou aria-selected="true") */
.onglet[aria-selected="true"], .onglet.actif, .legal-onglets button.actif {
  font-weight: 900; color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.35);
  background: var(--laiton); cursor: default;
  box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.55), inset 0 calc(-2 * var(--u)) calc(3 * var(--u)) rgba(0, 0, 0, 0.25);
  transform: none; filter: none;
}
.onglet:focus-visible, .legal-onglets button:focus-visible { outline: var(--anneau-clavier); outline-offset: 2px; }

/* ---------- Liste ou tableau en verre ---------- */
/* .liste : une liste en verre simple, sur <ol> ou <ul> : classement, dernières parties, joueurs du salon.
   Elle peut défiler à l'intérieur (.defile) : c'est la seule zone qui en a le droit, la page jamais. */
.liste, #fin-classement, #stats-dernieres {
  list-style: none; margin: 0; padding: calc(5 * var(--u)) calc(6 * var(--u));
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  border-radius: calc(14 * var(--u));
  background: var(--verre-fond);
  box-shadow: var(--verre-anneau), 0 0 0 1px rgba(0, 0, 0, 0.75);
}
.liste.defile, #fin-classement, #stats-dernieres, #salon-joueurs { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--metal-sombre) transparent; }
/* .liste-ligne : une ligne ; dedans .liste-rang, .liste-nom, puis une ou plusieurs .liste-valeur */
.liste-ligne, #fin-classement > li, #stats-dernieres > li {
  display: flex; align-items: center; gap: calc(10 * var(--u)); flex: none;
  min-height: calc(40 * var(--u)); padding: calc(4 * var(--u)) calc(10 * var(--u));
  border-radius: calc(9 * var(--u));
  font-size: var(--taille-texte);
}
.liste-ligne + .liste-ligne, #fin-classement > li + li, #stats-dernieres > li + li { border-top: 1px solid rgba(var(--metal-clair-rvb), 0.18); }
.liste-rang {
  flex: none; display: grid; place-items: center;
  width: calc(27 * var(--u)); height: calc(27 * var(--u)); border-radius: 50%;
  font-family: var(--police-plateau); font-weight: 900; font-size: calc(13 * var(--u)); font-variant-numeric: lining-nums;
  color: var(--sur-metal);
  background: linear-gradient(160deg, var(--metal-vif), var(--metal-clair) 38%, var(--metal-sombre) 78%, var(--metal-creux));
  box-shadow: inset 0 -2px 3px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(14, 8, 2, 0.8);
}
.liste-nom { flex: 1; min-width: 0; font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.liste-valeur { flex: none; font-family: var(--police-plateau); font-weight: 700; font-variant-numeric: tabular-nums lining-nums; color: var(--metal-vif); white-space: nowrap; text-align: right; }
/* la ligne du joueur lui-même (dans le vrai jeu : li.moi) ; .est-eteinte : un joueur éliminé, une ligne passée */
.liste-ligne.est-moi, #fin-classement > li.moi {
  border-top-color: transparent;
  background: linear-gradient(90deg, rgba(var(--accent-rvb), 0.26), rgba(var(--accent-rvb), 0.07));
  box-shadow: inset 0 0 0 max(1px, calc(1.3 * var(--u))) rgba(var(--accent-rvb), 0.75);
  color: var(--accent-vif);
}
.liste-ligne.est-eteinte { opacity: 0.5; }

/* ---------- Tuiles de chiffres ---------- */
/* .tuiles : une grille de .tuile : un chiffre clé et son nom (dans le vrai jeu : .cartes > .carte > .valeur + .libelle) */
.tuiles, .cartes { display: grid; grid-template-columns: repeat(auto-fit, minmax(calc(96 * var(--u)), 1fr)); gap: var(--ecart-touches); align-self: stretch; }
.tuile, .carte {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(4 * var(--u));
  min-width: 0; padding: calc(10 * var(--u)) calc(8 * var(--u)); text-align: center;
  border-radius: calc(12 * var(--u));
  background: var(--verre-fond);
  box-shadow: var(--verre-anneau), 0 0 0 1px rgba(0, 0, 0, 0.75);
}
.tuile-valeur, .carte .valeur {
  font-family: var(--police-plateau); font-weight: 900; line-height: 1; font-variant-numeric: lining-nums;
  font-size: calc(var(--taille-titre) * 0.86); color: var(--accent);
  text-shadow: 0 0 calc(14 * var(--u)) rgba(var(--accent-rvb), 0.5);
}
.tuile-nom, .carte .libelle {
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: var(--taille-etiquette); line-height: 1.25; color: var(--metal-clair);
}

/* ---------- Bandeaux d'information ---------- */
/* .bandeau : une plaque d'information (dans .bandeaux, ou en tête d'une scène) ; dedans .bandeau-titre, un détail, .bandeau-action */
.bandeau, .bandeau-sans-enjeu, .bandeau-avec-impact {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: calc(2 * var(--u)) calc(10 * var(--u));
  flex: none; min-width: 0; padding: calc(5 * var(--u)) calc(14 * var(--u));
  border-radius: calc(14 * var(--u)); text-align: center;
  font-size: var(--taille-texte); line-height: 1.25; color: var(--texte);
  background: linear-gradient(180deg, rgba(var(--verre-haut), 0.95), rgba(var(--verre-bas), 0.97));
  box-shadow:
    inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-clair),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    0 calc(3 * var(--u)) calc(10 * var(--u)) rgba(0, 0, 0, 0.5),
    inset 0 calc(2.5 * var(--u)) 0 rgba(255, 255, 255, 0.08);
}
.bandeau-titre {
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.18em;
  font-size: max(11px, calc(12.5 * var(--u))); color: var(--accent);
}
/* .bandeau-suite : la fin d'une phrase, montrée seulement quand la place ne manque pas (ordinateur) */
.bandeau-suite { display: none; }
/* .bandeau-action : le petit bouton d'un bandeau (« Recharger ») */
.bandeau-action {
  flex: none; min-height: max(44px, calc(44 * var(--u))); min-width: max(44px, calc(44 * var(--u))); padding: 0 calc(14 * var(--u));
  border: 0; border-radius: 999px; cursor: pointer;
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.08em;
  font-size: var(--taille-bouton); color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.35);
  /* une petite touche de LAITON, sur un pied court (section 5 bis) : c'est le seul geste du bandeau,
     il ne se confond plus avec le verre du bandeau qui le porte */
  --pied: calc(2 * var(--u)); --course: calc(1.5 * var(--u));
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0) 48%), var(--laiton);
  box-shadow: 0 0 0 1px rgba(14, 8, 2, 0.92), var(--socle-laiton), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  transition: transform 0.1s ease, filter 0.15s ease;
}
.bandeau-action:hover { filter: brightness(1.1); }
.bandeau-action:active { --pied: calc(0.5 * var(--u)); transform: translateY(var(--course)); filter: brightness(0.96); }
.bandeau-action:focus-visible { outline: var(--anneau-clavier); outline-offset: 2px; }
/* .bandeau-alerte : la panne (« Signal perdu, reconnexion en cours… ») ; .bandeau-ok : le retour à la normale.
   Dans le vrai jeu : #bandeau-reseau, et sa classe .retabli ; la question à impact d'un partenaire. */
.bandeau-alerte, .bandeau-ok, #bandeau-reseau { font-weight: 700; }
.bandeau-alerte, #bandeau-reseau, .bandeau-avec-impact {
  color: var(--sur-alerte);
  background: linear-gradient(180deg, var(--alerte-claire), var(--alerte));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.85), 0 0 calc(16 * var(--u)) rgba(var(--alerte-rvb), 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.bandeau-ok, #bandeau-reseau.retabli, .bandeau-sans-enjeu {
  color: var(--sur-ok);
  background: linear-gradient(180deg, var(--ok-vif), var(--ok));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.85), 0 0 calc(16 * var(--u)) rgba(var(--ok-rvb), 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
/* le bouton « Quitter le tutoriel » est rangé avec les bandeaux */
.bandeaux > button { align-self: center; }

@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  /* dans le coin en haut à gauche, comme une mention de chaîne : la plaque est étroite, son contenu s'empile */
  .bandeaux .bandeau {
    flex-direction: column; flex-wrap: nowrap; align-items: flex-start; text-align: left; gap: calc(3 * var(--u));
    padding: calc(8 * var(--u)) calc(11 * var(--u)) calc(9 * var(--u)); border-radius: calc(12 * var(--u));
    font-size: max(12px, calc(13 * var(--u)));
  }
  .bandeaux .bandeau-titre { font-size: max(10px, calc(11 * var(--u))); letter-spacing: 0.08em; }
  .bandeau-suite { display: inline; }
  .bandeau-action { min-height: calc(30 * var(--u)); min-width: 0; font-size: max(11px, calc(12 * var(--u))); }
  .bandeaux .bandeau-action { margin-top: calc(3 * var(--u)); }
  .bandeaux > button { align-self: flex-start; padding-left: calc(12 * var(--u)); padding-right: calc(12 * var(--u)); font-size: max(11px, calc(13 * var(--u))); min-height: calc(40 * var(--u)); }
}

/* ---------- Voile et carte centrale ---------- */
/* .voile-pupitre : il assombrit le pupitre sous la barre du haut (pause, « partie suivie ailleurs »).
   (Pas « .voile » : app.js pose cette classe-là sur la vidéo d'un partenaire.) */
.voile-pupitre {
  position: absolute; z-index: 10;
  display: grid; place-items: center;
  padding: calc(14 * var(--u));
  background: rgba(var(--verre-bas), 0.86);
  -webkit-backdrop-filter: blur(9px) saturate(0.8);
  backdrop-filter: blur(9px) saturate(0.8);
}
/* .voile-carte : la carte posée au milieu du voile (avec .verre.rivete) */
.voile-carte {
  display: flex; flex-direction: column; align-items: center; gap: calc(12 * var(--u));
  width: min(100%, calc(520 * var(--u))); max-height: 100%; min-height: 0;
  padding: calc(26 * var(--u)) calc(22 * var(--u)) calc(22 * var(--u));
  text-align: center;
}
/* .voile-titre : le titre de la carte (dans le vrai jeu : .pause-titre, .ailleurs-titre) */
.voile-titre, .pause-titre, .ailleurs-titre {
  margin: 0; text-wrap: balance;
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.12em; line-height: 1.1;
  font-size: calc(var(--taille-titre) * 0.74); color: var(--accent);
  text-shadow: 0 0 calc(18 * var(--u)) rgba(var(--accent-rvb), 0.55);
}
/* le symbole de la pause : deux barres de laiton */
.pause-symbole {
  width: calc(34 * var(--u)); height: calc(40 * var(--u));
  background: linear-gradient(90deg, var(--metal-clair) 0 36%, transparent 36% 64%, var(--metal-clair) 64% 100%);
  border-radius: calc(3 * var(--u));
}
#pause-message:empty { display: none; }
@media (orientation: landscape) and (max-height: 560px) {
  .voile-carte { padding: calc(16 * var(--u)) calc(22 * var(--u)) calc(14 * var(--u)); gap: calc(8 * var(--u)); width: min(100%, calc(560 * var(--u))); }
  .pause-symbole { display: none; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .voile-pupitre {
    border-radius: calc(22 * var(--u));
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7), inset 0 0 0 max(1px, calc(1.2 * var(--u))) rgba(var(--metal-clair-rvb), 0.35);
  }
  .voile-carte { width: min(100%, calc(600 * var(--u))); padding: calc(34 * var(--u)) calc(44 * var(--u)) calc(30 * var(--u)); gap: calc(14 * var(--u)); }
}

/* ---------- Pastilles d'état ---------- */
/* .pastille : une pastille d'état, à compléter par -ok (qualifié), -alerte (éliminé), -neutre, -accent, -moi */
.pastille {
  display: inline-flex; align-items: center; gap: calc(7 * var(--u));
  padding: calc(4 * var(--u)) calc(12 * var(--u)) calc(4 * var(--u)) calc(10 * var(--u));
  border-radius: 999px; white-space: nowrap;
  font-family: var(--police-plateau); font-weight: 800; text-transform: uppercase; letter-spacing: 0.14em;
  font-size: var(--taille-pastille); line-height: 1.25;
  --pastille-rvb: var(--metal-clair-rvb);
  color: rgb(var(--pastille-rvb));
  background: linear-gradient(180deg, rgba(var(--verre-haut), 0.94), rgba(var(--verre-bas), 0.96));
  box-shadow:
    inset 0 0 0 max(1px, calc(1.3 * var(--u))) rgba(var(--pastille-rvb), 0.72),
    0 2px 8px rgba(0, 0, 0, 0.45);
}
/* le voyant de la pastille */
.pastille::before {
  content: ''; flex: none; width: calc(7 * var(--u)); height: calc(7 * var(--u)); border-radius: 50%;
  background: currentColor; box-shadow: 0 0 calc(6 * var(--u)) currentColor;
}
.pastille-ok { --pastille-rvb: var(--ok-rvb); }
.pastille-alerte { --pastille-rvb: var(--alerte-rvb); }
.pastille-accent { --pastille-rvb: var(--accent-rvb); }
.pastille-moi { --pastille-rvb: var(--moi-rvb); }
.pastille-neutre { --pastille-rvb: var(--metal-vif-rvb); }
/* .pastille-pleine : la pastille remplie de sa couleur, texte sombre (« Il fallait répondre ») */
.pastille-pleine { padding-left: calc(12 * var(--u)); color: var(--sur-metal); background: linear-gradient(180deg, var(--metal-vif), var(--metal-clair));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.8), 0 2px 8px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.45); }
.pastille-pleine::before { display: none; }
.pastille-pleine.pastille-ok { color: var(--sur-ok); background: linear-gradient(180deg, var(--ok-vif), var(--ok)); }
.pastille-pleine.pastille-alerte { color: var(--sur-alerte); background: linear-gradient(180deg, var(--alerte-claire), var(--alerte)); }
.pastille-pleine.pastille-accent { color: var(--sur-accent); background: linear-gradient(180deg, var(--accent-vif), var(--accent)); }
.pastille-pleine.pastille-moi { color: var(--sur-moi); background: linear-gradient(180deg, var(--moi-vif), var(--moi)); }

/* ---------- Barre de votes ---------- */
/* .barre-votes : la barre de progression d'un vote ; sa part se règle par style="--part: 42" (en pour cent).
   Dans le vrai jeu : .recap-barre > span (largeur posée par app.js). */
.barre-votes, .recap-barre {
  --part: 0;
  position: relative; display: block; flex: 1 1 calc(60 * var(--u)); min-width: calc(40 * var(--u));
  height: calc(9 * var(--u)); border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, 0.09);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(0, 0, 0, 0.55);
}
.barre-votes::before, .recap-barre > span {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--part) * 1%); border-radius: inherit;
  background: linear-gradient(90deg, var(--metal-sombre), var(--accent));
  box-shadow: 0 0 calc(8 * var(--u)) rgba(var(--accent-rvb), 0.6);
}
/* la barre de la réponse qu'il fallait donner */
.barre-votes.est-gagnante::before, .a-donner .recap-barre > span {
  background: linear-gradient(90deg, var(--ok-sombre), var(--ok));
  box-shadow: 0 0 calc(8 * var(--u)) rgba(var(--ok-rvb), 0.6);
}

/* ---------- Compte à rebours géant ---------- */
/* .rebours : le compte à rebours géant ; dedans un surtitre puis .rebours-chiffre ; .urgence le fait rougir */
.rebours, #salon-rebours { display: flex; flex-direction: column; align-items: center; gap: calc(6 * var(--u)); text-align: center; min-width: 0; }
.rebours-chiffre {
  font-family: var(--police-plateau); font-weight: 900; line-height: 0.95; letter-spacing: 0.03em;
  font-variant-numeric: tabular-nums lining-nums; white-space: nowrap;
  font-size: var(--taille-rebours); color: var(--accent-vif);
  text-shadow:
    0 0 calc(26 * var(--u)) rgba(var(--accent-rvb), 0.6),
    0 0 calc(6 * var(--u)) rgba(var(--accent-rvb), 0.7),
    0 calc(3 * var(--u)) 0 rgba(0, 0, 0, 0.7);
}
.rebours.urgent .rebours-chiffre, .rebours-chiffre.urgence {
  color: var(--alerte);
  text-shadow: 0 0 calc(26 * var(--u)) rgba(var(--alerte-rvb), 0.65), 0 calc(3 * var(--u)) 0 rgba(0, 0, 0, 0.7);
}

/* ---------- Couleurs des rangs (roue du professeur, lot du soir) ----------
   La palette d'une case de jeu, en variables --rang-… Sans couleur de rang : le
   verre noir et le métal du thème. Avec une couleur : les quatre métaux de
   rang. Ce sont des DONNÉES DU JEU (SPECS 7.1 : doré, violet, bleu et vert
   métallique), les mêmes sous tous les thèmes : avec les couleurs de sens, les
   seules couleurs écrites en dur hors du thème.
   Dans le vrai jeu, app.js pose .carte-rang-or, -violet, -bleu, -vert sur les
   cases de la roue, et .verdict-rang-… sur le jeu annoncé.
     --rang-vif, -clair, -creux, -sombre   le cerclage de la case, du plus clair au plus sombre
     --rang-haut, -coeur, -bas             le fond de la case, de haut en bas
     --rang-lueur, --rang-reflet           la lueur intérieure et le reflet qui passe
     --rang-titre, --rang-part             le titre du jeu et sa chance
     --rang-teinte, --rang-teinte-vive     la teinte de ce qui annonce le jeu autour de la case (verdict, repère) */
.rang, .rouleau-carte, .lot-verdict {
  --rang-vif: var(--metal-clair); --rang-clair: var(--metal-sombre); --rang-creux: var(--metal-pied); --rang-sombre: var(--metal-creux);
  --rang-haut: rgb(var(--verre-haut)); --rang-bas: rgb(var(--verre-bas)); --rang-coeur: rgb(var(--verre-milieu));
  --rang-lueur: rgba(255, 255, 255, 0.03); --rang-reflet: rgba(255, 255, 255, 0.05);
  --rang-titre: var(--texte); --rang-part: var(--texte-doux);
  --rang-teinte: var(--accent); --rang-teinte-vive: var(--accent-vif);
}
.rang-or, .carte-rang-or, .verdict-rang-or {
  --rang-vif: #f0dca8; --rang-clair: #d8b877; --rang-creux: #8d6a30; --rang-sombre: #a07b3a;
  --rang-haut: #5e4012; --rang-coeur: #46300f; --rang-bas: #2a1b08;
  --rang-lueur: rgba(255, 181, 69, 0.2); --rang-reflet: rgba(255, 244, 214, 0.16);
  --rang-titre: #fbd987; --rang-part: #f3dc9e;
  --rang-teinte: #ffb545; --rang-teinte-vive: #ffd76a;
}
.rang-violet, .carte-rang-violet, .verdict-rang-violet {
  --rang-vif: #ecdcff; --rang-clair: #b794f2; --rang-creux: #6a45b6; --rang-sombre: #8d68d8;
  --rang-haut: #4b3186; --rang-coeur: #2f1d5a; --rang-bas: #1b1036;
  --rang-lueur: rgba(168, 120, 255, 0.22); --rang-reflet: rgba(232, 214, 255, 0.12);
  --rang-titre: #f1e7ff; --rang-part: #e2d3fc;
  --rang-teinte: #a878ff; --rang-teinte-vive: #d6c0ff;
}
.rang-bleu, .carte-rang-bleu, .verdict-rang-bleu {
  --rang-vif: #dcebff; --rang-clair: #8fb8f2; --rang-creux: #3d6cb4; --rang-sombre: #5e92dc;
  --rang-haut: #1f477f; --rang-coeur: #142f59; --rang-bas: #0b1a36;
  --rang-lueur: rgba(96, 160, 255, 0.22); --rang-reflet: rgba(214, 232, 255, 0.12);
  --rang-titre: #e8f2ff; --rang-part: #d2e4fc;
  --rang-teinte: #60a0ff; --rang-teinte-vive: #b4d3ff;
}
.rang-vert, .carte-rang-vert, .verdict-rang-vert {
  --rang-vif: #d5ffea; --rang-clair: #7fdcb2; --rang-creux: #2c8a64; --rang-sombre: #4db58a;
  --rang-haut: #154c3b; --rang-coeur: #0e3529; --rang-bas: #071f18;
  --rang-lueur: rgba(70, 210, 150, 0.2); --rang-reflet: rgba(214, 255, 236, 0.1);
  --rang-titre: #e6fff3; --rang-part: #c8f2de;
  --rang-teinte: #46d296; --rang-teinte-vive: #a6ecca;
}

/* ---------- Rayons de lumière ----------
   Des rayons qui partent d'un point et tournent lentement (finale, couronnement).
   Décor pur. Dans le vrai jeu : l'élément .rayons-plein, premier enfant des
   écrans de l'annonce et de la fin. Réglages, à poser sur le calque :
     --rayons-x, --rayons-y   le centre, dans le calque (défaut : son milieu)
     --rayons-force           l'intensité des rayons, de 0 à 1 (défaut 0.18)
     --rayons-portee          jusqu'où ils portent (défaut 520 u)
     --rayons-halo            la lueur au centre, de 0 à 1 (défaut 0 : aucune)
     --rayons-tour            la durée d'un tour (défaut 45 s) */
.rayons, .rayons-plein { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; overflow: hidden; border-radius: inherit; pointer-events: none; }
.rayons::before, .rayons-plein::before {
  content: ''; position: absolute; left: var(--rayons-x, 50%); top: var(--rayons-y, 50%);
  width: calc(2800 * var(--u)); height: calc(2800 * var(--u)); margin: calc(-1400 * var(--u)) 0 0 calc(-1400 * var(--u));
  background: repeating-conic-gradient(from 0deg, rgba(var(--accent-rvb), var(--rayons-force, 0.18)) 0deg 8.5deg, transparent 8.5deg 24deg);
  -webkit-mask: radial-gradient(circle, #000 0, rgba(0, 0, 0, 0.6) calc(var(--rayons-portee, calc(520 * var(--u))) * 0.42), transparent var(--rayons-portee, calc(520 * var(--u))));
  mask: radial-gradient(circle, #000 0, rgba(0, 0, 0, 0.6) calc(var(--rayons-portee, calc(520 * var(--u))) * 0.42), transparent var(--rayons-portee, calc(520 * var(--u))));
  animation: rayons var(--rayons-tour, 45s) linear infinite;
}
.rayons::after, .rayons-plein::after {
  content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: radial-gradient(ellipse 60% 46% at var(--rayons-x, 50%) var(--rayons-y, 50%), rgba(var(--accent-rvb), var(--rayons-halo, 0)), transparent 72%);
}
@keyframes rayons { to { transform: rotate(360deg); } }
/* les rayons ne se montrent que là où le jeu les allume (finale, couronnement) : sections 13 */
.rayons-plein { display: none; }
/* le second calque de rayons de l'ancien plateau : jamais montré */
.fin-rayons { display: none; }

/* ---------- Pied de page ---------- */
/* .pied : les liens légaux (mentions, CGU, règlement, confidentialité), sur <nav> ; chaque lien est un <a> */
.pied { grid-area: pied; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 calc(2 * var(--u)); min-width: 0; z-index: 1; }
.pupitre .pied a {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: max(44px, calc(44 * var(--u))); min-width: 44px; padding: 0 calc(4 * var(--u));
  font-size: max(11px, calc(11.5 * var(--u))); color: var(--texte-doux);
  text-decoration: underline; text-decoration-color: rgba(var(--texte-doux-rvb), 0.45); text-underline-offset: 0.2em;
  text-shadow: 0 1px 3px #000, 0 0 8px #000; white-space: nowrap;
}
.pupitre .pied a:hover { color: var(--texte); }
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  /* dans le coin en bas à droite, sous les boutons : une petite colonne. Hauteur nulle, contenu qui remonte */
  .pied {
    flex-direction: column; flex-wrap: nowrap; align-items: center; justify-content: flex-end; gap: calc(1 * var(--u));
    height: 0; margin-bottom: calc(16 * var(--u));
  }
  .pupitre .pied a { flex: none; min-height: 0; min-width: 0; padding: calc(3 * var(--u)) calc(4 * var(--u)); font-size: max(10.5px, calc(11 * var(--u))); }
}


/* ============================================================================
   12 bis. LA HIÉRARCHIE D'UN ÉCRAN HORS PARTIE
   ----------------------------------------------------------------------------
   Retour de Gautier, le 2026-10-09, devant l'accueil sur son téléphone : « tous
   les textes et boutons se ressemblent et on ne sait pas où lire, rien n'est
   vraiment bien défini, on dirait un gros bloc de choses similaires. » Il avait
   raison : sept pièces de verre cerclées de laiton, de la même largeur, toutes
   en capitales Cinzel de la même taille ; l'information et l'action avaient la
   même tête. Les règles, écrites ici une fois, que les feuilles d'étape citent
   (SPECS 2.12, « La hiérarchie des écrans hors partie » ; gardé par
   test/pupitre-hierarchie.test.js) :
     1. UN HÉROS par écran (.heros) : le seul grand panneau cerclé, là où l'œil
        se pose d'abord. Ce qui va avec lui se lit DEDANS, sous le grand nombre
        ou le grand titre, en lettres courantes.
     2. UNE action principale par état (.action-principale) : la seule touche
        de LAITON, la seule en capitales Cinzel. Jamais deux laitons à égalité :
        dans sa boîte, le premier bouton montré est de laiton, tout bouton
        montré après lui est de verre.
     3. Les actions SECONDAIRES sont des TUILES (.actions-secondaires > .tuile-action) : une rangée
        compacte de touches égales, un pictogramme dessiné dans la feuille
        (--picto) et un libellé en lettres courantes. Elles se touchent (pied de
        laiton, enfoncement, anneau au clavier, 44 px au moins), mais pèsent
        bien moins que l'action principale.
     4. L'INFORMATION ne ressemble jamais à une action (.carnet > .ligne-info) :
        du texte posé à plat, un pictogramme à l'accent devant lui, ni cadre ni
        cerclage ni pied. Un lien dans la phrase reste souligné.
     5. La TYPOGRAPHIE fait le tri : Cinzel en capitales pour le héros et
        l'action principale seulement ; le reste en lettres courantes, à trois
        tailles franchement distinctes (le héros, le texte, la note).
     6. Les GROUPES se voient : héros, action principale, tuiles, carnet.
        L'écart entre deux groupes (--ecart-groupes) est nettement plus grand
        que l'écart entre deux pièces d'un groupe (--ecart-pieces). Un cadre de
        laiton par groupe au plus.
     7. Une ligne d'état (.ligne-etat) dit ce qui est déjà fait (« Notifications :
        activées ») : un pictogramme et un texte souligné, parce qu'elle ouvre
        encore quelque chose ; plus de touche.
   Ces classes sont posées dans la page d'essai (pupitre.html) sur les pièces du
   jeu ; .ligne-etat est posée par le décor (pupitre.js) d'après l'état lu.
   ========================================================================== */
:root {
  --ecart-groupes: calc(20 * var(--u));   /* entre deux groupes d'un écran hors partie */
  --ecart-pieces: calc(8 * var(--u));     /* entre deux pièces d'un même groupe */
  --tuile-picto: calc(22 * var(--u));     /* le pictogramme d'une tuile */
  --ligne-picto: calc(18 * var(--u));     /* celui d'une ligne du carnet ou d'une ligne d'état */
  /* Trois tailles de lettres courantes, de la plus forte à la plus discrète : la phrase du héros
     (--taille-texte, un peu agrandie), le libellé d'une tuile, une ligne du carnet. Sur téléphone
     aucune ne descend sous 16 px : c'est aussi la graisse et la couleur qui les distinguent. */
  --taille-tuile: max(16px, calc(15.2 * var(--u)));
  --taille-carnet: max(16px, calc(14.6 * var(--u)));
  /* le pictogramme d'une pièce qui n'a pas reçu le sien (--picto) : un point */
  --picto-point: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3C/svg%3E");
}
@media (orientation: landscape) and (max-height: 560px) {
  :root { --ecart-groupes: calc(10 * var(--u)); --ecart-pieces: calc(6 * var(--u)); --tuile-picto: calc(18 * var(--u)); --ligne-picto: calc(15 * var(--u)); }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  :root {
    --ecart-groupes: calc(26 * var(--u)); --ecart-pieces: calc(12 * var(--u)); --tuile-picto: calc(28 * var(--u)); --ligne-picto: calc(20 * var(--u));
    --taille-tuile: max(13.5px, calc(17 * var(--u))); --taille-carnet: max(12.5px, calc(15.5 * var(--u)));
  }
}

/* ---------- 1. Le héros ----------
   Le verre simple et son filet de laiton (il ne défile pas, mais il porte des
   pièces que le programme cache et montre : pas de pseudo-élément d'anneau),
   quatre rivets. Ses pièces s'empilent au milieu. */
.heros {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: calc(12 * var(--u)); min-width: 0;
  padding: calc(18 * var(--u)) calc(18 * var(--u)) calc(20 * var(--u));
  border-radius: calc(16 * var(--u)); text-align: center;
  background: var(--verre-fond);
  -webkit-backdrop-filter: var(--verre-flou); backdrop-filter: var(--verre-flou);
  box-shadow: var(--verre-anneau), 0 0 0 1px rgba(0, 0, 0, 0.75), 0 calc(6 * var(--u)) calc(14 * var(--u)) rgba(0, 0, 0, 0.5);
}
.heros::after {
  content: ''; position: absolute; top: calc(8 * var(--u)); right: calc(8 * var(--u)); bottom: calc(8 * var(--u)); left: calc(8 * var(--u));
  pointer-events: none;
  --rivet: radial-gradient(circle at 38% 34%, var(--metal-vif) 0 16%, var(--metal-clair) 32%, var(--metal-creux) 60%, rgba(0, 0, 0, 0.85) 70%, transparent 74%);
  background: var(--rivet) left top, var(--rivet) right top, var(--rivet) left bottom, var(--rivet) right bottom;
  background-size: calc(8 * var(--u)) calc(8 * var(--u)); background-repeat: no-repeat;
  opacity: 0.9;
}
/* ce qui se lit dans le héros, sous le grand nombre : des lettres courantes, bien lisibles */
.heros-texte {
  margin: 0; max-width: 36ch;
  font-family: var(--police-texte); font-weight: 400; font-style: normal; text-transform: none; letter-spacing: 0;
  font-size: calc(var(--taille-texte) * 1.06); line-height: 1.4; color: var(--texte);
  text-wrap: balance; overflow-wrap: anywhere;
}

/* ---------- 2. L'action principale ----------
   La boîte prend la largeur ; ses boutons s'empilent. Le premier bouton montré
   est LA touche de laiton de l'écran, en grand. Il l'est même si la page du jeu
   l'écrit « secondaire » (« Me prévenir quand le salon ouvre ») : c'est sa
   place dans la boîte qui décide, pas sa classe. (Le laiton et le verre sont
   redits ici tels que la section 12 les écrit : une classe ne peut pas en citer
   une autre.) */
.action-principale { display: flex; flex-direction: column; align-items: stretch; gap: var(--ecart-pieces); align-self: stretch; min-width: 0; }
.action-principale > button:not(.ligne-etat) {
  min-height: calc(var(--hauteur-bouton) * 1.22); padding-left: calc(20 * var(--u)); padding-right: calc(20 * var(--u));
  font-weight: 900; font-size: calc(var(--taille-bouton) * 1.12);
  color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);
  background: var(--laiton-touche);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  --pied: calc(5 * var(--u)); --lueur-laiton: 0.34;
  box-shadow: var(--ombre-laiton);
}
.action-principale > button:not(.ligne-etat):hover { --lueur-laiton: 0.66; }
.action-principale > button:not(.ligne-etat):active { --pied: calc(1 * var(--u)); --lueur-laiton: 0.18; }
/* JAMAIS DEUX LAITONS : tout bouton montré après un bouton montré est de verre, à la taille ordinaire, et en
   lettres courantes (les capitales Cinzel sont à l'action principale, à elle seule) */
.action-principale > button:not([hidden]):not(.ligne-etat) ~ button:not(.ligne-etat) {
  min-height: var(--hauteur-bouton);
  font-family: var(--police-texte); font-weight: 600; font-size: var(--taille-texte); letter-spacing: 0; text-transform: none;
  color: var(--texte); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  background: var(--verre-touche);
  -webkit-backdrop-filter: var(--verre-flou); backdrop-filter: var(--verre-flou);
  --lueur-verre: 0.08;
  box-shadow: var(--ombre-verre);
}
.action-principale > button:not([hidden]):not(.ligne-etat) ~ button:not(.ligne-etat):hover { --lueur-verre: 0.36; }

/* ---------- 7. La ligne d'état ----------
   Ce qui est déjà fait ne se présente plus comme une action : un pictogramme,
   et un texte souligné comme un lien, parce que la ligne ouvre encore sa
   fenêtre. 44 px à toucher, comme tout ce qui répond. */
button.ligne-etat {
  align-self: center; min-height: var(--hauteur-bouton); padding: 0 calc(10 * var(--u)); gap: calc(8 * var(--u));
  border-radius: calc(8 * var(--u));
  font-family: var(--police-texte); font-weight: 400; font-size: var(--taille-texte); letter-spacing: 0; text-transform: none;
  color: var(--accent-vif); text-shadow: 0 1px 2px #000, 0 0 calc(8 * var(--u)) rgba(0, 0, 0, 0.9);
  text-decoration: underline; text-underline-offset: 0.18em;
  background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
}
button.ligne-etat::before {
  content: ''; flex: none; width: var(--ligne-picto); height: var(--ligne-picto);
  background: currentColor;
  -webkit-mask: var(--picto, var(--picto-point)) center / contain no-repeat; mask: var(--picto, var(--picto-point)) center / contain no-repeat;
}
/* (les mêmes états que le lien d'une phrase : elle ne se soulève ni ne s'enfonce, elle n'a pas de pied) */
button.ligne-etat:hover { transform: none; filter: none; color: var(--texte); text-decoration-thickness: max(2px, 0.11em); }
button.ligne-etat:active { transform: none; filter: none; color: var(--accent); }

/* ---------- 3. Les tuiles ----------
   La rangée se partage entre les tuiles montrées, à parts égales ; elle passe
   à la ligne quand une tuile n'aurait plus sa largeur. Une tuile : son
   pictogramme à l'accent, puis son libellé, en lettres courantes, centré. Le
   verre, le cerclage clair et le pied de laiton d'une touche de verre (section
   5 bis) : elle se touche. */
.actions-secondaires { display: flex; flex-wrap: wrap; align-items: stretch; justify-content: center; gap: var(--ecart-pieces); align-self: stretch; min-width: 0; }
button.tuile-action {
  flex: 1 1 0; min-width: calc(96 * var(--u)); max-width: 100%;
  flex-direction: column; justify-content: flex-start; gap: calc(5 * var(--u));
  min-height: max(44px, calc(66 * var(--u))); padding: calc(9 * var(--u)) calc(6 * var(--u)) calc(8 * var(--u));
  border-radius: calc(12 * var(--u));
  font-family: var(--police-texte); font-weight: 500; font-size: var(--taille-tuile); letter-spacing: 0; text-transform: none; line-height: 1.16;
  color: var(--texte); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); text-wrap: balance; overflow-wrap: anywhere;
  --pied: calc(4 * var(--u)); --course: calc(2.5 * var(--u));
  background: var(--verre-touche);
  -webkit-backdrop-filter: var(--verre-flou); backdrop-filter: var(--verre-flou);
  --lueur-verre: 0.1;
  box-shadow: var(--ombre-verre);
}
/* le pictogramme luit à l'accent ; sous la souris, il s'éclaire avec le filet (une touche, pas une plaque) */
button.tuile-action::before {
  content: ''; flex: none; width: var(--tuile-picto); height: var(--tuile-picto);
  background: var(--accent);
  -webkit-mask: var(--picto, var(--picto-point)) center / contain no-repeat; mask: var(--picto, var(--picto-point)) center / contain no-repeat;
}
button.tuile-action:hover::before { background: var(--accent-vif); }
button.tuile-action:active { --pied: calc(1 * var(--u)); }
@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : la hauteur manque, le pictogramme passe à gauche du libellé */
  button.tuile-action { flex-direction: row; justify-content: center; align-items: center; gap: calc(8 * var(--u)); min-height: max(44px, calc(44 * var(--u))); padding: calc(4 * var(--u)) calc(10 * var(--u)); text-align: left; }
}

/* ---------- 4. Le carnet ----------
   Des lignes posées à plat, l'une sous l'autre. Chacune : un pictogramme à
   l'accent, sa phrase. Ni fond, ni cerclage, ni pied : rien ici ne se touche,
   sauf un lien souligné dans une phrase. L'ombre du texte le garde lisible sur
   le fond d'ambiance. */
.carnet { display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: calc(7 * var(--u)); align-self: stretch; min-width: 0; }
.ligne-info {
  position: relative; margin: 0; padding: 0 0 0 calc(var(--ligne-picto) + 9 * var(--u)); border-radius: 0;
  font-family: var(--police-texte); font-weight: 400; font-size: var(--taille-carnet); line-height: 1.34;
  color: var(--texte-doux); text-align: left; text-wrap: pretty; overflow-wrap: anywhere;
  text-shadow: 0 1px 2px #000, 0 0 calc(8 * var(--u)) rgba(0, 0, 0, 0.9);
  background: none; box-shadow: none;
}
.ligne-info::before {
  content: ''; position: absolute; left: 0; top: 0.08em; width: var(--ligne-picto); height: var(--ligne-picto);
  background: var(--accent);
  -webkit-mask: var(--picto, var(--picto-point)) center / contain no-repeat; mask: var(--picto, var(--picto-point)) center / contain no-repeat;
}


/* ============================================================================
   13. HABILLAGE DE BASE DES ÉCRANS
   ----------------------------------------------------------------------------
   Pour que TOUT soit utilisable dès l'étape 0. Chaque écran est, par défaut, un
   panneau de verre simple, centré, qui défile À L'INTÉRIEUR si son contenu est
   trop haut (jamais la page). La feuille de son étape le remplace par sa vraie
   mise en page, où plus rien ne défile.
   ========================================================================== */
.pupitre > .scene {
  position: relative; z-index: 1; isolation: isolate;
  align-items: center; justify-content: flex-start; text-align: center;
  padding: var(--marge-panneau);
  border-radius: calc(16 * var(--u));
  background: var(--verre-fond);
  -webkit-backdrop-filter: var(--verre-flou);
  backdrop-filter: var(--verre-flou);
  box-shadow: var(--verre-anneau), var(--verre-ombre);
  overflow-x: hidden; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--metal-sombre) transparent;
  overscroll-behavior: contain;
}
/* rien ne s'écrase dans un écran qui défile : chaque pièce garde sa hauteur */
.pupitre > .scene > * { flex: none; max-width: 100%; }
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  .pupitre > .scene { border-radius: calc(20 * var(--u)); gap: calc(12 * var(--u)); }
}

/* ---------- Un écran CENTRÉ ----------
   Son contenu se tient au milieu du panneau quand il tient, et part du HAUT
   quand il déborde : le panneau défile alors, et tout s'atteint. JAMAIS
   « justify-content: center » sur un écran : avec lui, ce qui dépasse en haut
   d'un panneau qui défile ne s'atteint plus (le compte à rebours du salon, la
   première ligne d'une question). Deux pièces vides, aux marges automatiques,
   font le centrage ; une marge automatique ne devient jamais négative.
   Centrés : l'accueil (pas ses formulaires), le salon, le rappel des règles, le
   tutoriel, le partenaire (pas sa vidéo), l'annonce, le lot, le couronnement
   seul. Les autres écrans partent du haut. */
#ecran-auth:not(.formulaire)::before, #ecran-salon::before, #ecran-regles::before, #ecran-tuto::before,
#ecran-sponsor:not(.video-integrale)::before, #ecran-annonce::before, #ecran-lot::before,
#ecran-fin.couronnement-seul::before { content: ''; margin-top: auto; }
#ecran-auth:not(.formulaire)::after, #ecran-salon::after, #ecran-regles::after, #ecran-tuto::after,
#ecran-sponsor:not(.video-integrale)::after, #ecran-annonce::after, #ecran-lot::after,
#ecran-fin.couronnement-seul::after { content: ''; margin-bottom: auto; }

/* ---------- La question (#ecran-jeu) : le panneau de la question, puis les touches ---------- */
#ecran-jeu.scene {
  padding: 0; border-radius: 0; background: none; box-shadow: none; overflow: visible;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  align-items: stretch;
}
#ecran-jeu.scene > .scene-a { flex: 1 1 0; }
@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : la question à gauche, les réponses à droite */
  #ecran-jeu.scene { display: grid; grid-template-columns: minmax(0, 1.04fr) minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); column-gap: var(--ecart-colonnes); }
  #ecran-jeu.scene > .bandeau { grid-column: 1 / -1; }
  #ecran-jeu.scene > .scene-a { grid-column: 1; grid-row: 2; }
  #ecran-jeu.scene > .scene-b { grid-column: 2; grid-row: 2; align-self: center; }
}
/* pendant une question, sur téléphone, la bulle ne prend que deux lignes : la place va aux réponses */
body[data-ecran="jeu"] .bulle { --bulle-lignes: 2; }

/* ---------- Les résultats d'une manche (#ecran-resultats) ---------- */
#recap-verdict {
  font-family: var(--police-plateau); font-weight: 900; letter-spacing: 0.04em; line-height: 1.14; text-wrap: balance;
  font-size: max(16px, calc(20 * var(--u))); color: var(--accent-vif); text-shadow: 0 2px 0 rgba(0, 0, 0, 0.6);
}
#recap-verdict.ok { color: var(--ok); text-shadow: 0 0 calc(18 * var(--u)) rgba(var(--ok-rvb), 0.5), 0 2px 0 rgba(0, 0, 0, 0.6); }
#recap-verdict.perte { color: var(--alerte); text-shadow: 0 0 calc(18 * var(--u)) rgba(var(--alerte-rvb), 0.5), 0 2px 0 rgba(0, 0, 0, 0.6); }
/* les cœurs sont dans le cadran des vies : la ligne de l'ancien écran n'est plus montrée */
#recap-vies { display: none; }
#recap-reponses, #sponsor-recap { display: flex; flex-direction: column; gap: calc(7 * var(--u)); align-self: stretch; min-width: 0; }
/* une ligne de résultat, fabriquée par app.js (ligneRecap) : lettre, texte, plaques, barre, mention, pourcentage */
.recap-ligne {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  column-gap: calc(12 * var(--u)); padding: calc(7 * var(--u)) calc(12 * var(--u));
  border-radius: calc(13 * var(--u)); text-align: left;
  background: var(--verre-fond);
  box-shadow: inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-sombre), 0 0 0 1px rgba(0, 0, 0, 0.75);
}
.recap-lettre {
  display: grid; place-items: center;
  width: var(--pastille-touche); height: var(--pastille-touche); border-radius: 50%;
  font-family: var(--police-plateau); font-weight: 900; font-size: calc(var(--pastille-touche) * 0.52);
  color: var(--sur-metal); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
  /* la médaille des réponses de la question (section 10) */
  background:
    radial-gradient(circle at 38% 28%, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 42%),
    linear-gradient(175deg, var(--metal-vif) 0%, var(--accent-vif) 30%, var(--accent) 66%, var(--accent-sombre) 100%);
  box-shadow: inset 0 0 0 max(1px, calc(1.5 * var(--u))) rgba(255, 236, 190, 0.45), inset 0 calc(-2 * var(--u)) calc(4 * var(--u)) rgba(70, 30, 0, 0.4), 0 0 0 1px rgba(14, 8, 2, 0.85), 0 calc(2 * var(--u)) calc(5 * var(--u)) rgba(0, 0, 0, 0.6);
}
.recap-texte {
  min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: calc(3 * var(--u)) calc(8 * var(--u));
  font-family: var(--police-texte); font-weight: 700; letter-spacing: 0.005em; line-height: 1.18; overflow-wrap: anywhere;
  font-size: var(--taille-reponse);
}
.recap-badges { display: inline-flex; flex-wrap: wrap; gap: calc(4 * var(--u)); }
.recap-badges:empty { display: none; }
.recap-pied { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: calc(4 * var(--u)) calc(8 * var(--u)); min-width: 0; }
/* les plaques écrites : « IL FALLAIT RÉPONDRE » (vert, jamais la couleur seule) et « TA RÉPONSE » (bleu) */
.recap-badge {
  display: inline-flex; align-items: center; padding: calc(3 * var(--u)) calc(9 * var(--u)); border-radius: 999px; white-space: nowrap;
  font-family: var(--police-plateau); font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em;
  font-size: var(--taille-pastille); line-height: 1.25;
}
.recap-badge.fallait { color: var(--sur-ok); background: linear-gradient(180deg, var(--ok-vif), var(--ok)); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.8); }
.recap-badge.moi { color: var(--moi-vif); background: rgba(var(--moi-rvb), 0.16); box-shadow: inset 0 0 0 max(1px, calc(1.3 * var(--u))) rgba(var(--moi-rvb), 0.8); }
.recap-mention { font-family: var(--police-texte); font-style: italic; font-weight: 400; letter-spacing: 0; font-size: var(--taille-note); line-height: 1.22; color: var(--texte-doux); }
.recap-pct { font-family: var(--police-plateau); font-weight: 900; font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; font-size: max(16px, calc(var(--taille-reponse) * 1.1)); }
/* la réponse qu'il fallait donner (cadre et lueur « ok ») ; celle du joueur ; les autres, en retrait */
.recap-ligne.a-donner {
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 24%),
    linear-gradient(180deg, rgba(var(--ok-rvb), 0.24), rgba(var(--ok-rvb), 0.11)),
    linear-gradient(180deg, rgb(var(--verre-haut)), rgb(var(--verre-bas)));
  box-shadow: 0 0 0 max(1.5px, calc(2 * var(--u))) var(--ok), 0 0 calc(22 * var(--u)) rgba(var(--ok-rvb), 0.42), inset 0 0 calc(22 * var(--u)) rgba(var(--ok-rvb), 0.18);
}
.recap-ligne.mienne { outline: max(1.5px, calc(2 * var(--u))) solid var(--moi); outline-offset: calc(2 * var(--u)); }
.recap-ligne.en-retrait .recap-texte, .recap-ligne.en-retrait .recap-pct, .recap-ligne.en-retrait .recap-lettre { opacity: 0.6; }
/* La foule a répondu à côté (manche à la majorité, 2026-10-16) : la bonne
   réponse reste en retrait (ce n'est pas elle qui qualifiait, la plaque « IL
   FALLAIT RÉPONDRE » garde la vedette), mais elle se lit : son texte moins
   pâli, sa mention droite, grasse et claire, au lieu d'un italique gris. */
.recap-ligne.vraie-oubliee.en-retrait .recap-texte { opacity: 0.88; }
.recap-ligne.vraie-oubliee .recap-mention { font-style: normal; font-weight: 700; color: var(--texte); }

/* ---------- L'annonce d'une manche, et de la finale (#ecran-annonce) ---------- */
.annonce-manche { font-size: calc(var(--taille-titre) * 1.25); }
.annonce-difficulte, .annonce-joueurs { font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.06em; font-size: calc(var(--taille-texte) * 1.1); color: var(--texte); }
.annonce-difficulte { color: var(--accent); }
.annonce-mode { font-family: var(--police-plateau); font-weight: 900; letter-spacing: 0.04em; color: var(--accent-vif); font-size: var(--taille-texte); text-wrap: balance; }
.annonce-lot { font-size: var(--taille-note); color: var(--texte-doux); overflow-wrap: anywhere; }
/* la FINALE : les rayons s'étalent sur toute la scène, le titre grossit */
#ecran-annonce.annonce-finale .rayons-plein { display: block; --rayons-force: 0.22; --rayons-halo: 0.16; }
#ecran-annonce.annonce-finale .annonce-manche { font-size: calc(var(--taille-titre) * 1.55); color: var(--accent-vif); }

/* ---------- Le rappel des règles (#ecran-regles) ---------- */
.regles-visuel { display: flex; align-items: flex-end; justify-content: center; min-height: calc(110 * var(--u)); padding-top: calc(26 * var(--u)); margin-bottom: calc(22 * var(--u)); }
.regles-resume { max-width: calc(600 * var(--u)); font-size: calc(var(--taille-texte) * 1.1); line-height: 1.4; text-wrap: balance; transition: opacity 0.4s ease; }
/* la ligne de résumé n'apparaît qu'une fois la réplique du professeur finie (app.js) : elle garde sa place */
.regles-resume.regles-resume-attente { opacity: 0; }
.regles-points { font-family: var(--police-plateau); font-size: var(--taille-surtitre); letter-spacing: 0.2em; font-variant-numeric: tabular-nums; color: var(--texte-doux); }
/* visuel « la majorité gagne » : quatre barres, celle de la foule allumée */
.rv-barres { display: flex; align-items: flex-end; gap: calc(16 * var(--u)); height: calc(100 * var(--u)); }
.rv-barre {
  position: relative; width: calc(46 * var(--u)); height: var(--h); border-radius: calc(7 * var(--u)) calc(7 * var(--u)) 0 0;
  background: linear-gradient(180deg, rgba(var(--metal-clair-rvb), 0.4), rgba(var(--metal-clair-rvb), 0.14));
}
.rv-barre b { position: absolute; bottom: calc(-22 * var(--u)); left: 0; right: 0; font-family: var(--police-plateau); font-weight: 900; font-size: var(--taille-plaque); color: var(--texte-doux); }
.rv-barre.rv-foule { background: linear-gradient(180deg, var(--accent-vif), var(--accent) 40%, var(--accent-sombre)); box-shadow: 0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), 0.45); }
.rv-barre.rv-foule em { position: absolute; top: calc(-24 * var(--u)); left: 50%; transform: translateX(-50%); font-style: normal; white-space: nowrap; font-family: var(--police-plateau); font-weight: 900; font-size: var(--taille-plaque); letter-spacing: 0.05em; color: var(--accent); }
/* visuel « chrono » : le nombre, et une jauge */
.rv-chrono { font-family: var(--police-plateau); font-weight: 900; font-size: calc(var(--taille-titre) * 1.8); line-height: 1; color: var(--accent); text-shadow: 0 0 calc(26 * var(--u)) rgba(var(--accent-rvb), 0.4); }
.rv-jauge { width: min(100%, calc(280 * var(--u))); height: calc(10 * var(--u)); margin-top: calc(10 * var(--u)); border-radius: 999px; overflow: hidden; background: rgba(255, 255, 255, 0.09); }
.rv-jauge span { display: block; height: 100%; width: 62%; border-radius: 999px; background: linear-gradient(90deg, var(--alerte), var(--accent) 45%, var(--ok)); }
.regles-visuel > .rv-chrono, .regles-visuel > .rv-jauge { align-self: center; }
#regles-visuel { flex-wrap: wrap; align-content: flex-end; }
#regles-visuel > .rv-jauge { flex-basis: 100%; max-width: calc(280 * var(--u)); }
/* le trophée, en laiton (dessin repris du jeu : image en data:, permise par la politique de sécurité) */
.fin-trophee, .tuto-trophee, .rv-trophee {
  width: calc(96 * var(--u)); height: calc(96 * var(--u)); margin: 0 auto;
  background: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23fff2c4'/%3E%3Cstop offset='.45' stop-color='%23e6b964'/%3E%3Cstop offset='1' stop-color='%239a6a28'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='none' stroke='url(%23g)' stroke-width='4' stroke-linecap='round' d='M20 13h-7c0 8 3 12 8 13M44 13h7c0 8-3 12-8 13'/%3E%3Cpath fill='url(%23g)' d='M19 7h26v14c0 10-5 16-13 17-8-1-13-7-13-17z'/%3E%3Crect fill='url(%23g)' x='29' y='37' width='6' height='9'/%3E%3Cpath fill='url(%23g)' d='M23 46h18l2 6H21z'/%3E%3Crect fill='url(%23g)' x='18' y='52' width='28' height='5' rx='1.5'/%3E%3Cpath fill='%23fff8e0' opacity='.45' d='M24 10h4v12c0 4 1 7 3 9-4-1-7-5-7-11z'/%3E%3C/svg%3E");
  filter: drop-shadow(0 0 calc(18 * var(--u)) rgba(var(--accent-rvb), 0.5));
}

/* ---------- La roue du professeur (#ecran-roue), et ce que l'écran du lot partage avec elle ---------- */
.lot-consigne { max-width: calc(560 * var(--u)); color: var(--texte-doux); font-size: var(--taille-note); text-wrap: balance; }
.lot-consigne:empty { display: none; }
/* LA GÉOMÉTRIE DE LA ROUE EST CONTRACTUELLE : app.js lit la hauteur d'une case
   (offsetHeight) et déplace la bande de « index x hauteur ». Toutes les cases
   ont donc la MÊME hauteur, en pixels ENTIERS (--roue-case, tenue par
   pupitre.js), sans marge ni écart entre elles ; la fenêtre en montre trois, et
   la case tirée s'arrête sous le repère, au milieu. */
.rouleau { position: relative; width: min(100%, calc(420 * var(--u))); }
.rouleau-fenetre {
  height: calc(3 * var(--roue-case)); overflow: hidden; border-radius: calc(13 * var(--u));
  background: rgba(var(--verre-bas), 0.7);
  box-shadow: var(--verre-anneau), inset 0 calc(14 * var(--u)) calc(22 * var(--u)) calc(-10 * var(--u)) #000, inset 0 calc(-14 * var(--u)) calc(22 * var(--u)) calc(-10 * var(--u)) #000;
}
.rouleau-carte {
  position: relative; overflow: hidden; height: var(--roue-case);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(1 * var(--u));
  padding: 0 calc(14 * var(--u));
  border-bottom: 1px solid rgba(var(--metal-clair-rvb), 0.18);
  background: linear-gradient(180deg, var(--rang-haut), var(--rang-coeur) 55%, var(--rang-bas));
  box-shadow: inset 0 0 calc(18 * var(--u)) var(--rang-lueur);
}
.rouleau-carte.carte-rang { box-shadow: inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--rang-clair), inset 0 0 calc(18 * var(--u)) var(--rang-lueur); }
.carte-label {
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  font-size: max(14px, calc(16 * var(--u))); line-height: 1.15; color: var(--rang-titre);
}
.carte-pourcent { font-size: max(11px, calc(12 * var(--u))); line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--rang-part); }
/* le repère : la case du milieu, cerclée */
.rouleau-repere {
  position: absolute; left: calc(-4 * var(--u)); right: calc(-4 * var(--u)); top: var(--roue-case); height: var(--roue-case); pointer-events: none;
  border-radius: calc(9 * var(--u));
  box-shadow: 0 0 0 max(2px, calc(2.5 * var(--u))) var(--accent), 0 0 calc(18 * var(--u)) rgba(var(--accent-rvb), 0.5);
}
/* l'écran de la roue se resserre un peu, pour montrer le jeu annoncé et le lien de ses preuves sans défiler */
#ecran-roue.scene { gap: calc(8 * var(--u)); padding-top: calc(14 * var(--u)); padding-bottom: calc(12 * var(--u)); }
.rouleau-carte.carte-gagnante { animation: carte-gagnante 0.9s ease-in-out 3; }
@keyframes carte-gagnante { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.45); } }
/* le jeu annoncé (roue), « GAGNÉ : … », « LOT NON RÉCLAMÉ », « AUCUN JEU TIRÉ » (lot) */
.lot-verdict {
  font-family: var(--police-plateau); font-weight: 900; letter-spacing: 0.04em; line-height: 1.1; text-wrap: balance; overflow-wrap: anywhere;
  font-size: calc(var(--taille-titre) * 0.8); color: var(--texte-doux);
}
.lot-verdict:empty { display: none; }
.lot-verdict.lot-gagne { color: var(--rang-teinte-vive); text-shadow: 0 0 calc(20 * var(--u)) var(--rang-teinte), 0 2px 0 rgba(0, 0, 0, 0.6); }
.lot-verdict.lot-perdu { color: var(--alerte); }
.roue-engagement { font-size: var(--taille-note); color: var(--texte-doux); text-wrap: balance; overflow-wrap: anywhere; }
/* les preuves du tirage : repliées, elles se déplient ; longues, elles défilent dans leur carte */
.lot-preuve { align-self: stretch; text-align: left; }
.lot-preuve > summary, #zone-suppression > summary {
  display: flex; align-items: center; justify-content: center; min-height: var(--hauteur-bouton); cursor: pointer;
  font-size: var(--taille-texte); color: var(--accent-vif); text-decoration: underline; text-underline-offset: 0.18em;
}
/* une ligne à déplier : les états d'un lien (sous la souris, sous le doigt), et un CHEVRON
   dessiné qui dit le sens : vers le bas, repliée ; vers le haut, dépliée */
.lot-preuve > summary { gap: calc(8 * var(--u)); list-style: none; }
.lot-preuve > summary::-webkit-details-marker { display: none; }
.lot-preuve > summary:hover { color: var(--texte); text-decoration-thickness: max(2px, 0.11em); }
.lot-preuve > summary:active { color: var(--accent); }
.lot-preuve > summary::after {
  content: ''; flex: none; width: calc(7 * var(--u)); height: calc(7 * var(--u)); margin-top: calc(-4 * var(--u));
  border: solid currentColor; border-width: 0 max(1.5px, calc(2 * var(--u))) max(1.5px, calc(2 * var(--u))) 0;
  transform: rotate(45deg);
}
.lot-preuve[open] > summary::after { margin-top: calc(4 * var(--u)); transform: rotate(-135deg); }
.lot-preuve > div {
  display: flex; flex-direction: column; gap: calc(6 * var(--u));
  max-height: calc(260 * var(--u)); overflow-y: auto; padding: calc(10 * var(--u)) calc(12 * var(--u));
  border-radius: calc(12 * var(--u)); background: rgba(var(--verre-bas), 0.7); box-shadow: var(--verre-anneau);
  font-size: var(--taille-note);
}
.preuve-ligne { display: flex; flex-direction: column; gap: calc(1 * var(--u)); }
.preuve-cle { color: var(--metal-clair); font-weight: 700; }
.preuve-valeur { overflow-wrap: anywhere; color: var(--texte); }
.preuve-verdict { color: var(--texte); overflow-wrap: anywhere; }
.preuve-verdict.preuve-ok { color: var(--ok); }
.preuve-verdict.preuve-ko { color: var(--alerte); font-weight: 700; }
.preuve-verdict.preuve-reserve { color: var(--accent-vif); }

/* ---------- La fin de partie (#ecran-fin) ---------- */
#ecran-fin .rayons-plein { display: block; --rayons-y: 22%; --rayons-force: 0.2; --rayons-halo: 0.14; }
.fin-gagnant { color: var(--accent-vif); }
#fin-titre { font-family: var(--police-plateau); font-weight: 700; text-transform: none; letter-spacing: 0.03em; font-size: calc(var(--taille-texte) * 1.15); color: var(--texte); text-shadow: none; }
.fin-lot { font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.03em; color: var(--accent); overflow-wrap: anywhere; }
.fin-lot.fin-sans-lot { font-family: var(--police-texte); font-weight: 400; letter-spacing: 0; color: var(--texte-doux); }
#fin-detail, #fin-prochaine { font-size: var(--taille-note); color: var(--texte-doux); text-wrap: balance; }
#fin-classement { align-self: stretch; max-height: calc(240 * var(--u)); list-style: decimal inside; }
#fin-classement > li { display: list-item; font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.02em; text-align: left; line-height: calc(32 * var(--u)); overflow-wrap: anywhere; }
/* le couronnement, d'abord seul : le gagnant, centré ; puis le classement (app.js retire la classe) */
#ecran-fin.couronnement-seul #fin-detail,
#ecran-fin.couronnement-seul h3,
#ecran-fin.couronnement-seul #fin-classement,
#ecran-fin.couronnement-seul #fin-prochaine,
#ecran-fin.couronnement-seul #btn-partager { display: none; }
#ecran-fin.couronnement-seul .fin-gagnant { font-size: calc(var(--taille-titre) * 1.3); }
#ecran-fin:not(.couronnement-seul) .fin-trophee { width: calc(52 * var(--u)); height: calc(52 * var(--u)); }

/* ---------- La remise du lot (#ecran-lot) ---------- */
.salon-lot {
  display: flex; flex-direction: column; align-items: center; gap: calc(2 * var(--u));
  padding: calc(8 * var(--u)) calc(16 * var(--u)); border-radius: calc(12 * var(--u));
  background: rgba(var(--verre-bas), 0.6); box-shadow: inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-clair);
}
.salon-lot-label { font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; font-size: var(--taille-etiquette); color: var(--metal-clair); }
.salon-lot-titre { font-family: var(--police-plateau); font-weight: 900; letter-spacing: 0.03em; font-size: calc(var(--taille-texte) * 1.15); color: var(--accent-vif); overflow-wrap: anywhere; }
/* la case « Je certifie avoir 18 ans ou plus » : grosse, facile à toucher, jamais couverte */
.lot-majeur { align-self: stretch; padding: calc(10 * var(--u)) calc(14 * var(--u)); border-radius: calc(12 * var(--u)); background: rgba(var(--accent-rvb), 0.1); box-shadow: inset 0 0 0 max(1.5px, calc(2 * var(--u))) var(--accent); }
.lot-majeur input[type="checkbox"] { width: calc(34 * var(--u)); height: calc(34 * var(--u)); }
.lot-rebours { font-family: var(--police-plateau); font-weight: 900; font-variant-numeric: tabular-nums lining-nums; font-size: calc(var(--taille-titre) * 0.7); color: var(--accent-vif); }
.lot-rebours.urgence { color: var(--alerte); }

/* ---------- Connexion et inscription (#ecran-auth) ---------- */
/* Deux temps : l'ACCUEIL (titre, une phrase, les grands boutons), puis le seul
   FORMULAIRE choisi. La classe .formulaire, posée par app.js, bascule de l'un à
   l'autre ; .reseau : « Termine ton inscription », le formulaire seul. */
#ecran-auth:not(.formulaire) .onglets,
#ecran-auth:not(.formulaire) form,
#ecran-auth:not(.formulaire) .auth-barre { display: none !important; }
#ecran-auth.formulaire .auth-accueil,
#ecran-auth.formulaire .auth-portes,
#ecran-auth.formulaire .btn-essayer,
#ecran-auth.formulaire .auth-sous-titre,
#ecran-auth.formulaire .slogan,
#ecran-auth.formulaire #reseaux-accueil,
#ecran-auth.formulaire #reseaux-note { display: none !important; }
#ecran-auth.reseau .auth-barre,
#ecran-auth.reseau .onglets,
#ecran-auth.reseau .auth-titre { display: none !important; }
.slogan { font-style: italic; color: var(--texte-doux); font-size: var(--taille-note); text-wrap: balance; }
.auth-sous-titre { max-width: calc(520 * var(--u)); }
.auth-accueil { align-self: stretch; }
.auth-accueil > button { flex: 1 1 calc(200 * var(--u)); }
.auth-barre { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: calc(8 * var(--u)); align-self: stretch; }
#ecran-auth .onglets, #ecran-auth form { align-self: stretch; }
:where(.pupitre, dialog) form { display: flex; flex-direction: column; gap: calc(12 * var(--u)); min-width: 0; width: 100%; max-width: calc(520 * var(--u)); margin-left: auto; margin-right: auto; }
.reseau-titre { font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.06em; font-size: calc(var(--taille-titre) * 0.7); color: var(--accent); text-align: center; }
/* les boutons de connexion par un réseau social (fabriqués par app.js) */
.reseaux { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: calc(8 * var(--u)); }
.reseaux-legende { flex-basis: 100%; font-size: var(--taille-note); color: var(--texte-doux); }
#reseaux-formulaire .reseaux-legende { flex-basis: auto; }
.reseau-bouton {
  display: inline-flex; align-items: center; gap: calc(8 * var(--u)); min-height: var(--hauteur-bouton); padding: 0 calc(14 * var(--u));
  border-radius: calc(12 * var(--u)); text-decoration: none; cursor: pointer;
  font-weight: 700; font-size: var(--taille-texte); color: var(--texte);
  background: rgba(var(--verre-bas), 0.9); box-shadow: inset 0 0 0 max(1.2px, calc(1.5 * var(--u))) var(--metal-sombre), 0 0 0 1px rgba(0, 0, 0, 0.8);
}
.pupitre a.reseau-bouton { color: var(--texte); text-decoration: none; }
.reseau-bouton svg { width: calc(22 * var(--u)); height: calc(22 * var(--u)); flex: none; }
.reseau-bouton.en-cours { pointer-events: none; opacity: 0.6; }
#reseaux-formulaire .reseau-bouton { padding: 0; width: var(--hauteur-bouton); justify-content: center; }
#reseaux-formulaire .reseau-nom { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* la réponse du serveur à un formulaire (app.js lui donne la classe .erreur ou .succes) */
#auth-message { align-self: stretch; padding: calc(10 * var(--u)) calc(14 * var(--u)); border-radius: calc(12 * var(--u)); font-size: var(--taille-texte); overflow-wrap: anywhere; }
#auth-message.erreur { color: var(--sur-alerte); background: linear-gradient(180deg, var(--alerte-claire), var(--alerte)); font-weight: 700; }
#auth-message.succes { color: var(--sur-ok); background: linear-gradient(180deg, var(--ok-vif), var(--ok)); font-weight: 700; }
.pupitre #auth-message a { color: inherit; }

/* ---------- Accueil et salon (#ecran-salon) ---------- */
.compteur { font-family: var(--police-plateau); font-weight: 700; letter-spacing: 0.04em; color: var(--metal-vif); }
#salon-entree, #salon-infos, #salon-attente { display: flex; flex-direction: column; align-items: center; gap: calc(10 * var(--u)); align-self: stretch; min-width: 0; }
#salon-invite { max-width: calc(560 * var(--u)); text-wrap: balance; overflow-wrap: anywhere; }
#salon-invite:empty { display: none; }
#salon-nb-joueurs { font-family: var(--police-plateau); font-weight: 700; color: var(--metal-vif); }
#salon-nb-joueurs:empty { display: none; }
#salon-joueurs {
  list-style: none; margin: 0; padding: calc(4 * var(--u)); align-self: stretch;
  display: flex; flex-wrap: wrap; justify-content: center; gap: calc(6 * var(--u)); max-height: calc(170 * var(--u));
}
#salon-joueurs:empty { display: none; }
#salon-joueurs > li {
  padding: calc(4 * var(--u)) calc(11 * var(--u)); border-radius: 999px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--taille-texte); background: rgba(var(--verre-bas), 0.75); box-shadow: inset 0 0 0 1px rgba(var(--metal-clair-rvb), 0.4);
}
#salon-joueurs > li.badge-admin { color: var(--accent); box-shadow: inset 0 0 0 max(1px, calc(1.3 * var(--u))) var(--accent); }
.salon-gagnants { font-size: var(--taille-note); color: var(--texte-doux); text-wrap: balance; overflow-wrap: anywhere; }
#btn-notifications.notifications-actives { color: var(--ok); }

/* ---------- Mes statistiques (#ecran-stats), mon profil (#ecran-profil) ---------- */
#stats-dernieres { align-self: stretch; text-align: left; }
#ecran-profil form { align-self: stretch; }
/* la suppression du compte : bien séparée du reste */
#zone-suppression { align-self: stretch; padding-top: calc(6 * var(--u)); border-top: 1px solid rgba(var(--metal-clair-rvb), 0.25); display: flex; flex-direction: column; gap: calc(10 * var(--u)); }
#zone-suppression > summary { color: var(--alerte); }
#zone-suppression[open] > :not(summary) { margin-top: calc(10 * var(--u)); }

/* ---------- Le tutoriel (#ecran-tuto) ---------- */
#ecran-tuto.scene { transition: opacity 0.3s ease; }
#tuto-illustration { display: flex; flex-direction: column; align-items: center; gap: calc(12 * var(--u)); font-size: calc(var(--taille-texte) * 1.05); }
#tuto-illustration:empty { display: none; }
.regles-liste { margin: 0; padding-left: 1.2em; text-align: left; display: flex; flex-direction: column; gap: calc(6 * var(--u)); }
.tuto-vies { font-size: calc(var(--taille-titre) * 1.3); line-height: 1; letter-spacing: 0.12em; color: var(--vie); filter: drop-shadow(0 0 calc(12 * var(--u)) rgba(var(--vie-rvb), 0.5)); }
.tuto-vies.nombreuses { font-size: var(--taille-titre); }
/* l'écran « éteint » : le professeur parle, l'écran se met en veilleuse (tutoriel.js) */
#ecran-tuto.eteint { opacity: 0.45; }
#ecran-tuto.eteint::after { content: 'Écoutez le professeur'; font-size: var(--taille-note); color: var(--texte-doux); }
/* « Continuer » (fabriqué par tutoriel.js, dernier enfant de la page) : à la
   place de la bulle du professeur, qui s'est tu. Tout l'écran avance aussi. */
#tuto-continuer { grid-area: bas; align-self: center; justify-self: end; z-index: 4; margin-bottom: calc(10 * var(--u)); }
.tuto-continuer-fleche { display: none; }
body.tuto-attente .pupitre { cursor: pointer; }
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  #tuto-continuer { grid-area: bulle; margin-top: var(--ecart); margin-bottom: calc(16 * var(--u)); }
}

/* ---------- La séquence d'un partenaire (#ecran-sponsor) ---------- */
.sponsor-nom { color: var(--accent-vif); }
/* la vidéo : elle prend toute la scène ; la classe .voile (app.js) la couvre de noir tant qu'elle ne joue pas */
#ecran-sponsor.video-integrale { padding: 0; overflow: hidden; }
#ecran-sponsor.video-integrale > :not(#sponsor-video-zone) { display: none; }
#sponsor-video-zone { position: relative; flex: 1 1 0; align-self: stretch; min-height: 0; background: #000; border-radius: inherit; overflow: hidden; }
#sponsor-video-zone > video, #sponsor-video-zone > div, #sponsor-video-zone iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; }
#sponsor-video-zone > video { object-fit: contain; }
#sponsor-video-zone::after { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #000; opacity: 0; pointer-events: none; transition: opacity 0.5s ease; }
#sponsor-video-zone.voile::after { opacity: 1; transition: none; }
/* la question d'un partenaire : le gabarit de la question */
#sponsor-question-zone, #sponsor-resultats-zone { display: flex; flex-direction: column; gap: var(--ecart); align-self: stretch; min-width: 0; }
#ecran-sponsor.sponsor-compact .annonce-surtitre { display: none; }
#ecran-sponsor.sponsor-compact .sponsor-nom { font-size: calc(var(--taille-titre) * 0.55); }
.sponsor-etape { font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; font-size: var(--taille-surtitre); color: var(--metal-clair); }
#sponsor-question-texte { font-family: var(--police-plateau); font-weight: 700; line-height: 1.22; font-size: calc(var(--taille-question) * 0.85); text-wrap: balance; }
#sponsor-chrono { height: calc(8 * var(--u)); border-radius: 999px; overflow: hidden; background: rgba(255, 255, 255, 0.09); }
#sponsor-chrono-barre { height: 100%; width: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--metal-sombre), var(--accent)); }
#sponsor-chrono-barre.urgence { background: var(--alerte); }


/* ============================================================================
   14. FENÊTRES, MESSAGE BREF, PAVÉ DE DÉVELOPPEMENT, ANCIENS ÉLÉMENTS
   ========================================================================== */

/* ---------- Les fenêtres (<dialog>) : menu, confirmation, notifications, documents légaux, « Nos règles ont évolué » ---------- */
dialog {
  width: min(calc(100vw - 24px), calc(560 * var(--u)));
  max-height: calc(var(--hauteur-ecran) - 24px - var(--sur-haut) - var(--sur-bas));
  padding: calc(22 * var(--u)) calc(20 * var(--u)); border: 0; border-radius: calc(18 * var(--u));
  color: var(--texte); text-align: center;
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.085) 0%, rgba(255, 255, 255, 0) 24%),
    linear-gradient(180deg, rgb(var(--verre-haut)), rgb(var(--verre-bas)));
  box-shadow: var(--verre-anneau), 0 calc(18 * var(--u)) calc(50 * var(--u)) rgba(0, 0, 0, 0.7);
  overflow-y: auto; overscroll-behavior: contain;
}
dialog[open] { display: flex; flex-direction: column; gap: calc(12 * var(--u)); }
dialog > * { flex: none; }
dialog::backdrop { background: rgba(var(--verre-bas), 0.78); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
dialog h3 { font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.1em; line-height: 1.1; font-size: calc(var(--taille-titre) * 0.62); color: var(--accent); text-wrap: balance; overflow-wrap: anywhere; }
dialog h3:empty, dialog p:empty { display: none; }
/* le menu : une colonne de boutons de verre */
.menu-liste { display: flex; flex-direction: column; gap: calc(9 * var(--u)); }
.menu-liste button { width: 100%; }
dialog .dialogue-fermer { align-self: center; }
dialog ul { text-align: left; padding-left: 1.2em; display: flex; flex-direction: column; gap: calc(6 * var(--u)); }
.consentement-contexte { padding: calc(8 * var(--u)) calc(12 * var(--u)); border-radius: calc(10 * var(--u)); color: var(--sur-alerte); font-weight: 700; }
#notifications-retour { color: var(--accent-vif); }
/* les documents légaux : très longs, ils défilent dans leur cadre ; « Fermer » reste atteignable */
#dialogue-legal { width: min(calc(100vw - 24px), calc(760 * var(--u))); height: calc(var(--hauteur-ecran) - 24px - var(--sur-haut) - var(--sur-bas)); overflow: hidden; }
.legal-onglets { flex-wrap: wrap; }
.legal-onglets button { flex: 1 1 auto; padding: 0 calc(8 * var(--u)); letter-spacing: 0.04em; white-space: nowrap; }
.legal-contenu {
  flex: 1 1 0; min-height: 0; overflow-y: auto; text-align: left; padding: calc(10 * var(--u)) calc(12 * var(--u));
  /* Le filet du cadre est une VRAIE bordure, pas l'anneau en creux du verre (--verre-anneau, une
     ombre intérieure) : une ombre intérieure se peint SOUS le texte, et ce texte défile. Les
     lettres passaient sur le filet, en haut et au bas du cadre (relecture finale, 2026-10-08). */
  border: max(1.5px, calc(2 * var(--u))) solid var(--metal-sombre);
  border-radius: calc(12 * var(--u)); background: rgba(var(--verre-bas), 0.7);
  font-size: var(--taille-texte); line-height: 1.5; overflow-wrap: anywhere;
}
.legal-contenu h4, .legal-contenu h5 { margin: 1em 0 0.4em; font-family: var(--police-plateau); color: var(--accent); }
.legal-contenu p, .legal-contenu ul { margin: 0 0 0.7em; }
.legal-contenu table { width: 100%; border-collapse: collapse; margin: 0 0 0.9em; font-size: 0.92em; }
.legal-contenu th, .legal-contenu td { padding: calc(5 * var(--u)) calc(7 * var(--u)); border: 1px solid rgba(var(--metal-clair-rvb), 0.3); text-align: left; vertical-align: top; }

/* ---------- Le message bref au bas de l'écran (#toast). app.js pose lui-même son fond : var(--erreur) ou var(--ok) ---------- */
#toast {
  position: fixed; z-index: 30; left: 50%; bottom: calc(18 * var(--u) + var(--sur-bas)); transform: translateX(-50%);
  width: max-content; max-width: min(calc(100vw - 24px), calc(620 * var(--u)));
  padding: calc(10 * var(--u)) calc(18 * var(--u)); border-radius: calc(12 * var(--u));
  font-size: var(--taille-texte); font-weight: 700; line-height: 1.3; text-align: center; color: #170b07;
  background: var(--erreur);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.85), 0 calc(6 * var(--u)) calc(22 * var(--u)) rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* ---------- Le pavé de développement (jamais montré en production) ---------- */
#bascule-dev {
  position: fixed; z-index: 40; right: 0; top: 50%; display: flex; flex-direction: column; gap: 4px; padding: 5px 6px;
  max-width: 170px; border-radius: 8px 0 0 8px; font-size: 11px; color: #ddd; background: rgba(0, 0, 0, 0.8); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);
  opacity: 0.6;
}
#bascule-dev:hover, #bascule-dev:focus-within { opacity: 1; }
#bascule-dev .bascule-rangee { display: flex; align-items: center; gap: 4px; }
/* replié sur son étiquette « DEV » tant qu'on ne le survole pas : il ne couvre rien */
#bascule-dev:not(:hover):not(:focus-within) select,
#bascule-dev:not(:hover):not(:focus-within) button,
#bascule-dev:not(:hover):not(:focus-within) .bascule-etat { display: none; }
#bascule-dev select, #bascule-dev button { min-height: 22px; height: 22px; width: auto; max-width: 110px; padding: 0 4px; font-size: 11px; border-radius: 4px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3); background: #111; color: #ddd; text-transform: none; letter-spacing: 0; }
#bascule-dev .bascule-etat { font-size: 10px; }

/* ---------- Les anciens éléments, que le pupitre remplace ----------
   app.js et son.js s'y branchent et les écrivent toujours : ils restent dans la
   page, mais ne sont plus montrés. Ils disparaîtront au ménage (étape 11).
     les trois boutons de l'ancienne en-tête   -> les quatre boutons du pupitre
     l'ancien bouton rond du son               -> le bouton « Son »
     le bandeau de statut de la question       -> les cadrans et les étiquettes
     la barre du chrono                        -> le cadran du centre */
#menu-compte > button, #btn-son, #bandeau-statut, #chrono { display: none !important; }


/* ============================================================================
   15. REPLIS POUR LES NAVIGATEURS ANCIENS (plan de bascule, partie 7)
   ----------------------------------------------------------------------------
   Le jeu reste utilisable, en moins joli. Ce qui est déjà fait plus haut :
     - aucun color-mix() : les mélanges passent par rgba(var(--…-rvb), …) ;
     - aucun :has() : pupitre.js pose des classes (body[data-ecran], .sans-lot…) ;
     - la hauteur réelle de l'écran : 100dvh, sinon mesurée par pupitre.js ;
     - une couleur de laiton simple avant chaque dégradé conique ;
     - largeur ET hauteur écrites là où « aspect-ratio » aurait suffi ;
     - text-wrap (balance, pretty) : sans lui le texte passe à la ligne
       normalement, rien à prévoir.
   ========================================================================== */
/* sans flou derrière le verre : un verre un peu plus opaque, pour rester lisible */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root { --verre-opaque-haut: 0.93; --verre-opaque-bas: 0.97; }
}
/* sans découpe en anneau : le cerclage couvrirait tout le panneau. Un simple filet le remplace. */
@supports not ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .verre::before, .reponse::before { background: none; padding: 0; border: max(1.5px, calc(2 * var(--u))) solid var(--metal-clair); }
}


/* ============================================================================
   16. MOUVEMENTS RÉDUITS
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .pupitre *, .pupitre *::before, .pupitre *::after, dialog, dialog *, #toast { transition: none !important; animation: none !important; }
}
