/* ⚠ CONVENTION DE SCOPE — À LIRE AVANT DE TESTER CE FICHIER
   `saison2-socle.css` est scopé À 100 %% en `[data-s2]`, et un test automatique
   le vérifie. CE FICHIER-CI ne l'est pas entièrement : quelques règles sont
   scopées par un ID d'écran (`#screen-rapide`, `#screen-niveau`, `#screen-recap`,
   `#screen-join`) ou par `body.s2-onglet`. Elles sont sûres — elles ne peuvent
   toucher que l'écran nommé — mais un test « tout est en [data-s2] » les
   signalera comme des faux positifs. C'est voulu, ne les « corrige » pas. */
/* ============================================================================
   HOMIES — SAISON 2 · LA COLLE DU TUNNEL DE CRÉATION (vague 4)
   ----------------------------------------------------------------------------
   saison2-socle.css porte TOUT le dessin des écrans (il est généré, on n'y
   touche pas). Ce fichier-ci ne dessine rien de neuf : il fait entrer un écran
   `.s2` dans le shell de la page HÔTE, et il redit — à l'identique — les
   quelques valeurs de proto.css que host.css écrase sur son passage.

   Il ne touche ni proto.css, ni brutal.css, ni app.css, ni saison2-socle.css,
   ni saison2-app.css (l'autre vague). Mobile d'abord : tout ce qui suit est la
   base téléphone ; le grand écran passe par des @media (min-width…) à la fin.
   ============================================================================ */

/* ── 1. UN ÉCRAN DU TUNNEL OCCUPE TOUT LE CADRE ─────────────────────────────
   `.s2` est `position:absolute; inset:0` : son conteneur doit donc être
   POSITIONNÉ et avoir la taille du cadre. host.css met déjà
   `section.screen.active { display:flex; flex-direction:column; overflow:hidden }`
   sur ces écrans : il ne manque que le repère de position. */
section.screen[data-s2] { position: relative; }
/* le pointillé du fond vient de `.s2` : le body.dotted-bg ne doit pas passer à travers */
section.screen[data-s2] { background: var(--paper); }

/* ── 2. LES TROIS VALEURS DE PROTO QUE host.css ÉCRASE ──────────────────────
   host.css est chargé APRÈS proto.css et redéfinit ces classes pour l'ancien
   markup. On les redit ici, telles que proto.css les écrit, et rien de plus. */
[data-s2] .s2 .page-title { font-family: var(--font-d); font-size: 22px; letter-spacing: 2px; }
/* `.stepper` est le pas (− n +) de proto ; host.css s'en sert AUSSI pour le
   fil d'Ariane de son en-tête (overflow:hidden, masqué sous 560px). */
[data-s2] .s2 .stepper { display: flex; overflow: visible; gap: 10px; }
@media (max-width: 560px) { [data-s2] .s2 .stepper { display: flex; } }

/* ── 3. CE QUI DEVIENT CLIQUABLE ────────────────────────────────────────────
   La maquette est une image : dans l'app, ces blocs sont des boutons. On ne
   leur donne QUE le comportement (curseur, enfoncement), jamais un dessin. */
[data-s2] .s2 :is(.iconbtn, .btn, .cta, .listcard, .s2-pk, .s2-dif, .s2-more,
  .s2-cbt, .s2-pen, .s2-kick, .s2-live, .s2-scan, .toggle-btn,
  .seg .o, .s2-qr) { cursor: pointer; }
[data-s2] .s2 :is(.iconbtn, .s2-cbt, .s2-pen, .s2-kick):active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }
/* Un <button> ramène la police, le fond, le bord et le soulignement du
   navigateur. On les enlève — mais avec `:where()`, DONC À SPÉCIFICITÉ ZÉRO :
   la moindre classe du brandbook (`.pill`, `.btn`, `.s2-kick`, `.iconbtn`…)
   doit reprendre la main. C'est le piège qui a repeint QUITTER en texte nu. */
:where([data-s2] .s2) :where(button, a.iconbtn) {
  appearance: none; -webkit-appearance: none; font: inherit; color: inherit;
  background: none; border: 0; padding: 0; margin: 0; text-align: inherit;
  text-decoration: none; cursor: pointer;
}
/* `hidden` veut dire caché. Les classes de mise en place (`.stack`, `.s2-chips`,
   `.card`…) posent un `display` qui gagne contre celui du navigateur : sans ça,
   le bloc « offrir un prix » restait visible hors mode présentateur. */
[data-s2] .s2 [hidden] { display: none !important; }

/* ── 4. CE QU'ON NE PEUT PAS FAIRE, ET QUI DOIT SE VOIR ─────────────────────
   Un bouton éteint reste LISIBLE (il dit pourquoi) : on le pose en gris, on ne
   le fait pas disparaître. `.s2-off` du socle fait ça pour les cartes de liste ;
   ici c'est le CTA du pied. */
