/* ============================================================================
   HOMIES — SAISON 2 · LA COLLE DES ÉCRANS JOUEUR (§ 6a et § 6b)
   ----------------------------------------------------------------------------
   Chargé APRÈS saison2-socle.css, par public/play.html UNIQUEMENT.
   Tout est scopé [data-s2] : un écran non intégré ne bouge pas d'un pixel.

   Ce fichier ne redessine RIEN. Il ne fait que trois choses :
     ① rendre les conteneurs d'écran compatibles avec .s2 (position:absolute) ;
     ② rattraper les composants que l'app écrit AUTREMENT que les maquettes
        (QZ.optionHtml → .letter-wrap/.ocheck au lieu de .lwrap/.stamp,
         QZ.noto → class="noto" au lieu de class="nemoji") — content.js est
        partagé avec l'hôte, on ne le touche pas ;
     ③ poser les quelques blocs de jeu que le socle ne connaît pas encore
        (bandeau de format, media de question, zone de réponse).

   RÈGLE D'OMBRE : un fond et son ombre n'ont jamais la même couleur, ni celle
   du fond derrière. Aplat clair → ombre noire ; prune NÉON → magenta ;
   bloc magenta → jaune ; bloc noir → jamais d'ombre noire.
   ============================================================================ */

/* ── ① .s2 est position:absolute; inset:0 — son écran doit être POSITIONNÉ ── */
section.screen[data-s2] { position: relative; }
section.screen[data-s2].active { display: block; }
/* en jeu, l'écran prend tout le cadre : ni topbar, ni marge (body.playing) */
section.screen[data-s2].active > :is(.s2, .s2-ready, .s2-tr, .s2-sent, .s2-fb, .s2-closed) { position: absolute; inset: 0; }

/* .pill, .btn, .s2-prow… ont un `display` explicite : il gagne contre le
   display:none que le navigateur donne à [hidden]. Sans ça, une pastille
   masquée par le JS (catégorie inconnue, pas de mise) restait à l'écran. */
[data-s2] [hidden] { display: none !important; }

/* ── ② LES RÉPONSES ÉCRITES PAR content.js ────────────────────────────────
   Les builders partagés (intrus, multi, plus/moins, mémoire, ordre…) écrivent
   .letter-wrap et .ocheck ; la maquette écrit .lwrap et .stamp. Les deux
   rendent le MÊME objet — brutal.css dessine déjà .ocheck comme le tampon
   penché à coche et croix TRACÉES (le glyphe ✓ du HTML est neutralisé par
   color:transparent). Rien à rattraper : on ne touche à aucune des deux.
   La seule chose qui manquait, c'est de poser les réponses DROITES. */

/* la maquette 44 pose les quatre réponses droites : l'inclinaison de l'app
   (.opt:nth-child(4n+k)) tordait la colonne et faisait déborder les ombres. */
[data-s2] .s2-g .opt { transform: none; }
/* ⚠ PLUS DE ZOOM À LA SÉLECTION. Edwin, plusieurs fois : « quand je
   sélectionne, ça prend tout l'écran, il y a un effet de zoom, c'est comme si
   la carte était complètement coupée… on n'arrive pas à voir toute l'ombre ».
   `transform: scale(1.03)` (brutal.css l.615) agrandit la réponse de 3 % :
   son ombre, qui vit DÉJÀ 5 px en dehors de sa boîte, sortait du conteneur et
   se faisait trancher par son `overflow:hidden`.
   La réponse choisie s'ENFONCE, comme tous les blocs du jeu : elle se décale
   de son ombre au lieu de grossir. Rien ne déborde, et le geste est celui de
   la maison — l'appui enfonce, il n'agrandit pas. */

/* les emojis écrits par content.js portent class="noto" : on leur donne au
   moins la mise en place de .nemoji (proto.css), sinon ils cadrent mal. */
[data-s2] .noto { display: inline-block; width: 1em; height: 1em; vertical-align: -.14em; object-fit: contain; }