[data-s2] .s2 .cta:is([data-disabled="true"], .off) > .bd { background: var(--gray2); color: color-mix(in srgb, var(--ink) 45%, transparent); }
[data-s2] .s2 .cta:is([data-disabled="true"], .off) { cursor: default; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .cta:is([data-disabled="true"], .off) > .bd { background: #3E2A3B; color: rgba(246,238,227,.42); border-color: #FF5CA8; }

/* le voile VERROUILLÉ d'une tuile de pack : le socle dessine `.s2-pk .lk`,
   mais l'app y met aussi un cadenas cliquable qui ouvre la fiche d'achat. */
[data-s2] .s2 .s2-pk .lk { cursor: pointer; }
/* pack injouable hors-ligne : même voile, le cadenas en moins */
[data-s2] .s2 .s2-pk.offline .lk { background: rgba(10,10,10,.74); }

/* ── 5. LE SALON : CE QUE LA MAQUETTE NE POUVAIT PAS MONTRER ────────────────
   Le QR est une VRAIE image (le serveur la renvoie), pas trois carrés dessinés ;
   elle prend la place du faux QR du socle, à la même taille. */
[data-s2] .s2 .s2-qr img { width: 100%; height: 100%; display: block; object-fit: contain; }
[data-s2] .s2 .s2-qr.real { background: #FFFEF7; padding: 4px; }
[data-s2] .s2 .s2-qr.real i, [data-s2] .s2 .s2-qr.real u { display: none; }
/* la ligne d'un bot : pas de pays, pas de grade — un robot, et la croix */
[data-s2] .s2 .s2-prow.bot .cty { font-style: normal; }
/* JOUER SANS INTERNET — le dépannage, replié.
   Le pavé de trois lignes (« PAS DE QR ? SUR LE MÊME WIFI, VA SUR 192.168.x.x »)
   occupait un bloc entier du salon pour un cas de secours. Il ne reste qu'un
   LIEN discret, visible seulement quand on est vraiment sur une adresse du
   réseau local (host/05_create.js › showLanAddress) : il ouvre le QR en grand,
   et c'est LÀ que l'adresse est écrite et copiable. */
[data-s2] .s2 .lan-lnk { align-self: flex-start; flex-shrink: 0; padding: 0; border: 0; background: none;
  font-family: var(--font-m); font-weight: 800; font-size: 9px; letter-spacing: 1.6px; cursor: pointer;
  color: color-mix(in srgb, var(--ink) 55%, transparent);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 2px; }
[data-s2] .s2 .lan-lnk:active { color: var(--ink); }
/* dans le QR plein écran : l'adresse, en toutes lettres, sur un aplat jaune à
   ombre noire (aplat clair → ombre noire). */
[data-s2] .qr-ov-lan { display: flex; flex-direction: column; align-items: center; gap: 6px;
  margin-top: 10px; opacity: 1; }
[data-s2] .qr-ov-lan[hidden] { display: none; }
[data-s2] .qr-ov-lan .ls-addr { font-family: var(--font-d); font-size: 15px; letter-spacing: 1px;
  border: 3px solid var(--ink); background: var(--yellow); color: var(--ink);
  box-shadow: 4px 4px 0 var(--ink); padding: 5px 11px; cursor: pointer; }
[data-s2] .qr-ov-lan .ls-addr:active { transform: translate(4px, 4px); box-shadow: none; }

/* LE MUR DES JOUEURS — l'écart qu'on VOIT.
   `#playersWall` n'était pas une colonne : les `.s2-prow` s'empilaient en blocs
   sans marge et se TOUCHAIENT (écart mesuré : 0 px). Le gap porte l'écart vu,
   et chaque ligne réserve les 4 px d'ombre qu'elle déborde — tokens du socle,
   pas de valeur inventée. */
[data-s2] .s2 #playersWall { display: flex; flex-direction: column; gap: var(--s2-r); }
[data-s2] .s2 #playersWall > .s2-prow { margin-bottom: 4px; }
[data-s2] .s2 #playersWall > .s2-prow.vide { margin-bottom: 0; }   /* place libre : pas d'ombre à réserver */
/* DUEL et PAR ÉQUIPES posent un séparateur dans le mur : une section commence. */
[data-s2] .s2 #playersWall > .s2-div { margin-top: calc(var(--s2-rs) - var(--s2-r)); }
[data-s2] .s2 #playersWall > .s2-div:first-child { margin-top: 0; }

/* ── 6. REJOINDRE (côté joueur) ─────────────────────────────────────────────
   Les cases du code sont de VRAIS champs : `.codecells .cell` de proto leur
   donne la boîte, il ne manque que ce qui fait un champ (centrage, capitales,
   pas de chrome du navigateur). */
[data-s2] .s2 .codecells .cell { text-align: center; text-transform: uppercase; caret-color: var(--magenta);
  outline: none; padding: 0; color: inherit; }
[data-s2] .s2 .codecells .cell:focus { background: var(--yellow); box-shadow: 3px 3px 0 var(--magenta); }
/* l'étape qui n'est pas à l'écran sort du flux (les deux vivent dans le même `.s2-scroll`) */
/* ⚠ `.s2-scroll` est un flex EN COLONNE : ses enfants se laissent comprimer dès
   que le contenu dépasse la hauteur de l'écran. Depuis que REJOINDRE tient sur
   un seul écran, il dépasse — et tout s'écrasait : « TAPE LE CODE » tombait de
   29 à 11 px, les visages de la grille d'avatars étaient coupés en deux. Chaque
   bloc garde sa hauteur, et c'est la colonne qui défile. C'est le même piège
   que sur l'accueil : à retenir pour tout écran dont le contenu grandit. */
#screen-join .s2-scroll > * { flex: none; }
/* les deux étapes n'existent plus : REJOINDRE est un seul écran */
/* les parties récemment rejointes : rendues par play/11_recent-rooms.js, qui
   n'est pas de ce chantier — on leur donne le vocabulaire de la maquette. */
[data-s2] .s2 .recent-rooms { display: none; flex-direction: column; gap: 8px; }
[data-s2] .s2 .recent-rooms.show { display: flex; }
[data-s2] .s2 .recent-head { display: flex; align-items: center; gap: 9px; }
[data-s2] .s2 .recent-title { font-family: var(--font-d); font-size: 12px; letter-spacing: 2.2px; }
[data-s2] .s2 .recent-clear { margin-left: auto; font-family: var(--font-d); font-size: 10px; letter-spacing: 1px;
  border: 2px solid var(--ink); background: var(--red); color: var(--paper); padding: 3px 7px; cursor: pointer; }
[data-s2] .s2 .recent-list { display: flex; flex-direction: column; gap: 8px; }
[data-s2] .s2 .recent-row { display: flex; align-items: center; gap: 9px; text-align: left;
  border: var(--bd) solid var(--ink); background: var(--paper); box-shadow: 4px 4px 0 var(--ink);
  padding: 9px 11px; cursor: pointer; }
[data-s2] .s2 .recent-row .code { font-family: var(--font-d); font-size: 15px; letter-spacing: 1.4px;
  background: var(--yellow); border: 2px solid var(--ink); padding: 2px 7px; flex: none; }
[data-s2] .s2 .recent-row .host { flex: 1; min-width: 0; font-family: var(--font-d); font-size: 13px;
  letter-spacing: .4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
[data-s2] .s2 .recent-row .when { flex: none; font-family: var(--font-m); font-weight: 800; font-size: 8.5px;
  letter-spacing: 1.4px; color: color-mix(in srgb, var(--ink) 55%, transparent); }
html[data-skin="neon"][data-theme] [data-s2] .s2 .recent-row { box-shadow: 4px 4px 0 #FF5CA8; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .recent-row .code { border-color: #0A0A0A; color: #0A0A0A; }
/* le message d'erreur de l'étape code */
[data-s2] .s2 .join-err { display: none; font-family: var(--font-d); font-size: 12px; letter-spacing: 1px;
  background: var(--red); color: var(--paper); border: 3px solid var(--ink); padding: 8px 11px; }
[data-s2] .s2 .join-err.show { display: block; }
/* la grille des styles d'avatar et la rangée de couleurs (play/03_avatar.js,
   qui n'est pas de ce chantier : il rend `.ava-opt.sel` et `.color-sw.sel`). */
/* ⚠ PLUS DE SCROLL DANS LE SCROLL. `play.css` plafonnait la grille à 148 px
   avec son propre défilement : on voyait une bande de visages tranchés en deux
   au bas du cadre, et il fallait faire défiler une zone À L'INTÉRIEUR d'une
   page qui défile déjà — pénible au doigt. Les 13 styles tiennent en quatre
   rangées, la page les montre tous, rien n'est coupé. */
[data-s2] .s2 .ava-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px;
  max-height: none; overflow: visible;
}
[data-s2] .s2 .ava-grid .ava-opt { border: 3px solid var(--ink); background: var(--paper); box-shadow: 3px 3px 0 var(--ink);
  padding: 3px; cursor: pointer; overflow: hidden; display: block; }
[data-s2] .s2 .ava-grid .ava-opt.sel { background: var(--yellow); box-shadow: 3px 3px 0 var(--magenta); }
[data-s2] .s2 .ava-grid .ava-opt .ava-emo { width: 100%; height: auto; aspect-ratio: 1; border: 0; box-shadow: none; }
[data-s2] .s2 .s2-cols .color-sw { flex: 1; height: 24px; border: 2.5px solid var(--ink); cursor: pointer; }
[data-s2] .s2 .s2-cols .color-sw.sel { border-width: 5px; }
html[data-skin="neon"][data-theme] [data-s2] .s2 :is(.s2-cols .color-sw, .ava-grid .ava-opt) { border-color: #0A0A0A; }

/* ── 8. L'AVATAR ÉQUIPÉ DANS UN AVATAR DE PROTO ─────────────────────────────
   AVATARS.box() / QZ.framedAvatar() rendent `.ava-emo` (et `.ava-fr`), qui
   portent DÉJÀ leur bord de 3 px (brutal.css). Posés dans le `.avatar` de
   proto, qui a le sien, ça faisait un double cadre. Même arbitrage que
   saison2-app.css applique aux cinq onglets. */
[data-s2] .s2 .avatar > :is(.ava-emo, .ava-fr) { width: 100%; height: 100%; border: 0; box-shadow: none; }
[data-s2] .s2 .ava-fr > .ava-emo { border: 0; }
[data-s2] .s2 .avatar > :is(.ava-emo, .ava-fr) img { width: 100%; height: 100%; display: block; }

/* ── 9. LE BOUTON « CONTINUER » DE REJOINDRE ────────────────────────────────
   play/05_join-flow.js écrit `joinBtn.textContent` et `joinBtn.disabled` : le
   nœud doit rester un <button> SANS enfant, donc il ne peut pas porter le
   `.cta > .bd` de proto. On lui donne la même masse et la même ombre dure. */
[data-s2] .s2 .join-cta { flex-shrink: 0; width: 100%; font-family: var(--font-d); font-size: 18px;
  letter-spacing: 2px; text-align: center; padding: 14px; cursor: pointer;
  border: var(--bd-strong) solid var(--ink); background: var(--magenta); color: var(--paper);
  box-shadow: var(--sh-cta) var(--sh-cta) 0 var(--ink); }
/* le même appui que partout ailleurs (socle › « UN SEUL GESTE ») : ce bouton
   s'enfonçait de --sh-cta et perdait toute son ombre, un geste à lui seul. */
[data-s2] .s2 .join-cta:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }
[data-s2] .s2 .join-cta:disabled { background: var(--gray2); color: color-mix(in srgb, var(--ink) 45%, transparent); cursor: default; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .join-cta { border-color: #0A0A0A; color: #0A0A0A; box-shadow: var(--sh-cta) var(--sh-cta) 0 #FFD600; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .join-cta:disabled { background: #3E2A3B; color: rgba(246,238,227,.42); border-color: #FF5CA8; box-shadow: none; }

/* ── 10. L'ACTION AU BOUT D'UNE LIGNE DE FORMAT ─────────────────────────────
   La maquette pose l'action (chevron, prix, pastille) en dernier enfant de
   `.bd` ; l'app la REMPLACE quand l'état change (verrou levé, format choisi),
   d'où un conteneur stable. */
[data-s2] .s2 .fmt-act { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
[data-s2] .s2 .fmt-act .s2-tick { width: 26px; height: 26px; }
/* le champ « titre du quiz » de l'éditeur est un vrai <input> posé dans `.s2-ttl .v` */
[data-s2] .s2 .s2-ttl input.v { border: 0; background: none; outline: none; color: inherit; padding: 0; }

/* ── 7. GRAND ÉCRAN ─────────────────────────────────────────────────────────
   Le téléphone est la base. Sur tablette et PC, l'écran reste centré et cesse
   de s'étirer : au-delà, une carte inclinée devient un trapèze (cf. la note du
   brandbook sur les cartes droites en grand). */
@media (min-width: 720px) {
  section.screen[data-s2] > .s2 { max-width: 560px; margin: 0 auto; inset: 0 auto; width: 100%;
    border-left: 4px solid var(--ink); border-right: 4px solid var(--ink); }
}
@media (min-width: 1024px) {
  section.screen[data-s2] > .s2 { max-width: 640px; }
}

/* ── 11. LA TUILE DE PACK : CE QUE LA MAQUETTE FIGEAIT ──────────────────────
   Le socle dessine `.s2-pk` (fond, bord, ombre, icône, pas). L'app y ajoute
   trois états que la maquette ne montrait pas : le squelette d'attente, le
   badge NOUVEAU, et la tuile ÉCARTÉE (le Mix mélange déjà tout). */
[data-s2] .s2 .s2-pk > :is(.stepper, .s2-more) { margin-top: auto; }
/* ÉCARTÉE : le Mix et les packs ne se prennent pas ensemble */
[data-s2] .s2 .s2-pk.excl { filter: grayscale(.85); opacity: .55; }
/* SQUELETTE : le temps que l'état du compte arrive (jamais « tout verrouillé » qui clignote) */
[data-s2] .s2 .s2-pk.pk-skel { background: var(--gray2); box-shadow: 4px 4px 0 var(--ink); pointer-events: none; }
[data-s2] .s2 .s2-pk.pk-skel .sk { display: block; background: color-mix(in srgb, var(--ink) 16%, transparent); }
[data-s2] .s2 .s2-pk.pk-skel .sk-ic { width: 30px; height: 30px; }
[data-s2] .s2 .s2-pk.pk-skel .sk-nm { width: 80%; height: 13px; margin-top: 6px; }
[data-s2] .s2 .s2-pk.pk-skel .sk-ds { width: 50%; height: 8px; margin-top: 6px; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .s2-pk.pk-skel { background: #3E2A3B; box-shadow: 4px 4px 0 #FF5CA8; }

/* ── 12. LE +18 DU MODE SOIRÉE QU'ON A OUBLIÉ DE COCHER ─────────────────────
   Le garde-fou doit se VOIR : la ligne passe en rouge et sursaute une fois. */
[data-s2] .s2 #soireeGate.needcheck > .bd { background: var(--red); color: var(--paper); animation: s2h-shake .32s; }
[data-s2] .s2 #soireeGate.needcheck .desc { color: rgba(255,254,247,.72); }
@keyframes s2h-shake { 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }

/* ── 13. DEUX NOMS DE CLASSE DÉJÀ PRIS ─────────────────────────────────────
   `saison2-socle.css` est GÉNÉRÉ : on ne l'édite pas, on arbitre ici.
   · `.s2-ttl` est aussi le titre d'un format de la saison 2 (saison2.css,
     `flex:1`) : la barre du titre du quiz s'étirait sur tout l'écran.
   · `.s2-big` sert DEUX fois dans le socle — le titre d'une carte, et une
     taille d'emoji (56×56). Sur REJOINDRE et NIVEAU, c'est un TITRE.
   On redit la valeur du socle, et rien de plus. */
[data-s2] .s2 .s2-ttl { flex: 0 0 auto; font-size: unset; letter-spacing: unset; }
#screen-rapide .s2-big, #screen-niveau .s2-big, #screen-recap .s2-big, #screen-join .s2-big { width: auto; height: auto; }
/* play.css centre le contenu d'une étape de REJOINDRE : la maquette l'aligne à gauche */


/* ── 14. LES EMOJIS RENDUS PAR LE JS ────────────────────────────────────────
   `QZ.noto()` pose la classe `.noto` (brutal.css), la maquette pose `.nemoji`
   (proto.css, taille 1em). Là où le JS n'a pas pu passer `nemoji`, on donne à
   `.noto` la taille que la maquette attend à cet endroit. */
[data-s2] .s2 .s2-scan .qr-emoji .noto { width: 34px; height: 34px; display: block; }
[data-s2] .s2 .btn .noto, [data-s2] .s2 .sticker .noto { width: 15px; height: 15px; }
[data-s2] .s2 .s2-cat .noto { width: 13px; height: 13px; }

/* ── 15. LA PASTILLE ────────────────────────────────────────────────────────
   host.css redéfinit `.pill` pour l'ancienne page hôte : fond JAUNE d'office,
   bord 3 px, padding 5/12. Dans la maquette une pastille est CRÈME, et le
   jaune se demande (`.pill.yellow`). On redit proto.css, à l'identique. */
[data-s2] .s2 .pill { border: 2.5px solid var(--ink); background: var(--paper);
  height: 30px; padding: 0 11px; letter-spacing: .5px; font-size: 13px; }
[data-s2] .s2 .pill.yellow { background: var(--yellow); }
[data-s2] .s2 .pill.cyan { background: var(--cyan); }
[data-s2] .s2 .pill.green { background: var(--green); }
[data-s2] .s2 .pill.red { background: var(--red); color: var(--paper); }

/* ── 16. ABÎME : LE GRIS « ÉTEINT » N'EXISTE PAS ENCORE ─────────────────────
   `--gray2` n'est redéfini que par la peau NÉON (brutal.css). En ABÎME il
   reste le gris clair du thème crème : un format verrouillé ou un bouton
   éteint devenait du clair sur du clair, avec une encre crème par-dessus.
   On pose la surface sombre d'ABÎME (`--gray` = #2A2A2A) là où on s'en sert. */
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 :is(.listcard.s2-off, .listcard.s2-soon) > .bd,
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 .cta:is([data-disabled="true"], .off) > .bd,
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 .join-cta:disabled,
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 .s2-prow.vide,
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 .s2-pk.pk-skel {
  background: #2A2A2A; color: color-mix(in srgb, var(--ink) 55%, transparent);
}

/* ── 17. L'ÉDITION DÉTAILLÉE EST UN ÉCRAN D'ORDINATEUR ──────────────────────
   `.ed-main / #panel` porte le panneau d'édition question par question. Sur
   téléphone on pioche, on importe et on lance (c'est ce que dit le bandeau
   « ÇA S'ÉCRIT SUR ORDI ») : le panneau est une grille large qui débordait la
   colonne. On le sort de l'écran téléphone, on le rend au grand écran. */
[data-s2] .s2 .ed-main { display: none; }
@media (min-width: 1024px) { [data-s2] .s2 .ed-main { display: block; } }

/* ── 18. UN CHAMP QUI A LE FOCUS NE DEVIENT PAS BLANC EN PEAU SOMBRE ────────
   proto.css éclaircit le fond d'un champ actif (`.input:focus { background:#fff }`)
   pour la peau crème. En ABÎME et en NÉON l'encre est crème : on écrivait du
   clair sur du blanc. On garde le signal (l'ombre magenta) et on rend la
   surface sombre. Même chose pour la case de code, qui passe en jaune. */
html[data-theme="abime"]:not([data-skin="neon"]) [data-s2] .s2 .input:focus { background: #2A2A2A; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .input:focus { background: #3E2A3B; }
html[data-skin="neon"][data-theme] [data-s2] .s2 .codecells .cell:focus,
html[data-skin="neon"][data-theme] [data-s2] .s2 .codecells .cell.filled { color: #0A0A0A; border-color: #0A0A0A; }

/* ── 12. LA CROIX QUI RETIRE UN PACK ────────────────────────────────────────
   La maquette 33 ne montre qu'un pas (− n +) : pour sortir du MIX SURPRISE,
   qui démarre à 5, il fallait cinq appuis — et une tuile devenue « excl »
   (Mix pris à côté) ou verrouillée ne répondait plus du tout. On rend la
   croix qui existait avant la saison 2 : un clic, le pack retombe à 0.
   Elle est TRACÉE (deux barres), jamais le glyphe ✗, et elle passe AU-DESSUS
   du voile « verrouillé » — c'est là qu'on en a le plus besoin. */
[data-s2] .s2 .s2-pk .s2-pkx {
  position: absolute; top: var(--bd); right: var(--bd); z-index: 6;
  width: 28px; height: 28px; cursor: pointer;
  /* les tuiles de pack portent leur couleur en dur (cyan, jaune, vert…) dans
     TOUS les thèmes : le bord et l'ombre de la croix restent donc de l'encre
     fixe, sinon ils viraient au blanc en ABÎME / NÉON et disparaissaient. */
  background: var(--red); border: 2.5px solid #0A0A0A; box-shadow: 2px 2px 0 #0A0A0A;
  -webkit-tap-highlight-color: transparent;
}
[data-s2] .s2 .s2-pk .s2-pkx i { position: absolute; left: 50%; top: 50%; display: block; }
[data-s2] .s2 .s2-pk .s2-pkx i::before,
[data-s2] .s2 .s2-pk .s2-pkx i::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 15px; height: 3px; margin: -1.5px 0 0 -7.5px; background: var(--paper);
}
[data-s2] .s2 .s2-pk .s2-pkx i::before { transform: rotate(45deg); }
[data-s2] .s2 .s2-pk .s2-pkx i::after { transform: rotate(-45deg); }
[data-s2] .s2 .s2-pk .s2-pkx:active { transform: translate(2px, 2px); box-shadow: none; }
/* tuile noire (le MIX) : une ombre noire ne se verrait pas, et `--paper`
   devient sombre en ABÎME / NÉON. Elle passe donc au JAUNE, dans tous les
   thèmes — un bloc sombre porte toujours une ombre colorée. */
[data-s2] .s2 .s2-pk.dk .s2-pkx { box-shadow: 2px 2px 0 var(--yellow); }
/* la croix garde sa place quand le pas est là : le pas s'arrête avant elle */
[data-s2] .s2 .s2-pk:has(.s2-pkx) .stepper { padding-right: 30px; }


/* ── LE BANDEAU DE NOTIFICATION NE BLOQUE PLUS « REJOINDRE » ────────────────
   ⚠ BUG BLOQUANT, trouvé en testant le doigt au centre du bouton : le bandeau
   « Sois alerté de tes nouveaux défis » (`.pwa-banner`, position:fixed;
   bottom:12px) se posait PAR-DESSUS le bouton REJOINDRE. Le clic partait dans
   le bandeau : on tapait son code, on appuyait, et il ne se passait rien.
   Le même piège avait déjà été corrigé pour les cinq onglets — il restait sur
   les écrans qui portent un CTA collé en bas. Le bandeau passe au-dessus de
   lui (le CTA fait 18px de texte + 28 de padding + 8 de bord ≈ 62px). */
body:has(#screen-join.active) .pwa-banner,
body:has(.screen.active .join-cta) .pwa-banner {
  bottom: calc(62px + 12px + env(safe-area-inset-bottom));
}


/* ── LE BADGE « CODE DE LA ROOM » N'EST PLUS COUPÉ ──────────────────────────
   `.s2-scroll` n'a pas de marge haute et cache ce qui dépasse. Le sticker est
   penché et porte son ombre en `::before` : son coin haut-gauche sortait de la
   zone et se faisait trancher net par le bord de l'écran. On lui rend la
   hauteur qu'il lui faut — 8 px, la valeur de son inclinaison plus l'ombre. */
#screen-join .s2-scroll { padding-top: 8px; }

/* ── LE CHOIX DES COULEURS ──────────────────────────────────────────────────
   ⚠ La pastille choisie passait son bord de 2,5 à 5 px : le noir mangeait la
   couleur par l'intérieur, et comme les bords comptent dans la largeur, toute
   la rangée se décalait d'un cran. Edwin : « lorsqu'on veut sélectionner les
   couleurs, c'est mal fait avec les bordures noires ».
   La pastille garde exactement sa taille et son bord. Ce qui la désigne, c'est
   une COCHE TRACÉE en CSS — jamais le glyphe — et l'ombre dure de la maison. */
/* ⚠ `play.css` leur donne `width:28px` FIXE et agrandit la choisie de 18 %
   (`transform: scale(1.18)`) : la rangée se décalait à chaque changement et les
   pastilles n'avaient plus la même largeur. On neutralise les deux. */
#screen-join .s2-cols .color-sw {
  position: relative; flex: 1; width: auto; height: 26px;
  border: 3px solid var(--ink); box-shadow: none; transform: none; cursor: pointer;
}
#screen-join .s2-cols .color-sw.sel {
  border-width: 3px; transform: none; box-shadow: 3px 3px 0 var(--ink);
}
#screen-join .s2-cols .color-sw.sel::after {
  content: ''; position: absolute; left: 50%; top: 48%;
  width: 6px; height: 11px; margin: -7px 0 0 -3px;
  border: solid #FFFEF7; border-width: 0 3px 3px 0; transform: rotate(45deg);
}
html[data-skin="neon"][data-theme] #screen-join .s2-cols .color-sw.sel { box-shadow: 3px 3px 0 #FF2E93; }

/* ── LE CHOIX DES TÊTES ─────────────────────────────────────────────────────
   Edwin : « le choix des avatars, je pense qu'ils sont trop grands ». À quatre
   colonnes, une tête faisait 80 px et les douze styles couvraient un demi-
   écran. À six, elles font 52 px : deux rangées suffisent, et le pseudo remonte
   au-dessus du pli. */
[data-s2] .s2 .ava-grid { grid-template-columns: repeat(6, 1fr); gap: 6px; }


/* ══ LE TUNNEL DE CRÉATION ═════════════════════════════════════════════════

   1 · LE FIL DES QUATRE ÉTAPES
   La coche de l'étape franchie était tracée par deux barres de 2 px : à cette
   taille elle ressemblait à un trait, pas à une coche. Edwin : « je ne sais pas
   si tu as voulu mettre un check, mais il est coupé, on ne le voit pas ».
   On la retrace plus franche — toujours en CSS, jamais le glyphe — et les
   quatre cases prennent l'ombre dure qui manquait. */
[data-s2] .s2-way span { box-shadow: 3px 3px 0 var(--ink); }
/* ⚠ TROISIÈME PASSE. Edwin, capture à l'appui : « l'icône est coupée ».
   Les deux barres étaient posées en `bottom`, donc la branche longue sortait
   de la boîte de 11 px et se faisait rogner. On dessine la coche comme
   partout ailleurs (deux barres tournées, ancrées en haut), dans une boîte
   qui la contient en entier. */
[data-s2] .s2-wtick { position: relative; width: 13px; height: 13px; margin-right: 6px;
  display: inline-block; vertical-align: -2px; overflow: visible; }
[data-s2] .s2-wtick::before, [data-s2] .s2-wtick::after { content: ''; position: absolute; background: currentColor; }
[data-s2] .s2-wtick::before { width: 3px; height: 7px; left: 2px; top: 4px; transform: rotate(-45deg); transform-origin: 50% 100%; }
[data-s2] .s2-wtick::after  { width: 3px; height: 13px; left: 5px; top: -2px; transform: rotate(40deg); transform-origin: 50% 100%; }
html[data-skin="neon"][data-theme] [data-s2] .s2-way span { box-shadow: 3px 3px 0 #FF2E93; }

/* 2 · LE CRAN CHOISI SE VOIT — SANS LISERÉ COLORÉ
   ⚠ J'avais posé un bandeau de couleur en haut de chaque carte : Edwin ne l'a
   jamais demandé et l'a trouvé moche. Retiré. Ce qui dit la difficulté, c'est
   la jauge de cinq carrés, déjà présente, et l'aplat de la carte choisie. */
[data-s2] .s2-dif { --cran: var(--cyan); }
[data-s2] .s2-dif[data-diff="1"] { --cran: #5BE885; }
[data-s2] .s2-dif[data-diff="2"] { --cran: #B8E986; }
[data-s2] .s2-dif[data-diff="3"] { --cran: var(--yellow); }
[data-s2] .s2-dif[data-diff="4"] { --cran: #FF9F45; }
[data-s2] .s2-dif[data-diff="5"] { --cran: #FF5252; }
[data-s2] .s2-dif .g i.f { background: var(--cran); }
[data-s2] .s2-dif.on { background: var(--cran); color: #0A0A0A; }
html[data-skin="neon"][data-theme] [data-s2] .s2-dif .g i.f { background: var(--cran); }
html[data-skin="neon"][data-theme] [data-s2] .s2-dif.on { background: var(--cran); color: #0A0A0A; }

/* 3 · SUIVANT RESTE FERMÉ TANT QU'AUCUN CRAN N'EST CHOISI
   Edwin : « quand on vient sur le niveau et qu'on n'a rien sélectionné, on peut
   aller sur suivant, ce qui ne devrait pas être le cas ». Même traitement que
   l'étape FORMAT, qui portait déjà `data-disabled`. */
[data-s2] .s2 .cta[data-disabled="true"] { opacity: .45; pointer-events: none; }

/* 4 · LE BANDEAU DE NOTIFICATION NE COUVRE PLUS « SUIVANT »
   Même piège que sur REJOINDRE : `.pwa-banner` est collé en bas et se posait
   par-dessus le bouton de l'étape. Ici on ne pouvait même plus le voir. */
body:has(#screen-packs.active) .pwa-banner,
body:has(#screen-niveau.active) .pwa-banner,
body:has(#screen-format.active) .pwa-banner,
body:has(#screen-recap.active) .pwa-banner {
  bottom: calc(62px + 12px + env(safe-area-inset-bottom));
}


/* l'adresse LAN du salon (copier l'adresse) : dernier bouton qui gardait
   l'enfoncement de 4 px de brutal.css. Même geste que tout le reste. */
[data-s2] .ls-addr:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }



/* ============================================================================
   LE LOBBY — maquette validée s28, écran 4
   ----------------------------------------------------------------------------
   Recopié de design-mockups/s28-refonte-saison2.html (règles .jr-*, lignes
   405-468), avec les tokens de l'app : --line → --ink, --shadow → --ink (et le
   magenta en NÉON), --surface → --paper, --surface2 → --gray2, --text-mut →
   l'encre à 55 %. Rien n'est réinterprété : mêmes tailles, mêmes bords, mêmes
   ombres, mêmes inclinaisons.
   ========================================================================== */

/* le format, en haut à droite, penché */
#screen-lobby[data-s2] .jr-fpill {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-d); font-size: 12px; letter-spacing: .5px;
  background: var(--magenta); color: #FFFEF7;
  border: 2.5px solid var(--ink); box-shadow: 3px 3px 0 var(--ink);
  padding: 5px 9px; transform: rotate(2deg); white-space: nowrap;
}
#screen-lobby[data-s2] .jr-fpill .nemoji { width: 14px; height: 14px; }

/* FILE LE CODE AUX POTES + les cellules géantes */
#screen-lobby[data-s2] .jr-clabel {
  font-family: var(--font-m); font-weight: 700; font-size: 9px; letter-spacing: 2px;
  color: color-mix(in srgb, var(--ink) 55%, transparent); text-align: center; margin: 6px 0 9px;
}
#screen-lobby[data-s2] .jr-code { display: flex; gap: 9px; justify-content: center; cursor: pointer; }
#screen-lobby[data-s2] .jr-code .c {
  width: 48px; height: 62px; display: grid; place-items: center;
  font-family: var(--font-d); font-size: 31px;
  border: var(--bd-strong) solid var(--ink); box-shadow: 5px 5px 0 var(--ink);
  background: var(--yellow); color: #0A0A0A; transform: rotate(-1.5deg);
}
#screen-lobby[data-s2] .jr-code .c:nth-child(2n) { transform: rotate(1.5deg); }
#screen-lobby[data-s2] .jr-code:active .c { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); }

/* le QR + le lien à coller dans le groupe */
#screen-lobby[data-s2] .jr-share {
  display: flex; align-items: center; gap: 13px; margin-top: 18px;
  border: var(--bd) solid var(--ink); box-shadow: 4px 4px 0 var(--ink);
  background: var(--paper); padding: 12px;
}
#screen-lobby[data-s2] .jr-share .jr-qr { width: 88px; height: 88px; flex: 0 0 auto; }
#screen-lobby[data-s2] .jr-share .mid { flex: 1; min-width: 0; }
#screen-lobby[data-s2] .jr-share .l {
  font-family: var(--font-d); font-size: 14px; letter-spacing: .5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#screen-lobby[data-s2] .jr-share .m {
  font-family: var(--font-m); font-weight: 700; font-size: 8.5px;
  color: color-mix(in srgb, var(--ink) 55%, transparent); margin-top: 3px;
}
#screen-lobby[data-s2] .jr-share .acts { display: flex; gap: 6px; margin-top: 8px; }
#screen-lobby[data-s2] .jr-share .acts .btn { flex: 1; min-width: 0; font-size: 10px; padding: 6px 6px; gap: 5px; }
#screen-lobby[data-s2] .jr-share .acts .nemoji { width: 13px; height: 13px; }

/* le titre de section : LE MOT · la barre · le lien d'action */
#screen-lobby[data-s2] .shead {
  font-family: var(--font-d); font-size: 15px; letter-spacing: 1.5px;
  margin: 18px 0 10px; display: flex; align-items: center; gap: 10px;
}
#screen-lobby[data-s2] .shead .bar { flex: 1; height: 3px; background: var(--ink); }
#screen-lobby[data-s2] .shead a {
  font-family: var(--font-m); font-weight: 700; font-size: 10px; letter-spacing: .5px;
  color: var(--magenta); text-decoration: none; cursor: pointer; white-space: nowrap;
}

/* QUI ON INVITE ? — les potes, avec leur pastille de présence */
#screen-lobby[data-s2] .jr-inv { display: flex; gap: 10px; }
#screen-lobby[data-s2] .jr-fr {
  flex: 1; min-width: 0; border: 2.5px solid var(--ink); background: var(--paper);
  box-shadow: 3px 3px 0 var(--ink); padding: 9px 5px 8px; text-align: center;
}
#screen-lobby[data-s2] .jr-fr .aw { position: relative; display: inline-block; }
#screen-lobby[data-s2] .jr-fr .aw .avatar { width: 34px; height: 34px; }
#screen-lobby[data-s2] .jr-fr .dt {
  position: absolute; top: -5px; right: -5px; width: 13px; height: 13px;
  background: var(--green); border: 2.5px solid var(--ink);
}
#screen-lobby[data-s2] .jr-fr.off .dt { background: #C8C8C8; }
#screen-lobby[data-s2] .jr-fr.off .aw .avatar { filter: grayscale(1); opacity: .6; }
#screen-lobby[data-s2] .jr-fr .nm {
  font-family: var(--font-d); font-size: 10px; letter-spacing: .3px; margin-top: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#screen-lobby[data-s2] .jr-fr .ac {
  display: block; margin-top: 5px; width: 100%;
  font-family: var(--font-d); font-size: 8.5px; letter-spacing: .5px;
  border: 2px solid var(--ink); box-shadow: 2px 2px 0 var(--ink); padding: 4px 2px;
  background: var(--magenta); color: #FFFEF7; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#screen-lobby[data-s2] .jr-fr .ac.sent { background: var(--green); color: #0A0A0A; }
#screen-lobby[data-s2] .jr-fr .ac.dis {
  background: var(--gray2); color: color-mix(in srgb, var(--ink) 55%, transparent); cursor: default;
}
#screen-lobby[data-s2] .jr-fr .plus {
  font-family: var(--font-d); font-size: 20px; height: 34px; display: grid; place-items: center;
  color: color-mix(in srgb, var(--ink) 55%, transparent);
}

/* le toast d'arrivée */
/* ⚠ Edwin : « le cadre est trop long et il est penché ; il faut qu'il soit
   droit et qu'il s'adapte ». Dans un conteneur flex, `inline-block` ne suffit
   pas : l'élément s'étire sur toute la largeur. `align-self` le ramène à la
   taille de son texte, et on retire l'inclinaison. */
#screen-lobby[data-s2] .jr-toast {
  display: inline-block; width: auto; max-width: 100%; align-self: flex-start;
  margin-bottom: 12px; transform: none;
  font-family: var(--font-d); font-size: 11px; letter-spacing: .5px; padding: 7px 11px;
  background: var(--green); color: #0A0A0A;
  border: 2.5px solid var(--ink); box-shadow: 3px 3px 0 var(--ink);
}

/* LE MUR DE JOUEURS — quatre par ligne */
#screen-lobby[data-s2] .jr-wall { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px 10px; margin-top: 4px; }
#screen-lobby[data-s2] .jr-pl {
  position: relative; min-width: 0; border: 2.5px solid var(--ink); background: var(--paper);
  box-shadow: 3px 3px 0 var(--ink); padding: 9px 4px 7px; text-align: center;
}
#screen-lobby[data-s2] .jr-pl .avatar { margin: 0 auto; width: 40px; height: 40px; }
#screen-lobby[data-s2] .jr-pl .nm {
  font-family: var(--font-d); font-size: 9px; letter-spacing: .3px; margin-top: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#screen-lobby[data-s2] .jr-pl.me { background: var(--yellow); }
#screen-lobby[data-s2] .jr-pl.me .nm { color: #0A0A0A; }
#screen-lobby[data-s2] .jr-pl .cr {
  position: absolute; top: -13px; left: 50%; transform: translateX(-50%) rotate(-8deg);
  width: 18px; height: 18px; z-index: 2;
}
/* ⚠ le badge et la croix RESTENT DANS la tuile. Débordants (comme sur la
   maquette, qui n'a qu'une tuile à la fois sous les yeux), ils se marchaient
   dessus dans la gouttière de 10 px : le BOT d'une tuile touchait la croix de
   sa voisine. */
#screen-lobby[data-s2] .jr-pl .bt {
  position: absolute; top: 3px; right: 3px; z-index: 2;
  font-family: var(--font-d); font-size: 7.5px; letter-spacing: .5px;
  background: var(--cyan); color: #0A0A0A; border: 2px solid var(--ink);
  box-shadow: 2px 2px 0 var(--ink); padding: 1px 4px; transform: rotate(3deg);
}
#screen-lobby[data-s2] .jr-pl.new { transform: rotate(-2deg); }
#screen-lobby[data-s2] .jr-pl.emp { border-style: dashed; background: none; box-shadow: 2px 2px 0 var(--ink); }
#screen-lobby[data-s2] .jr-pl.emp .q {
  font-family: var(--font-d); font-size: 18px; height: 40px; display: grid; place-items: center;
  color: color-mix(in srgb, var(--ink) 45%, transparent);
}
#screen-lobby[data-s2] .jr-pl.emp .nm { color: color-mix(in srgb, var(--ink) 45%, transparent); }
/* l'action sur une tuile : ✕ pour exclure, ✏️ pour mon avatar — tracées en CSS */
#screen-lobby[data-s2] .jr-pl .s2-kick,
#screen-lobby[data-s2] .jr-pl .s2-pen { position: absolute; top: 3px; left: 3px; z-index: 2; width: 20px; height: 20px; }

/* LE PIED : la config d'un trait, la mise, puis DÉMARRER */
#screen-lobby[data-s2] .jr-foot {
  margin-top: auto; flex: none; background: var(--paper);
  border-top: var(--bd) solid var(--ink); padding: 10px 0 0;
}
#screen-lobby[data-s2] .jr-foot .rc {
  font-family: var(--font-m); font-weight: 700; font-size: 9.5px; letter-spacing: .5px;
  color: color-mix(in srgb, var(--ink) 55%, transparent); text-align: center; margin-bottom: 10px;
}
#screen-lobby[data-s2] .jr-money { justify-content: center; margin-bottom: 10px; }
#screen-lobby[data-s2] .jr-money:empty, #screen-lobby[data-s2] .jr-money:not(:has(.pill:not([hidden]))) { display: none; }