/* le ping réseau de l'app (net-ping.js) dans une barre saison 2 : trois barres,
   comme .s2-ping de la maquette. La fonction ne bouge pas, seule la forme. */
[data-s2] .net-ping { flex: none; display: inline-flex; align-items: center; gap: 5px; }
[data-s2] .net-ping .np-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 15px; }
[data-s2] .net-ping .np-bars i { display: block; width: 4px; background: var(--green); }
[data-s2] .net-ping .np-bars i:nth-child(1) { height: 6px; }
[data-s2] .net-ping .np-bars i:nth-child(2) { height: 10px; }
[data-s2] .net-ping .np-bars i:nth-child(3) { height: 15px; }
[data-s2] .net-ping.ok .np-bars i:nth-child(3) { background: var(--yellow); }
[data-s2] .net-ping.bad .np-bars i:nth-child(2),
[data-s2] .net-ping.bad .np-bars i:nth-child(3) { background: var(--red); }
[data-s2] .net-ping.off .np-bars i { background: #8A8A8A; }
[data-s2] .net-ping .np-ms { font-family: var(--font-m); font-weight: 800; font-size: 8px; letter-spacing: .4px;
  color: color-mix(in srgb, var(--ink) 55%, transparent); }
[data-s2] :is(.s2-ghdr, .s2-cg .hd) .net-ping .np-ms { color: #CFC3CE; }

/* ── ③ L'ÉCRAN DE QUESTION ────────────────────────────────────────────────── */
/* le QR du salon : la maquette le DESSINE, l'app en a un vrai. Même cadre. */
[data-s2] .s2-qr img { display: block; width: 100%; height: 100%; object-fit: contain; background: #FFFEF7; }
[data-s2] .s2-qr:has(img[src=""]) { display: none; }

/* le bouton muet du salon et du classement, au format de la barre saison 2 */
[data-s2] .s2-bar .mute-btn,
[data-s2] .s2-bar .wait-mute { flex: none; width: 30px; height: 30px; padding: 0; font-size: 14px; line-height: 1;
  border: 2.5px solid var(--ink); background: var(--paper); color: var(--ink);
  box-shadow: 3px 3px 0 var(--ink); cursor: pointer; }
html[data-skin="neon"][data-theme] [data-s2] .s2-bar :is(.mute-btn, .wait-mute) { border-color: #0A0A0A; box-shadow: 3px 3px 0 #FF5CA8; }

/* le bandeau de format (LA TAUPE · LA TOUR · L'ARÈNE · DUEL · BATTLE · équipes,
   LA BOMBE) : il garde son rendu, il se cale seulement dans l'aire de jeu. */
[data-s2] .s2-gbody > .fmt-hud { flex-shrink: 0; margin: 0; }
[data-s2] .s2-gbody > .fmt-hud[hidden] { display: none; }
[data-s2] .s2-gbody > .mob-media:empty { display: none; }
[data-s2] .s2-gbody > .mob-media { flex-shrink: 0; overflow-x: clip; }
/* le corps de la question : il défile en hauteur, jamais en largeur */
[data-s2] .s2-gbody { overflow-x: clip; }
/* ⚠ C'EST ICI QU'ON POUVAIT FAIRE GLISSER L'ÉCRAN DE JEU. Edwin : « le fait
   qu'on puisse glisser de gauche à droite ». Le piège est dans la spec CSS :
   quand `overflow-y` vaut `auto` et que `overflow-x` est laissé à `visible`,
   le navigateur CALCULE `overflow-x: auto`. La zone de réponses, qui ne
   défile que verticalement, devenait donc AUSSI une zone défilante
   horizontale — et comme l'ombre dure de chaque réponse déborde de 5 px de
   sa boîte, il y avait exactement 5 px à faire glisser au doigt. D'où
   l'impression, depuis le début, que l'ombre était coupée.
   Deux gestes, et les deux sont nécessaires :
     ① on RÉSERVE la place de l'ombre (à droite et en bas, là où elle tombe),
        sinon la couper serait juste l'autre moitié du défaut ;
     ② `overflow-x: clip` — et pas `hidden` : `hidden` cache le débordement
        mais fabrique quand même une zone défilante. `clip` n'en crée aucune. */
[data-s2] .s2-gbody > .answer-zone {
  padding: 0 var(--sh) var(--sh) 0;
  overflow-y: auto; overflow-x: clip;
}
/* ⚠ ET LA CEINTURE, EN PLUS DES BRETELLES. `overflow-x: clip` ne tient pas
   ici : la spec le DÉGRADE EN `hidden` dès que l'autre axe vaut `auto`, et
   `hidden` refabrique une zone défilante. Ce qui règle vraiment le défaut,
   c'est la réserve d'ombre au-dessus (plus rien ne déborde, donc plus rien à
   faire glisser). `touch-action: pan-y` verrouille le reste : le doigt ne
   peut QUE monter et descendre dans la zone de jeu, quoi qu'il arrive au
   contenu plus tard. */
[data-s2] .s2-gbody,
[data-s2] .s2-gbody > .answer-zone { touch-action: pan-y; }
/* ⚠ L'OMBRE MANGE LA GOUTTIÈRE. `.opt .sh` déborde de 5 px sous chaque
   réponse : à 11 px de gap, il ne restait que 6 px de blanc entre deux
   réponses et la colonne paraissait soudée. Edwin : « lorsqu'on répond aux
   questions, c'est groupé, en termes de design c'est pas fou ». 16 px de gap
   = 11 px réellement vus, le même air qu'entre deux cartes de l'app. */
[data-s2] .s2-gbody > .answer-zone.options-col { display: flex; flex-direction: column; gap: 16px; }

/* LE BOUTON « VALIDER » DE LA ZONE DE RÉPONSE (ordre, estimation, multi,
   anagramme, avis…). Il reste collé en bas de la colonne, à pleine largeur,
   et ne mange plus la moitié de l'écran : une ligne, jamais deux. */
[data-s2] .answer-zone .btn.valider {
  flex: none; margin-top: 2px; white-space: nowrap;
}
/* la ligne clavier de l'anagramme (⌫ / VALIDER →) : même gabarit */
[data-s2] .answer-zone .btn.valider + .btn,
[data-s2] .answer-zone .kb-row .btn { flex: none; }

/* le pied « qui a répondu » : vide, il ne laisse pas une bande orpheline */
[data-s2] .s2-gfoot:empty { display: none; }
[data-s2] .s2-gfoot .avs .ava-emo { width: 30px; height: 30px; border: 2.5px solid var(--ink); flex: none; }
[data-s2] .s2-gfoot .avs > * + * { margin-left: -12px; }
[data-s2] .s2-gfoot .pill { flex: none; }

/* ── L'ÉCRAN RÉPONSE ENVOYÉE ─────────────────────────────────────────────── */
[data-s2] .s2-sent .options { padding: 0; }
[data-s2] .s2-sent .card > .bd { padding: 0; }
[data-s2] .s2-sent .s2-gfoot { background: none; border: 0; padding: 9px 11px; }

/* ── LE VERDICT ──────────────────────────────────────────────────────────── */
/* ⚠ IL NE DÉFILE PLUS. Edwin : « l'écran de résultat (correct et/ou faux), on
   peut scroller, ce qui ne doit pas être possible ». Ce qui dépassait n'était
   pas le texte mais `.rays`, le soleil décoratif de 1 100 px. Même règle que
   côté hôte (saison2-hostgame.css § ④) : l'écran est coupé net, et seule la
   bonne réponse — la seule partie qui peut vraiment s'allonger — défile chez
   elle. */
[data-s2] .s2-fb { overflow: hidden; overflow: clip; }
[data-s2] .s2-fb > .s2-ttl.wide { max-height: 30vh; overflow-y: auto; scrollbar-width: none; }
[data-s2] .s2-fb > .s2-ttl.wide::-webkit-scrollbar { display: none; }
[data-s2] .s2-fb .s2-ttl .v { white-space: normal; line-height: 1.15; }
[data-s2] .s2-fb .dl b { display: inline-flex; align-items: baseline; }
[data-s2] .s2-fb .s2-chips { flex: none; }

/* ── LE CLASSEMENT ───────────────────────────────────────────────────────── */
[data-s2] .s2-lbt .avatar.s { width: 34px; height: 34px; }
[data-s2] .s2-lbt .cos-nick { font: inherit; }
/* ── UN ÉLIMINÉ SE VOIT ────────────────────────────────────────────────────
   Edwin : « la couleur de la carte de ceux qui sont éliminés doit être rouge
   avec un emoji squelette, comme la saison précédente ». La saison 1 peignait
   toute la ligne en rouge (public-v1 › .player-result.dead) ; la saison 2 se
   contentait d'un `opacity:.62` invisible — d'où « pourquoi il y a un 2ᵉ et
   un 3ᵉ au classement s'ils sont éliminés ? ». On reprend le traitement de
   la saison 1 : aplat rouge, pseudo crème, avatar en gris, badge 💀 + manche
   de sortie. L'ombre reste encre (le rouge n'est pas un fond sombre). */
[data-s2] .s2-lbt.dead { opacity: 1; background: var(--red); }
[data-s2] .s2-lbt.dead .nm,
[data-s2] .s2-lbt.dead .sc,
[data-s2] .s2-lbt.dead .cos-nick { color: var(--paper); }
[data-s2] .s2-lbt.dead .avatar { filter: grayscale(1); }
[data-s2] .s2-lbt.dead .s2-rkb { background: var(--paper); color: var(--ink); }
[data-s2] .s2-gain.out {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--ink); color: var(--yellow);
  border-color: var(--paper); box-shadow: 2px 2px 0 var(--paper);
}
[data-s2] .s2-gain.out .nemoji { width: 15px; height: 15px; }
[data-s2] .s2-lbt .medal { flex: none; width: 26px; height: 26px; }
[data-s2] .s2-lbt .medal .nemoji { width: 18px; height: 18px; }
[data-s2] .s2-lbt .s2-rkb { width: 30px; }
/* les bandeaux de format posés au-dessus de la liste (tour, arène, équipes) */
[data-s2] #plbHead:empty { display: none; }
[data-s2] #plbHead { flex-shrink: 0; }

/* ── LA FIN DE PARTIE ────────────────────────────────────────────────────── */
[data-s2] .s2-pod .avatar.s { width: 40px; height: 40px; }
[data-s2] .s2-pod .cos-title { display: none; }   /* la marche est étroite : le pseudo suffit */
[data-s2] .s2-pod .crown { position: absolute; top: -17px; left: 50%; margin-left: -13px; }
[data-s2] .s2-pod .card { position: relative; }
[data-s2] .s2-res .emoji-box { flex: none; }
[data-s2] #fullBoard { display: flex; flex-direction: column; gap: 8px; }
/* PAR ÉQUIPE : le podium devient un bloc (colonnes Rouge/Bleu) */
[data-s2] .s2-pod.pod-teams { display: block; }
/* ⚠ LE DUEL OCCUPE TOUTE LA LARGEUR. `.s2-pod` est une grille de 3 colonnes
   (les marches 2·1·3) : le bloc du duel, enfant unique, se retrouvait dans la
   colonne de gauche et tenait sur un tiers de l'écran. Edwin : « l'écran
   résultat final du duel s'affiche mal, c'est coincé sur la gauche ». Même
   traitement que la vue par équipes. */
[data-s2] .s2-pod.pod-duel { display: block; }

/* ── L'ÉCRAN ÉLIMINÉ ─────────────────────────────────────────────────────── */
[data-s2] #screen-eliminated .s2-fb { justify-content: flex-start; }

/* ── COLLISION DE NOMS AVEC saison2.css ───────────────────────────────────
   public/css/saison2.css (LA TAUPE · LA TOUR · L'ARÈNE, chargée avant le
   socle) utilise DÉJÀ .s2-top, .s2-scroll et .s2-ttl — pour sa barre du haut,
   sa zone qui défile et son titre. Le socle ne redit que ce qui l'intéresse :
   le reste (padding, bordure, align-items, flex) passait au travers et
   recentrait les lignes du classement sur un tiers de l'écran.
   On rend ici aux trois classes ce que la maquette attend. */
[data-s2] .s2-top { align-items: stretch; padding: 0; border-bottom: 0; flex: 0 0 auto; }
[data-s2] .s2-scroll { padding: 0 6px 6px; }
[data-s2] .s2-ttl { flex: 0 0 auto; font-family: var(--font-m); font-size: inherit; letter-spacing: normal; }

/* ── 49 · LE VERDICT DE FORMAT, AU VOCABULAIRE DE LA MAQUETTE ─────────────
   QZ.taupeVerdictHtml (content.js, partagé avec l'hôte) écrit .tp-verdict.
   La maquette 49 en fait un bloc d'ENCRE à ombre colorée (.s2-vd) : verte
   quand l'équipe gagne, rouge quand c'est la taupe. Jamais de noir sur noir,
   et le texte redevient lisible (le blanc à 75 % sur vert clair ne l'était pas). */
[data-s2] #overS2 .tp-verdict { background: #0A0A0A; border-color: #0A0A0A; box-shadow: 5px 5px 0 var(--green); color: #FFFEF7; }
[data-s2] #overS2 .tp-verdict.ko { box-shadow: 5px 5px 0 var(--red); }
[data-s2] #overS2 .tp-vd-stamp { background: var(--green); color: #0A0A0A; border-color: #FFFEF7; box-shadow: none; font-size: 19px; }
[data-s2] #overS2 .tp-verdict.ko .tp-vd-stamp { background: var(--red); color: #FFFEF7; }
[data-s2] #overS2 .tp-vd-who b { color: var(--yellow); }
[data-s2] #overS2 .tp-vd-who i { color: #CFC3CE; opacity: 1; }
[data-s2] #overS2 .tp-vd-lines div { color: #9E8F9C; opacity: 1; }
[data-s2] #overS2 .tp-vd-lines div.on { color: #FFFEF7; }
[data-s2] #overS2 .tp-h { margin-top: 10px; }

/* ── ABÎME : l'encre redevient noire sur les aplats vifs ──────────────────
   saison2-socle.css fait déjà ce travail pour les composants qu'il connaît
   (.btn.yellow, .pill.green, .lbrow.me…). Deux blocs de la boucle de jeu n'y
   étaient pas : la marche du podium et « TON RÉSULTAT ». En ABÎME leur texte
   restait clair sur or / argent / bronze — illisible. Les bords et les ombres,
   eux, ne bougent pas : clairs sur fond sombre, c'est la doctrine d'ABÎME. */
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] :is(
  .s2-pod .card > .bd, .s2-res .bd, .s2-vd .stamp
) { color: #0A0A0A; }
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] :is(
  .s2-pod .card > .bd .nm, .s2-pod .card > .bd .sc, .s2-pod .card > .bd .rk,
  .s2-res .k, .s2-res .v, .s2-res .m, .s2-res .cos-nick
) { color: #0A0A0A; }

/* ── COLLISION INTERNE AU SOCLE : .s2-big ─────────────────────────────────
   saison2-socle.css porte DEUX règles .s2-big : le chiffre-titre (ligne 1016)
   et, bien plus bas (ligne 2946), la taille d'un emoji de la galerie des types
   — width:56px; height:56px. La seconde gagne. Sur la SALLE FERMÉE, le score
   gardé se faisait donc couper à « 4 … ». On lui rend sa largeur. */
[data-s2] :is(.s2-closed, .s2-sent, .s2-fb, .s2) .s2-big { width: auto; height: auto; }

/* ── NÉON : l'état d'une réponse révélée ──────────────────────────────────
   saison2-socle.css arbitre .opt.correct / .opt.wrong en repeignant le fond
   (vert / rouge) et le texte avec var(--ink) / var(--paper). En NÉON ces deux
   tokens s'inversent : l'encre devient claire (crème sur vert = illisible) et
   le papier devient prune. Les maquettes ne montrent jamais ces deux états en
   NÉON — elles ne pouvaient donc pas trancher. Ici on tranche : sur un aplat
   VIF, l'encre est noire ; sur le rouge, le texte est crème. */
html[data-skin="neon"][data-theme] [data-s2] :is(.opt.correct, .opt.selected) .bd { color: #0A0A0A; }
html[data-skin="neon"][data-theme] [data-s2] .opt.wrong .bd { color: #FFFEF7; }

/* ── MIX DU JOUR : L'INTRO PASSE À LA PEAU SAISON 2 ───────────────────────
   Edwin : « il faut penser aussi à la nouvelle interface de MIX DU JOUR, ça a
   gardé le design de la saison précédente ».
   Deux choses le trahissaient :
   ① un DÉGRADÉ rose → violet en fond, que le brandbook interdit (« pas de
     dégradé, de lueur, de flou ») ;
   ② le bouton « Plus tard » tombait sous le bord de l'écran.
   Le fond devient un aplat magenta à trame de points — la matière de la
   saison 2 — et la colonne respire assez pour que les deux boutons tiennent.
   `brutal.css` porte la règle d'origine et on n'y touche pas : on la recouvre
   ici, avec la même spécificité mais chargée après. */
.daily-intro {
  background: var(--magenta);
  background-image: radial-gradient(rgba(10, 10, 10, .16) 1.6px, transparent 1.7px);
  background-size: 11px 11px;
  align-items: flex-start;
  padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
}
.daily-intro .di-inner { width: 100%; max-width: 420px; margin: auto; }
/* ⚠ LE TITRE ÉTAIT DÉTOURÉ. `brutal.css` lui pose un
   `-webkit-text-stroke: 1.5px` — c'est exactement ce qu'Edwin avait déjà refusé
   (« détouré au noir, enlève ça, je ne t'ai pas demandé »), et c'est ce qui
   faisait « la police, de la façon c'est écrit, j'aime pas ». Plus de contour :
   du crème plein, posé sur son ombre dure. */
.daily-intro .di-ttl {
  -webkit-text-stroke: 0; text-stroke: 0;
  text-shadow: 5px 5px 0 #0A0A0A; letter-spacing: 0; font-size: 46px;
}

/* ⚠ ET TROP DE JAUNE. Edwin : « ici on n'est plus dans du jaune, je vois que tu
   utilises encore les couleurs jaunes un peu partout ». Le jaune est la couleur
   de la saison 1 ; la saison 2 vit sur le magenta et ses accents. Le badge du
   haut passe au cyan, l'objectif à l'encre, et le bouton COMMENCER au vert —
   c'est lui l'action, il doit se distinguer du fond magenta. */
.daily-intro .di-badge {
  background: var(--cyan); transform: rotate(-3deg);
  box-shadow: 6px 6px 0 #0A0A0A;
}
.daily-intro .di-obj { background: #0A0A0A; color: #FFFEF7; box-shadow: 5px 5px 0 var(--cyan); }
.daily-intro .di-obj .di-obj-k { color: var(--cyan); }
.daily-intro .di-go {
  margin-top: 4px; background: var(--green); color: #0A0A0A;
  border: 4px solid #0A0A0A; box-shadow: 6px 6px 0 #0A0A0A;
}

/* « Plus tard » était un lien souligné perdu sous le bouton : Edwin veut un
   BOUTON. Il en devient un — discret, mais visable au pouce. */
.daily-intro .di-later {
  margin-top: 12px; padding: 11px 16px; width: 100%;
  font-family: var(--fd); font-size: 14px; letter-spacing: 1px;
  background: var(--paper); color: #0A0A0A; text-decoration: none;
  border: 3px solid #0A0A0A; box-shadow: 4px 4px 0 #0A0A0A; cursor: pointer;
}
.daily-intro .di-later:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 #0A0A0A; }
/* ⚠ le fond est magenta : une ombre magenta y disparaîtrait. Les blocs clairs
   gardent leur ombre noire, et le bloc d'encre prend une ombre jaune.
   ⚠ CE QUI ÉTAIT ÉCRIT N'ÉTAIT PAS CE QUI ÉTAIT FAIT : la ligne posait une
   ombre NOIRE sur un bloc NOIR (elle écrasait l'ombre cyan d'au-dessus).
   C'est le « noir sur noir » qu'Edwin a repéré sur l'écran du MIX DU JOUR. */
.daily-intro .di-obj { box-shadow: 5px 5px 0 var(--yellow); }
html[data-skin="neon"][data-theme] .daily-intro { background-color: #1C0F1A; }
html[data-skin="neon"][data-theme] .daily-intro .di-obj { box-shadow: 5px 5px 0 #FF2E93; }


/* ── AUCUN BANDEAU PENDANT UNE PARTIE ──────────────────────────────────────
   ⚠ Le bandeau « Sois alerté de tes nouveaux défis » (`.pwa-banner`, collé en
   bas) se posait PAR-DESSUS la dernière réponse, en pleine question, chrono en
   marche. On ne demande pas à quelqu'un d'activer ses notifications pendant
   qu'il joue : il a quelques secondes pour répondre, et une réponse cachée est
   une réponse perdue. Le bandeau attend la fin de la manche. */
body:has(#screen-question.active) .pwa-banner,
body:has(#screen-sent.active) .pwa-banner,
body:has(#screen-reveal.active) .pwa-banner,
body:has(#screen-transition.active) .pwa-banner,
body:has(#screen-podium.active) .pwa-banner,
body:has(#screen-feedback.active) .pwa-banner,
body:has(#screen-carnage.active) .pwa-banner { display: none !important; }


/* ── QUITTER : VISIBLE, ET ATTRAPABLE AU DOIGT ─────────────────────────────
   Edwin : « le bouton abandonner la partie, il faut qu'il soit bien visible,
   bien évidemment en rouge ». La croix du bandeau de jeu était transparente et
   mesurait 27×27 — sous les 44 px qu'il faut pour un doigt, et invisible sur
   le bandeau d'encre. Elle devient un vrai bouton rouge, à sa taille. */
[data-s2] .s2-ghdr .x {
  width: 34px; height: 34px; flex: none;
  background: var(--red); border: 3px solid #0A0A0A; box-shadow: 2px 2px 0 #0A0A0A;
  position: relative; cursor: pointer;
}
/* la croix est TRACÉE, jamais le glyphe ✕ */
[data-s2] .s2-ghdr .x::before,
[data-s2] .s2-ghdr .x::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 16px; height: 3px; margin: -1.5px 0 0 -8px; background: #FFFEF7;
}
[data-s2] .s2-ghdr .x::before { transform: rotate(45deg); }
[data-s2] .s2-ghdr .x::after { transform: rotate(-45deg); }
/* la zone touchable déborde du dessin : 44 px au doigt, sans grossir à l'œil */
[data-s2] .s2-ghdr .x { outline-offset: 0; }
[data-s2] .s2-ghdr .x::marker { content: none; }

/* ── LA SALLE D'ATTENTE · MÊMES CHIPS QUE LE SALON DE L'HÔTE ───────────────
   Edwin : « hôte et joueur, attention, n'oublie pas qu'on a deux types de
   joueurs ». Les deux écrans montrent la MÊME partie : ils doivent la montrer
   pareil. Le salon de l'hôte est passé aux valeurs de la maquette s33b ②
   (police 10,5 px, padding 5/8, hauteur 26) parce que sa barre se coupait au
   bord ; la salle d'attente gardait les grandes. Elles sont désormais
   identiques des deux côtés. */
#screen-wait[data-s2] #waitGameInfo { gap: 6px; }
#screen-wait[data-s2] #waitGameInfo .pill {
  font-size: 10.5px; letter-spacing: .4px; padding: 5px 8px; min-height: 26px; gap: 4px;
}
#screen-wait[data-s2] #waitGameInfo .pill .nemoji { width: 13px; height: 13px; }

/* la carte « toi » : le drapeau tombait sur sa propre ligne, au-dessus de
   « NIV 1 · TU ES DANS LA PLACE », alors que dans les cartes de la liste juste
   en dessous il est sur la même ligne que le texte. Même ligne des deux côtés. */
#screen-wait[data-s2] .s2-you .s2-sub { display: flex; align-items: center; gap: 5px; }

/* le même désert côté joueur : la place libre prend l'espace qu'il reste
   au-dessus de la barre INVITER · MON PROFIL · QUITTER. */
/* ⚠ #waitPlayers EST le bloc qui défile (l'hôte, lui, a un #playersWall À
   L'INTÉRIEUR du sien) : il a déjà sa hauteur, lui en imposer une le faisait
   déborder et poussait la barre de boutons hors de l'écran. */
#screen-wait[data-s2] #waitPlayers { display: flex; flex-direction: column; }
#screen-wait[data-s2] #waitPlayers > .s2-prow:not(.vide) { flex: none; }
#screen-wait[data-s2] #waitPlayers > .s2-prow.vide { flex: none; }

/* ⚠ LE PODIUM N'EST PAS TOUJOURS UN PODIUM. Edwin, capture à l'appui : l'écran
   de fin du MIX DU JOUR tenait dans une colonne large comme un tiers d'écran,
   le reste vide, le titre coupé en trois lignes.
   La cause : `#podium` porte `.s2-pod` (grille de trois marches) et on y pose
   le verdict du défi (`.daily-end`) ou celui du duel (`.duel-end`), qui ne sont
   pas des marches. brutal.css avait déjà la parade — mais écrite pour `.podium`,
   la classe de la saison 1. En saison 2 elle ne s'appliquait plus.
   Même règle, bonne classe. */
[data-s2] .s2-pod:has(.daily-end),
[data-s2] .s2-pod:has(.duel-end) { display:block; grid-template-columns:none; gap:0; padding:0; }

/* ════════════════════════════════════════════════════════════════════════
   FIN DE PARTIE — « on n'arrive pas à scroller »
   Edwin, capture à l'appui : sur LA TOUR, le titre « CLASSEMENT COMPLET »
   était coupé et la liste inatteignable. Mesuré : la zone de défilement
   faisait 29 px de haut. Tout ce qui est au-dessus (GG, verdict, la tour,
   la carte de résultat) mangeait la hauteur, et `.s2-scroll` ne gardait que
   les miettes — elle défilait donc « dans le vide ».
   On fait défiler l'ÉCRAN ENTIER, et le pied (PARTAGER / ACCUEIL) reste
   collé en bas. Le classement redevient atteignable, quel que soit le mode.
   ════════════════════════════════════════════════════════════════════════ */
[data-s2]#screen-over .s2 { overflow-y: auto; -webkit-overflow-scrolling: touch; }
[data-s2]#screen-over .s2-scroll { overflow: visible; min-height: 0; flex: none; }
[data-s2]#screen-over .s2-two {
  position: sticky; bottom: 0; z-index: 6; margin-top: 12px;
  padding: 10px 0 calc(6px + env(safe-area-inset-bottom));
  background: var(--app-bg, #FFFEF7); border-top: 4px solid var(--ink);
}
/* la tour en fin de partie : un rappel, pas la pièce maîtresse */
[data-s2]#screen-over .tr-twrwrap { flex: none; min-height: 0; }
[data-s2]#screen-over .tr-fl { height: 28px; font-size: 11px; }

/* MÉMOIRE : la bonne case porte le même petit repère que les réponses — un
   point discret dans le coin, pas un surlignage qui se verrait de loin. */
[data-s2] .nt-memcell.god-ok,
[data-s2] .nt-memcell.pres-correct { position: relative; }
[data-s2] .nt-memcell.god-ok::after,
[data-s2] .nt-memcell.pres-correct::after {
  content: ''; position: absolute; top: 5px; right: 5px; width: 7px; height: 7px;
  background: var(--ink); border-radius: 50%;
}