/* ── NÉON : sur l'encre prune, l'ombre est magenta ─────────────────────── */
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] :is(.jr-share, .jr-fr, .jr-pl) { box-shadow: 3px 3px 0 var(--magenta); }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-share { box-shadow: 4px 4px 0 var(--magenta); }
/* les aplats vifs gardent leur encre et leur ombre noires */
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-code .c { border-color: #0A0A0A; box-shadow: 5px 5px 0 #0A0A0A; }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-pl.me { box-shadow: 3px 3px 0 #0A0A0A; border-color: #0A0A0A; }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-fpill { box-shadow: 3px 3px 0 var(--yellow); }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-toast { border-color: #0A0A0A; box-shadow: 3px 3px 0 #0A0A0A; }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-fr .ac { border-color: #0A0A0A; box-shadow: 2px 2px 0 #0A0A0A; }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-fr .ac.dis { background: var(--gray2); color: var(--ink); }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-pl .bt { border-color: #0A0A0A; box-shadow: 2px 2px 0 #0A0A0A; }
html[data-skin="neon"][data-theme] #screen-lobby[data-s2] .jr-pl.emp { box-shadow: 2px 2px 0 var(--magenta); }
/* pas encore de potes : une ligne, pas une carte vide en travers de l'écran */
#screen-lobby[data-s2] .jr-none {
  font-family: var(--font-m); font-weight: 700; font-size: 9px; letter-spacing: .5px; line-height: 1.5;
  color: color-mix(in srgb, var(--ink) 55%, transparent);
  border: 2.5px dashed color-mix(in srgb, var(--ink) 35%, transparent); padding: 10px 12px; text-align: center;
}
/* les badges de la partie, sous le code : format, questions, niveau, temps,
   mise, prix. Centrés, à la taille mesurée sur la maquette (10,5 / 5-8 / 26). */
#screen-lobby[data-s2] .jr-cfg { justify-content: center; flex-wrap: wrap; overflow: visible; margin-top: 14px; gap: 6px; }
#screen-lobby[data-s2] .jr-cfg .pill {
  font-size: 10.5px; letter-spacing: .4px; padding: 5px 8px; min-height: 26px; gap: 4px;
}
#screen-lobby[data-s2] .jr-cfg .pill .nemoji { width: 13px; height: 13px; }
/* les deux actions de section : de vrais boutons, pas des liens (Edwin : « bot,
   fais-le en bouton ; pareil pour tous ») */
#screen-lobby[data-s2] .shead .btn { flex: none; font-size: 10px; padding: 5px 9px; gap: 5px; }
#screen-lobby[data-s2] .shead .btn .nemoji { width: 14px; height: 14px; }
/* le panneau INVITER MES POTES : l'écran des potes, en plein écran */
.inv-ov {
  position: fixed; inset: 0; z-index: 90; background: rgba(10,10,10,.55);
  display: flex; align-items: flex-end; opacity: 0; transition: opacity var(--dur-s) var(--ease-out);
}
.inv-ov.show { opacity: 1; }
/* ⚠ PAS de classe `.s2` sur la feuille : elle pose position:absolute; inset:0
   (c'est le shell d'un écran entier) et le panneau remplissait l'écran pour
   trois lignes. La feuille garde donc ses propres bases. */
/* ⚠ ELLE PRENAIT TOUT L'ÉCRAN, SANS UN PIXEL D'AIR. Edwin : « la pop-up
   s'affiche mais ça prend tout l'écran, zéro espace, ce qui fait que c'est
   pas agréable à voir ». Elle était en `width: 100%`, collée aux quatre
   bords, avec un simple filet en haut : rien ne disait que c'était un
   panneau posé PAR-DESSUS le salon.
   Elle devient une vraie feuille : de l'air sur les côtés et en bas, un bord
   épais tout autour et l'ombre dure de la maison, et 78vh au plus pour qu'on
   voie toujours le salon derrière au-dessus d'elle. */
.inv-ov .inv-sheet {
  flex: 1 1 auto; min-width: 0;
  margin: 0 14px calc(14px + env(safe-area-inset-bottom));
  max-height: 78vh; display: flex; flex-direction: column;
  background: var(--paper);
  border: var(--bd-strong) solid var(--ink);
  box-shadow: var(--sh) var(--sh) 0 var(--magenta);
  padding: 14px 0; gap: 12px;
  transform: translateY(14px); transition: transform var(--dur-s) var(--ease-out);
}
.inv-ov .inv-sheet .s2-bar { display: flex; align-items: center; gap: 9px; flex: none; padding: 0 16px; }
.inv-ov.show .inv-sheet { transform: none; }
/* la feuille épouse son contenu : elle ne s'étire à 88vh que si la liste est
   longue. Sinon on avait un panneau plein écran pour trois lignes. */
/* la liste respire aussi : l'ombre dure des cartes a sa place à droite, et
   `overflow-x: clip` évite qu'elle se laisse pousser au doigt. */
.inv-ov .s2-scroll { flex: 0 1 auto; min-height: 0; overflow-y: auto; overflow-x: clip;
  padding: 0 16px 6px 14px; touch-action: pan-y; }
.inv-ov .s2-bar .page-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-skin="neon"][data-theme] .inv-ov .inv-sheet { border-top-color: var(--magenta); }
