/* ============================================================================
   LE LABORATOIRE · interface B · ÉTAPE 5 : HORS PARTIE
   ----------------------------------------------------------------------------
   Feuille de la page d'essai public/pupitre.html, chargée APRÈS pupitre/socle.css.
   Elle porte la mise en page, et seulement elle, de :
     #ecran-auth       connexion et inscription : l'accueil à grands boutons,
                       les formulaires (ils défilent dans leur panneau), les
                       boutons des réseaux sociaux, le message du serveur
     #ecran-salon      l'accueil du joueur connecté et le salon : tous ses états
     #ecran-profil     mon profil, la suppression du compte
     #ecran-stats      mes statistiques
   Clavier du téléphone : une page qui ne défile pas doit garder visible le
   champ qu'on remplit ; champs à 16 px au moins.
   Maquettes : data/maquettes-2026-10-07/B-suite/accueil.html, salon.html,
   profil.html, stats.html. Plan : docs/interface-b/plan-de-bascule.md, partie 3.

   Règles (les mêmes pour toutes les feuilles, gardées par
   test/pupitre-feuilles.test.js) : ne retouche pas socle.css ; CHAQUE
   sélecteur s'accroche à une pièce de cette étape (#ecran-auth, #ecran-salon,
   #ecran-profil, #ecran-stats, une pièce qu'ils contiennent, ou
   body[data-ecran="auth"], "salon", "profil", "stats",
   body[data-moment="hors"], body.sans-compte pour ce qui est hors de
   l'écran) : jamais de sélecteur nu (« .reponse { … } ») ni de réglage posé
   sur :root, qui changeraient les écrans des autres étapes sans que rien le
   dise (un réglage se redéfinit sur ton écran : #ecran-… { --taille-titre:
   … }) ; le nom d'une animation (@keyframes) commence par « hors-partie- » ;
   tout en « u », couleurs du thème ; pas de color-mix(), pas de :has(), pas de
   « inset: », pas de dvh hors de @supports ; aucune ressource en ligne.
   Mesurer : « npm run pupitre:mesurer » (mode d'emploi en tête de
   outils/mesurer-le-pupitre.mjs), sans retoucher l'outil : les états que tu
   veux mesurer dans outils/parcours-du-pupitre/hors-partie.mjs, et ce qui est voulu
   sur tes écrans (une étiquette, un décor, une pièce posée exprès sur une
   autre, une fenêtre qui rogne) par la propriété « --mesure » dans cette
   feuille. Un écran ne se centre jamais par justify-content (socle.css,
   section 13, « Un écran CENTRÉ »). Monte le « ?v= » de cette feuille, sur sa
   ligne de pupitre.html, quand tu la modifies.

   SOMMAIRE
     1. Ce que les quatre écrans partagent : matières, champs, et la place du
        professeur hors partie (sur téléphone : sa bande, au pied de l'écran)
     2. Connexion et inscription (#ecran-auth) : l'accueil, puis la fiche
     3. Accueil et salon (#ecran-salon)
     4. Mon profil (#ecran-profil)
     5. Mes statistiques (#ecran-stats)
   Ce que cette feuille attend de pupitre.js (bloc « hors partie ») : l'unité
   « u » tenue pendant que le clavier d'un téléphone est sorti, et le compte à
   rebours du salon ramené sur une ligne quand il porte des mots.
   ========================================================================== */


/* ============================================================================
   1. CE QUE LES QUATRE ÉCRANS PARTAGENT
   ========================================================================== */

/* Les matières et les mesures de cette feuille (préfixe --hp-), posées sur ses
   écrans.
     --hp-rivets   quatre rivets aux coins, en fonds : pour un panneau qui
                   DÉFILE à l'intérieur (le .rivete du socle est un
                   pseudo-élément, qui défilerait avec le contenu)
     --hp-carte    le verre d'une petite carte, et --hp-filet son filet
     --hp-debord   la place laissée aux ombres autour d'un écran sans habillage
                   (il rogne ce qui dépasse de lui, puisqu'il peut défiler)
     --hp-bulle    la hauteur de la bulle du professeur (celle du socle)
     --hp-bande    la bande du professeur : sa bulle et sa marge du bas
     --hp-retrait  d'où part une bulle posée à côté du professeur */
#ecran-auth, #ecran-salon, #ecran-profil, #ecran-stats {
  --hp-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%);
  --hp-rivets:
    var(--hp-rivet) left calc(8 * var(--u)) top calc(8 * var(--u)) / calc(8 * var(--u)) calc(8 * var(--u)) no-repeat,
    var(--hp-rivet) right calc(8 * var(--u)) top calc(8 * var(--u)) / calc(8 * var(--u)) calc(8 * var(--u)) no-repeat,
    var(--hp-rivet) left calc(8 * var(--u)) bottom calc(8 * var(--u)) / calc(8 * var(--u)) calc(8 * var(--u)) no-repeat,
    var(--hp-rivet) right calc(8 * var(--u)) bottom calc(8 * var(--u)) / calc(8 * var(--u)) calc(8 * var(--u)) no-repeat;
  --hp-carte: linear-gradient(180deg, rgba(var(--verre-haut), 0.84), rgba(var(--verre-bas), 0.92));
  --hp-filet: inset 0 0 0 max(1px, calc(1.2 * var(--u))) rgba(var(--metal-clair-rvb), 0.42), 0 0 0 1px rgba(0, 0, 0, 0.72);
  --hp-debord: calc(8 * var(--u));
  --hp-bulle: calc(var(--bulle-lignes) * var(--interligne-bulle) * var(--taille-bulle) + var(--bulle-haut) + var(--bulle-bas));
  --hp-bande: calc(var(--hp-bulle) + 10 * var(--u));
  --hp-retrait: calc(var(--largeur-professeur) - 2 * var(--u));
}

/* UN ÉCRAN SANS HABILLAGE : l'accueil sans compte, le salon et les
   statistiques ne sont plus UN panneau qui porte tout, mais des pièces posées
   sur le fond (une affiche, des boutons, des cartes). L'écran garde son
   défilement intérieur, en dernier recours (très petit téléphone) : il déborde
   donc de sa place de --hp-debord sur les côtés, pour que les ombres de ses
   pièces ne soient pas rognées. */
#ecran-auth:not(.formulaire), #ecran-salon, #ecran-stats {
  padding: 0 var(--hp-debord) var(--hp-bande);
  margin-left: calc(-1 * var(--hp-debord)); margin-right: calc(-1 * var(--hp-debord));
  border-radius: 0; background: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  align-items: stretch;
}

/* ---------- LA BANDE DU PROFESSEUR ----------
   Hors partie, la place de la bulle du professeur porte ce que la maquette lui
   fait dire : le slogan (accueil sans compte), l'invitation du salon, ou
   l'invitation à compléter son profil. Ce sont des pièces de l'écran, habillées
   en bulle et posées à la place de la sienne ; une vraie réplique (l'équipe du
   labo peut prendre la parole) s'ouvre par-dessus, au même endroit. Rien ne
   bouge quand il parle.
   Sur TÉLÉPHONE, le professeur et sa bulle ne prennent donc plus une rangée à
   eux sous les liens légaux : ils sont AU PIED DE L'ÉCRAN, dans une bande que
   l'écran leur réserve (--hp-bande), le professeur accoudé à gauche. Sur
   ORDINATEUR, la bulle garde sa rangée sous la scène (socle) : le salon
   s'étend jusqu'à elle, et y pose son invitation. */
#ecran-auth:not(.formulaire):not([hidden]) ~ .rampe-basse,
body[data-ecran="salon"] .rampe-basse,
body[data-ecran="stats"] .rampe-basse { display: contents; }
body[data-ecran="auth"] .professeur, body[data-ecran="salon"] .professeur, body[data-ecran="stats"] .professeur {
  grid-area: scene; align-self: end; justify-self: start; z-index: 2;
}
body[data-ecran="salon"] .bulle, body[data-ecran="stats"] .bulle {
  grid-area: scene; align-self: end; z-index: 3;
  margin-left: calc(var(--largeur-professeur) - 2 * var(--u));
  /* une vraie réplique s'ouvre exprès SUR la bulle de l'écran (dit à l'outil de mesure) */
  --mesure: chevauche;
}
/* Sur l'écran de connexion, personne n'est connecté : il ne dit jamais rien */
body[data-ecran="auth"] .bulle { display: none; }
/* Il laisse sa place aux formulaires (la fiche de connexion ou d'inscription,
   le profil), comme sur la maquette : c'est ce qui laisse voir le champ qu'on
   remplit quand le clavier est sorti. Sur le profil, sa bulle revient le temps
   d'une réplique. */
#ecran-auth.formulaire:not([hidden]) ~ .rampe-basse { display: none; }
body[data-ecran="profil"] .professeur,
body[data-ecran="profil"] .bulle-queue,
body[data-ecran="profil"] .bulle:not(.est-ouverte) { display: none; }

/* CE QUE LE PROFESSEUR A À CÔTÉ DE LUI (refait le 2026-10-09, hiérarchie des
   écrans hors partie : socle, section 12 bis). Ces pièces étaient habillées en
   bulle, du même verre cerclé que les boutons et que l'affiche : trois cadres
   de plus sur l'écran, et l'invitation du salon redisait dans sa bulle ce que
   le compte à rebours disait déjà. Elles sont maintenant DU TEXTE POSÉ À PLAT,
   à la place de la bulle :
     - à l'accueil sans compte, le slogan : une citation, en italique, derrière
       un filet de laiton ;
     - à l'accueil du joueur, le carnet (#salon-infos, section 3) : compléter
       son profil, la ligne du classement, les derniers vainqueurs. L'invitation
       du salon, elle, se lit dans le héros, sous le compte à rebours.
   La place a au moins la hauteur de la bulle (une vraie réplique s'y ouvre) ;
   un texte plus long la fait grandir vers le haut, et l'écran se resserre
   au-dessus (jamais de texte coupé). */
#ecran-auth:not(.formulaire) .slogan {
  position: relative; display: flex; align-items: center;
  min-height: var(--hp-bulle); margin: 0 0 calc(-1 * var(--hp-bulle)) calc(var(--hp-retrait) + 10 * var(--u));
  padding: 0 0 0 calc(13 * var(--u)); border-radius: 0; max-width: none;
  font-style: italic; font-size: var(--taille-bulle); line-height: var(--interligne-bulle); color: var(--texte-doux);
  text-align: left; text-wrap: balance; overflow-wrap: anywhere;
  text-shadow: 0 1px 2px #000, 0 0 calc(8 * var(--u)) rgba(0, 0, 0, 0.9);
  background: none;
}
/* le filet de la citation (décor) : il a la hauteur du texte, pas celle de la place */
#ecran-auth:not(.formulaire) .slogan::before {
  content: ''; position: absolute; left: 0; top: 50%; width: max(2px, calc(2.5 * var(--u))); height: calc(2.9 * var(--taille-bulle));
  transform: translateY(-50%); border-radius: calc(2 * var(--u));
  background: linear-gradient(180deg, var(--metal-vif), var(--metal-sombre));
}

@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : le professeur garde la rangée du socle, à côté des
     liens légaux ; le slogan est dans l'enseigne (section 2) */
  #ecran-auth:not(.formulaire):not([hidden]) ~ .rampe-basse,
  body[data-ecran="salon"] .rampe-basse,
  body[data-ecran="stats"] .rampe-basse { display: flex; }
  body[data-ecran="salon"] .bulle, body[data-ecran="stats"] .bulle { margin-left: 0; --mesure: seule; }
  #ecran-auth:not(.formulaire), #ecran-salon, #ecran-stats { padding-bottom: var(--hp-debord); }
  /* (« min-height: auto » et pas 0 : une pièce de grille au minimum nul
     laisserait sa rangée rétrécir sous elle quand la place manque, et
     passerait sur la pièce d'en dessous) */
  #ecran-auth:not(.formulaire) .slogan { min-height: auto; margin: 0; padding: calc(8 * var(--u)) calc(14 * var(--u)); }
  #ecran-auth:not(.formulaire) .slogan::before { content: none; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  /* ordinateur : le professeur a sa colonne et sa bulle sa rangée (socle) */
  #ecran-auth.formulaire:not([hidden]) ~ .rampe-basse { display: contents; }
  body[data-ecran="auth"] .professeur, body[data-ecran="salon"] .professeur, body[data-ecran="stats"] .professeur {
    grid-area: prof; justify-self: end;
  }
  body[data-ecran="profil"] .professeur { display: block; }
  body[data-ecran="profil"] .bulle-queue { display: block; }
  body[data-ecran="profil"] .bulle:not(.est-ouverte) { display: flex; }
  body[data-ecran="salon"] .bulle, body[data-ecran="stats"] .bulle { grid-area: bulle; margin-left: 0; z-index: 2; }
  body[data-ecran="stats"] .bulle { --mesure: seule; }
  #ecran-auth:not(.formulaire), #ecran-salon, #ecran-stats { padding-bottom: 0; }
  /* le slogan : à la place de la bulle du socle, mêmes marges */
  #ecran-auth:not(.formulaire) .slogan { margin: var(--ecart) 0 calc(16 * var(--u)) calc(14 * var(--u)); padding-left: calc(18 * var(--u)); }
}

/* UN PANNEAU QUI DÉFILE : la fiche d'un formulaire, le profil. Le verre simple
   du socle, et ses quatre rivets. */
#ecran-auth.formulaire, #ecran-profil {
  background: var(--hp-rivets), var(--verre-fond);
  text-align: left;
}

/* ---------- Les champs ----------
   Le NOM d'un champ court (« Email », « Mot de passe », « Pseudo ») : une
   petite étiquette gravée au-dessus de sa case, comme sur la maquette. La
   saisie, elle, reste à 16 px au moins (sinon l'iPhone zoome sur le champ). */
#ecran-auth form label, #form-profil > label, #form-suppression label {
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: max(11px, calc(11.5 * var(--u))); line-height: 1.25; color: var(--metal-clair);
  gap: calc(5 * var(--u));
  --mesure: etiquette;
}
/* (ce qu'on y écrit ne prend ni la graisse ni les capitales de l'étiquette) */
#ecran-auth form label > input, #form-profil > label > input, #form-profil > label > select, #form-suppression label > input {
  font-weight: 400; letter-spacing: 0; text-transform: none;
}
/* … sauf la phrase d'une case à cocher, qui se lit */
#ecran-auth form label.case {
  font-family: var(--police-texte); font-weight: 400; text-transform: none; letter-spacing: 0;
  font-size: var(--taille-texte); line-height: 1.35; color: var(--texte);
  gap: calc(12 * var(--u)); align-items: flex-start;
  --mesure: lu;
}
#ecran-auth form label.case > input { margin-top: calc(1 * var(--u)); }
#ecran-auth form label.case > span { min-width: 0; text-wrap: pretty; }
/* une note dans un formulaire : centrée, comme la phrase d'un écriteau */
#ecran-auth form .note { text-align: center; text-wrap: balance; }
#ecran-auth form .note strong { color: var(--accent-vif); font-weight: 700; overflow-wrap: anywhere; }

/* Un champ que le navigateur a rempli lui-même : ni fond jaune ni texte noir,
   le verre reste (le fond est repeint par une ombre intérieure, seul moyen), et
   la lueur du champ actif aussi. Deux règles : un navigateur qui ne connaît pas
   l'un des deux noms ignorerait la règle entière. */
#ecran-auth input:-webkit-autofill, #ecran-profil input:-webkit-autofill {
  -webkit-text-fill-color: var(--texte); caret-color: var(--texte);
  box-shadow:
    inset 0 0 0 calc(60 * var(--u)) 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);
}
#ecran-auth input:autofill, #ecran-profil input:autofill {
  -webkit-text-fill-color: var(--texte); caret-color: var(--texte);
  box-shadow:
    inset 0 0 0 calc(60 * var(--u)) 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);
}
#ecran-auth input:-webkit-autofill:focus-visible, #ecran-profil input:-webkit-autofill:focus-visible {
  box-shadow:
    inset 0 0 0 calc(60 * var(--u)) rgb(var(--verre-bas)),
    0 0 0 max(1.5px, calc(2 * var(--u))) var(--accent),
    0 0 calc(14 * var(--u)) rgba(var(--accent-rvb), 0.45);
}


/* ============================================================================
   2. CONNEXION ET INSCRIPTION (#ecran-auth)
   ----------------------------------------------------------------------------
   Deux temps (la classe .formulaire, posée par app.js, passe de l'un à l'autre) :
     L'ACCUEIL   l'enseigne (le titre et une phrase) dans un panneau riveté,
                 les portes (trois grands boutons, puis les réseaux sociaux),
                 et le slogan, dans la bulle du professeur
     LA FICHE    le seul formulaire choisi, dans un panneau qui prend la hauteur
                 de son contenu et défile à l'intérieur s'il le faut
   ========================================================================== */

/* ---------- L'accueil ----------
   Une grille d'une colonne. Le panneau de l'enseigne n'existe pas dans la page
   (le titre et la phrase sont deux pièces de l'écran) : c'est le ::before de
   l'écran, étalé sous leurs rangées ; ::after pose ses rivets. Deux rangées
   souples, au-dessus et au-dessous, donnent au panneau la hauteur qui reste et
   tiennent l'enseigne en son milieu. */
#ecran-auth:not(.formulaire) {
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-rows:
    minmax(calc(14 * var(--u)), 1fr) auto auto minmax(calc(14 * var(--u)), 1fr)
    auto auto auto auto auto;
  gap: 0; justify-items: stretch; align-items: start;
}
#ecran-auth:not(.formulaire)::before, #ecran-auth:not(.formulaire)::after {
  content: ''; grid-column: 1; grid-row: 1 / 5; align-self: stretch; margin: 0;
  border-radius: calc(16 * var(--u)); pointer-events: none;
}
#ecran-auth:not(.formulaire)::before {
  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);
}
#ecran-auth:not(.formulaire)::after { background: var(--hp-rivets); opacity: 0.9; }
#ecran-auth:not(.formulaire) > * { grid-column: 1; position: relative; z-index: 1; }
#ecran-auth:not(.formulaire) .auth-titre { grid-row: 2; margin: 0 calc(16 * var(--u)); font-size: calc(var(--taille-titre) * 1.12); }
#ecran-auth:not(.formulaire) .auth-sous-titre {
  grid-row: 3; justify-self: center; margin: calc(12 * var(--u)) calc(16 * var(--u)) 0;
  max-width: min(calc(100% - 32 * var(--u)), 46ch); color: var(--texte); text-wrap: balance;
}
/* (un mot mis en valeur : en gras, à la couleur du texte. Il avait la couleur des liens, sans leur trait : on pouvait croire qu'il se touchait) */
#ecran-auth:not(.formulaire) .lot-nom { font-weight: 700; color: var(--texte); }
/* LES PORTES, dans l'ordre de la hiérarchie (socle, section 12 bis) :
     l'action principale   « Se connecter », la seule touche de laiton
     les tuiles            « Créer un compte », « Essayer le jeu… », et « Voir le
                           classement général » quand son volet public est ouvert
     les réseaux sociaux   de petites touches de verre, derrière leur légende */
#ecran-auth:not(.formulaire) .auth-accueil { grid-row: 5; margin-top: var(--ecart-groupes); }
#ecran-auth:not(.formulaire) .auth-accueil > button { flex: none; }
#ecran-auth:not(.formulaire) .auth-portes { grid-row: 6; margin-top: var(--ecart-groupes); }
/* deux tuiles par rangée ; la troisième (« Essayer le jeu… », le plus long des libellés) prend alors la sienne */
#ecran-auth:not(.formulaire) .auth-portes > .tuile-action { flex: 1 1 40%; }
#ecran-auth:not(.formulaire) #btn-classement-visiteur { order: 2; }
#ecran-auth:not(.formulaire) #btn-essayer { order: 3; flex-basis: 46%; }
/* un compte de plus ; une fiole (l'essai) */
#btn-vers-inscription { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9.6' cy='8.05' r='4.1'/%3E%3Cpath d='M2.6 20.05c1.6-3.9 4.6-5.3 7-5.3 1.5 0 3.2.5 4.7 1.8M18.6 12.6v6.4M15.4 15.8h6.4'/%3E%3C/svg%3E"); }
#btn-essayer { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.4 3.8h5.2M10.2 3.8v5.6L5 18.2a1.5 1.5 0 0 0 1.3 2.2h11.4a1.5 1.5 0 0 0 1.3-2.2l-5.2-8.8V3.8M7.6 14.6h8.8'/%3E%3C/svg%3E"); }
#ecran-auth:not(.formulaire) #reseaux-accueil { grid-row: 7; margin-top: calc(var(--ecart-pieces) + 4 * var(--u)); }
#ecran-auth:not(.formulaire) #reseaux-note { grid-row: 8; margin-top: calc(6 * var(--u)); text-align: center; text-wrap: balance; color: var(--texte); text-shadow: 0 1px 3px #000, 0 0 8px #000; }
/* le slogan, à côté du professeur (section 1) */
#ecran-auth:not(.formulaire) .slogan { grid-row: 9; margin-top: var(--ecart-groupes); }

/* L'ACCUEIL TROP PLEIN (téléphone court ; le décor le mesure et pose « serre », pupitre.js,
   serrerLAccueilSansCompte) : volet public du classement ouvert et réseaux sociaux configurés, tout ne tient
   pas sous l'enseigne à 360 x 640. Les groupes se rapprochent, les tuiles passent leur pictogramme à gauche de
   leur libellé, et la place du slogan se resserre à la taille du professeur. Aucun texte ne rétrécit. */
#ecran-auth.serre:not(.formulaire) { --ecart-groupes: calc(12 * var(--u)); --hp-bulle: calc(84 * var(--u)); }
#ecran-auth.serre:not(.formulaire) .tuile-action { flex-direction: row; justify-content: center; align-items: center; gap: calc(8 * var(--u)); min-height: max(44px, calc(46 * var(--u))); padding: calc(4 * var(--u)) calc(8 * var(--u)); text-align: left; }

/* « Ou continuer avec » : la légende sur sa ligne, entre deux traits, puis une
   petite touche de verre par réseau social (deux par rangée sur téléphone).
   Des actions secondaires : leur nom en lettres courantes, comme une tuile. */
#reseaux-accueil { gap: calc(7 * var(--u)) var(--ecart-pieces); }
#reseaux-accueil .reseaux-legende {
  display: flex; align-items: center; justify-content: center; gap: calc(10 * var(--u));
  font-family: var(--police-texte); font-weight: 400; text-transform: none; letter-spacing: 0;
  font-size: var(--taille-note); line-height: 1.2; color: var(--texte-doux); text-shadow: 0 1px 2px #000, 0 0 calc(8 * var(--u)) rgba(0, 0, 0, 0.9);
}
#reseaux-accueil .reseaux-legende::before, #reseaux-accueil .reseaux-legende::after {
  content: ''; flex: 0 1 calc(34 * var(--u)); height: max(1px, calc(1.2 * var(--u)));
  background: rgba(var(--metal-clair-rvb), 0.45);
}
#reseaux-accueil .reseau-bouton {
  flex: 1 1 calc(120 * var(--u)); min-width: 0; justify-content: center; gap: calc(9 * var(--u));
  padding: 0 calc(12 * var(--u)); border-radius: calc(12 * var(--u));
  font-family: var(--police-texte); font-weight: 500; text-transform: none; letter-spacing: 0;
  font-size: var(--taille-texte); color: var(--texte); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  --pied: calc(3 * var(--u)); --course: calc(2 * var(--u));
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.07) 0%, rgba(255, 255, 255, 0) 24%),
    linear-gradient(180deg, rgba(var(--verre-haut), 0.82), rgba(var(--verre-bas), 0.9));
  box-shadow:
    inset 0 0 0 max(1px, calc(1.2 * var(--u))) var(--metal-clair),
    0 0 0 1px rgba(0, 0, 0, 0.8),
    var(--socle-verre);
  transition: transform 0.1s ease, filter 0.15s ease;
}
#reseaux-accueil .reseau-bouton:hover { filter: brightness(1.2); }
/* enfoncés : comme toute touche (socle, section 5 bis) */
#reseaux-accueil .reseau-bouton:active, #reseaux-formulaire .reseau-bouton:active { --pied: calc(1 * var(--u)); transform: translateY(var(--course)); filter: brightness(0.96); }
#reseaux-accueil .reseau-bouton:focus-visible, #reseaux-formulaire .reseau-bouton:focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
#reseaux-accueil .reseau-bouton svg { width: calc(21 * var(--u)); height: calc(21 * var(--u)); }

@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : l'enseigne à gauche (le titre, la phrase, le slogan),
     les portes à droite (l'action de laiton, les tuiles, les réseaux).
     Cinq rangées, toutes à la hauteur de ce qu'elles portent : l'action est
     à cheval sur les deux premières, les réseaux sur les deux dernières.
     Aucune rangée souple (1fr) : une pièce à cheval sur une rangée souple ne
     la fait pas grandir, et les portes sortaient par le haut de l'écran, hors
     d'atteinte. La place qui reste se partage entre les rangées ; s'il en
     manque, l'écran défile à l'intérieur, depuis le haut. */
  #ecran-auth:not(.formulaire) {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); column-gap: var(--ecart-colonnes);
    grid-template-rows: auto auto auto auto auto;
  }
  #ecran-auth:not(.formulaire)::before, #ecran-auth:not(.formulaire)::after { grid-row: 1 / 6; }
  #ecran-auth:not(.formulaire) .auth-titre { align-self: end; margin-top: calc(8 * var(--u)); }
  #ecran-auth:not(.formulaire) .auth-sous-titre { align-self: center; margin-top: calc(5 * var(--u)); }
  #ecran-auth:not(.formulaire) .slogan { grid-row: 4; align-self: start; display: block; margin: calc(6 * var(--u)) calc(16 * var(--u)) calc(8 * var(--u)); text-align: center; padding: 0; }
  #ecran-auth:not(.formulaire) .auth-accueil,
  #ecran-auth:not(.formulaire) .auth-portes,
  #ecran-auth:not(.formulaire) #reseaux-accueil,
  #ecran-auth:not(.formulaire) #reseaux-note { grid-column: 2; margin-top: 0; }
  #ecran-auth:not(.formulaire) .auth-accueil { grid-row: 1 / 3; align-self: end; }
  #ecran-auth:not(.formulaire) .auth-accueil > button { min-height: max(44px, calc(44 * var(--u))); }
  #ecran-auth:not(.formulaire) .auth-portes { grid-row: 3; align-self: center; margin-top: calc(8 * var(--u)); margin-bottom: calc(8 * var(--u)); }
  /* les réseaux sur une seule rangée ; à trois et plus, leur logo seul (leur
     nom reste dit par aria-label, comme dans la fiche) */
  #ecran-auth:not(.formulaire) #reseaux-accueil { grid-row: 4 / 6; align-self: start; flex-wrap: nowrap; }
  #reseaux-accueil .reseau-bouton { flex: 1 1 0; }
  #reseaux-accueil .reseau-bouton:first-of-type:nth-last-of-type(n + 3) .reseau-nom,
  #reseaux-accueil .reseau-bouton:first-of-type:nth-last-of-type(n + 3) ~ .reseau-bouton .reseau-nom { display: none; }
  #ecran-auth:not(.formulaire) #reseaux-note { display: none; }
  #reseaux-accueil .reseaux-legende { display: none; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  #ecran-auth:not(.formulaire) {
    grid-template-rows:
      minmax(calc(20 * var(--u)), 1fr) auto auto minmax(calc(20 * var(--u)), 1fr)
      auto auto auto auto auto;
  }
  #ecran-auth:not(.formulaire)::before, #ecran-auth:not(.formulaire)::after { border-radius: calc(20 * var(--u)); }
  /* L'action de laiton à gauche, les tuiles à sa droite, sur une même rangée : deux colonnes sous l'enseigne,
     qui les couvre toutes les deux. « Se connecter » prend la hauteur des tuiles : c'est la plus grosse pièce de la rangée. */
  #ecran-auth:not(.formulaire) { grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.5fr); column-gap: var(--ecart-pieces); }
  #ecran-auth:not(.formulaire)::before, #ecran-auth:not(.formulaire)::after { grid-column: 1 / -1; }
  #ecran-auth:not(.formulaire) > * { grid-column: 1 / -1; }
  #ecran-auth:not(.formulaire) .auth-accueil { grid-column: 1; align-self: stretch; }
  #ecran-auth:not(.formulaire) .auth-accueil > button { flex: 1 1 auto; }
  #ecran-auth:not(.formulaire) .auth-portes { grid-column: 2; grid-row: 5; flex-wrap: nowrap; }
  #ecran-auth:not(.formulaire) .auth-portes > .tuile-action, #ecran-auth:not(.formulaire) #btn-essayer, #ecran-auth:not(.formulaire) #btn-classement-visiteur { flex: 1 1 0; order: 0; }
  #ecran-auth:not(.formulaire) #reseaux-accueil { grid-row: 6; margin-top: var(--ecart-pieces); }
  #ecran-auth:not(.formulaire) #reseaux-note { grid-row: 7; }
  #ecran-auth:not(.formulaire) .auth-titre { margin: 0 calc(40 * var(--u)); font-size: calc(var(--taille-titre) * 1.2); }
  #ecran-auth:not(.formulaire) .auth-sous-titre { margin-top: calc(16 * var(--u)); max-width: min(calc(100% - 80 * var(--u)), 58ch); font-size: var(--taille-texte); line-height: 1.45; }
  /* la légende et les boutons des réseaux sur une même rangée (ils repassent
     à la ligne d'eux-mêmes s'ils sont quatre) */
  #reseaux-accueil { gap: calc(8 * var(--u)) calc(14 * var(--u)); }
  #reseaux-accueil .reseaux-legende { flex: 0 0 auto; white-space: nowrap; }
  #reseaux-accueil .reseau-bouton { flex: 1 1 calc(150 * var(--u)); }
  #reseaux-accueil .reseau-bouton svg { width: calc(23 * var(--u)); height: calc(23 * var(--u)); }
  /* LE SLOGAN prend la place et la forme de la bulle du socle, sous la scène :
     le professeur est accoudé à sa gauche, dans sa colonne. Sur cet écran la
     vraie bulle n'existe pas : la page réserve déjà les 16 u du bas. */
  #ecran-auth:not(.formulaire) .slogan { margin-bottom: 0; }
}

/* ---------- La fiche ----------
   L'écran devient LE panneau du formulaire : il prend la hauteur de son
   contenu (pas celle de la scène) et défile à l'intérieur au-delà. Ses pièces
   se rangent en lignes : la barre (retour à l'accueil, essai sans compte), les
   onglets, le message du serveur (le seul retour donné au joueur : en tête),
   le formulaire, puis les réseaux sociaux. La barre du jeu (.auth-barre) n'est
   plus une boîte : ses pièces rejoignent les autres. Le titre de l'accueil
   n'est pas redit.
   Les écarts (8 u entre les lignes, 9 u entre les champs) sont comptés pour
   que l'inscription, avec ses réseaux sociaux, tienne encore sur téléphone
   SOUS le bandeau « Nouvelle version du jeu » : c'est justement sur un
   formulaire que ce bandeau s'affiche (la page ne s'y recharge pas seule). */
#ecran-auth.formulaire {
  flex-direction: row; flex-wrap: wrap; align-items: center; align-content: flex-start; justify-content: space-between;
  gap: calc(8 * var(--u)) calc(8 * var(--u));
  align-self: start; max-height: 100%;
  padding: calc(16 * var(--u)); --hp-fiche-haut: calc(16 * var(--u));
  scroll-padding: calc(16 * var(--u));
}
#ecran-auth.formulaire .auth-titre { display: none; }
#ecran-auth.formulaire .auth-barre { display: contents; }
#ecran-auth.formulaire > *, #ecran-auth.formulaire .auth-barre > * { flex: none; min-width: 0; max-width: 100%; }
#ecran-auth.formulaire #btn-auth-retour { order: 1; padding-left: calc(14 * var(--u)); padding-right: calc(16 * var(--u)); letter-spacing: 0.04em; }
/* « Essayer sans compte » : un geste discret, écrit comme un lien */
#ecran-auth.formulaire #btn-essayer-formulaire {
  order: 2; margin-left: auto; padding: 0 calc(4 * 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: none; text-decoration: underline; text-underline-offset: 0.18em;
  background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
}
#ecran-auth.formulaire #btn-essayer-formulaire:hover, #ecran-auth.formulaire #btn-essayer-formulaire:active { transform: none; filter: brightness(1.15); }
#ecran-auth.formulaire .onglets { order: 3; flex: 1 0 100%; }
/* Le message du serveur est le seul retour donné au joueur : il COLLE au haut
   de la fiche quand elle défile (téléphone couché, clavier sorti, petit
   écran). Sans cela, qui vient d'appuyer sur « Créer mon compte », au bas de
   la fiche, ne voyait pas le refus écrit plus haut, hors de vue : rien ne
   semblait se passer. Il passe alors exprès SUR les champs qui défilent
   dessous (dit à l'outil de mesure), au ras du bord de la fiche : une position
   collante se compte depuis le contenu, sous la marge intérieure de la fiche
   (--hp-fiche-haut, redite à chaque rangement), où les champs qui défilent se
   verraient encore, en lamelle, au-dessus de lui. */
#ecran-auth.formulaire #auth-message {
  order: 4; flex: 1 0 100%; text-align: center; text-wrap: balance;
  position: sticky; top: calc(3 * var(--u) - var(--hp-fiche-haut)); z-index: 2;
  box-shadow: 0 calc(3 * var(--u)) calc(9 * var(--u)) rgba(0, 0, 0, 0.5);
  --mesure: chevauche;
}
#ecran-auth.formulaire form { order: 5; flex: 1 0 100%; max-width: 100%; margin: 0; gap: calc(9 * var(--u)); }
#ecran-auth.formulaire form > button[type="submit"] { margin-top: calc(2 * var(--u)); margin-bottom: calc(4 * var(--u)); }
#ecran-auth.formulaire form > button.lien { align-self: center; }
/* les réseaux sociaux de la fiche : leur logo dans un rond de verre (leur nom
   reste dit par aria-label), après le formulaire sur téléphone */
#ecran-auth.formulaire #reseaux-formulaire { order: 6; flex: 1 0 100%; gap: calc(10 * var(--u)); }
#reseaux-formulaire .reseaux-legende { font-size: var(--taille-note); color: var(--texte-doux); }
#reseaux-formulaire .reseau-nom { display: none; }
#reseaux-formulaire .reseau-bouton {
  width: max(44px, calc(46 * var(--u))); height: max(44px, calc(46 * var(--u))); min-height: 0; border-radius: 50%;
  background: linear-gradient(180deg, rgba(var(--verre-haut), 0.9), rgba(var(--verre-bas), 0.95));
  --pied: calc(3 * var(--u)); --course: calc(2 * var(--u));
  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), var(--socle-verre);
  transition: transform 0.1s ease, filter 0.15s ease;
}
#reseaux-formulaire .reseau-bouton:hover { filter: brightness(1.25); }
#reseaux-formulaire .reseau-bouton svg { width: 46%; height: 46%; }
/* « Activer ton compte », « Termine ton inscription » : une plaque gravée */
#ecran-auth .reseau-titre {
  align-self: center; padding: calc(5 * var(--u)) calc(18 * var(--u)); border-radius: calc(5 * var(--u));
  font-size: var(--taille-plaque); line-height: 1.2; letter-spacing: 0.14em; text-wrap: balance;
  color: var(--plaque-encre); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  /* (gravée en creux : « Activer ton compte » se lisait en laiton, juste au-dessus du bouton « Activer mon compte ») */
  background: var(--plaque-fond);
  box-shadow: var(--plaque-ombre);
  --mesure: etiquette;
}
/* le message du serveur ; en développement, il porte un lien */
#auth-message { line-height: 1.3; }
#auth-message a { display: inline-flex; align-items: center; min-height: max(44px, calc(44 * var(--u))); }

@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : la barre et les onglets sur une rangée, les champs côte à côte */
  #ecran-auth.formulaire { padding: calc(10 * var(--u)) calc(16 * var(--u)); --hp-fiche-haut: calc(10 * var(--u)); gap: calc(6 * var(--u)) calc(8 * var(--u)); }
  #ecran-auth.formulaire .onglets { order: 2; flex: 1 1 calc(240 * var(--u)); }
  #ecran-auth.formulaire #btn-essayer-formulaire { order: 3; margin-left: 0; }
  /* (l'écart entre les deux colonnes se dit sous « #ecran-auth.formulaire » : écrit sur le
     formulaire seul, il cédait à l'écart de la fiche, « #ecran-auth.formulaire form ») */
  #ecran-auth.formulaire #form-connexion, #ecran-auth.formulaire #form-inscription { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(14 * var(--u)); align-items: end; }
  #form-connexion > button, #form-inscription > button, #form-inscription > .case { grid-column: 1 / -1; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  #ecran-auth.formulaire {
    align-self: center; padding: calc(20 * var(--u)) calc(34 * var(--u)) calc(22 * var(--u)); --hp-fiche-haut: calc(20 * var(--u));
    gap: calc(12 * var(--u)) calc(14 * var(--u));
    scroll-padding: calc(20 * var(--u));
  }
  /* une seule rangée : retour, onglets, essai sans compte (les réseaux
     sociaux restent après le formulaire : à quatre, ils n'y tiendraient pas) */
  #ecran-auth.formulaire .onglets { order: 2; flex: 1 1 calc(340 * var(--u)); }
  #ecran-auth.formulaire #btn-essayer-formulaire { order: 3; margin-left: 0; }
  #reseaux-formulaire .reseau-bouton { width: calc(50 * var(--u)); height: calc(50 * var(--u)); }
  #ecran-auth.formulaire form { gap: calc(12 * var(--u)); max-width: calc(500 * var(--u)); margin-left: auto; margin-right: auto; }
  /* l'inscription : les champs à gauche, les cases et le bouton à droite */
  #ecran-auth.formulaire #form-inscription, #ecran-auth.formulaire #form-reseau {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: calc(30 * var(--u)); row-gap: calc(12 * var(--u));
    align-items: start; max-width: 100%;
  }
  #form-inscription > label:nth-of-type(1) { grid-column: 1; grid-row: 1; }
  #form-inscription > label:nth-of-type(2) { grid-column: 1; grid-row: 2; }
  #form-inscription > label:nth-of-type(3) { grid-column: 1; grid-row: 3; }
  #form-inscription > label:nth-of-type(4) { grid-column: 2; grid-row: 1; align-self: center; }
  #form-inscription > label:nth-of-type(5) { grid-column: 2; grid-row: 2; align-self: center; }
  #form-inscription > button { grid-column: 2; grid-row: 3; align-self: end; }
  /* « Termine ton inscription » : le titre, le résumé et le pseudo à gauche */
  #form-reseau > .reseau-titre { grid-column: 1; grid-row: 1; justify-self: center; }
  #form-reseau > #reseau-resume { grid-column: 1; grid-row: 2; }
  #form-reseau > label:nth-of-type(1) { grid-column: 1; grid-row: 3; }
  #form-reseau > label:nth-of-type(2) { grid-column: 2; grid-row: 1 / 3; align-self: center; }
  #form-reseau > label:nth-of-type(3) { grid-column: 2; grid-row: 3; align-self: center; }
  #form-reseau > button[type="submit"] { grid-column: 2; grid-row: 4; }
  #form-reseau > #btn-reseau-annuler { grid-column: 1; grid-row: 4; align-self: center; justify-self: center; }
}


/* ============================================================================
   3. ACCUEIL ET SALON (#ecran-salon)
   ----------------------------------------------------------------------------
   Refait le 2026-10-09 sur le retour de Gautier (« tous les textes et boutons
   se ressemblent, on ne sait pas où lire ») : la hiérarchie du socle (section
   12 bis), QUATRE GROUPES que la page d'essai range dans cet ordre :
     1  LE HÉROS        .salon-heros : le compte à rebours géant (#salon-rebours :
                        ou « EN DIRECT », « À BIENTÔT », « DÉMO »), ou la phrase
                        #salon-compteur quand rien ne se compte ; SOUS lui, en
                        lettres courantes, #salon-invite (les deux heures, « il
                        manque un joueur », « la partie n'a pas eu lieu », le
                        motif d'une exclusion) ; puis #salon-lot, le jeu du soir,
                        une fois la roue tirée. Un seul panneau, un seul cerclage.
        la salle        #salon-attente, une fois entré : les présents, à plat
     2  L'ACTION        #salon-entree : #btn-rejoindre (« Entrer dans le salon »,
                        « Entrer et jouer », « Regarder en direct »), ou, salon
                        fermé, #btn-notifications tant que la notification reste
                        à activer. Une seule touche de laiton ; une fois les
                        notifications activées (ou bloquées), une ligne d'état.
     3  LES TUILES      .salon-rappels : apprendre à jouer, le classement
                        général
     4  LE CARNET       #salon-infos : compléter son profil, la ligne du
                        classement, l'aide des notifications, les derniers
                        vainqueurs ; du texte à plat, à côté du professeur
   Entre deux groupes, --ecart-groupes ; dans un groupe, --ecart-pieces. Les
   écarts sont des marges posées sur les pièces montrées : un groupe vide (aucune
   action possible, carnet sans ligne) ne laisse pas de trou.
   Téléphone : une colonne ; le héros prend la place qui reste ; le carnet est
   dans la bande du professeur (section 1).
   Téléphone couché, ordinateur : le héros à gauche, sur toute la hauteur ; à
   droite la salle, l'action et les tuiles, au milieu de la colonne. Sur
   ordinateur le carnet est sous les deux colonnes, à la place de la bulle.
   ========================================================================== */
#ecran-salon { gap: 0; padding-bottom: calc(10 * var(--u)); }
#ecran-salon::before, #ecran-salon::after { content: none; }
#ecran-salon > * { flex: none; min-width: 0; max-width: 100%; }

/* ---------- 1. Le héros ----------
   L'ATTENTE DU SALON (2026-10-16, Gautier : « L'interface d'attente que le salon s'ouvre n'est pas jolie, elle
   fait extrêmement vide et n'est pas centrée »). Le compte à rebours est LE héros : plus grand, posé sur la
   lueur d'un projecteur (la seule de l'écran), entre deux filets de laiton ; le panneau, au cerclage plus
   franc, se tient au milieu de l'écran avec l'action et les tuiles (sur ordinateur, une seule colonne centrée,
   plus bas). */
#ecran-salon > .salon-heros { flex: 1 0 auto; }
#ecran-salon:not(.salon-entre) { --taille-rebours: calc(94 * var(--u)); }
/* Sur téléphone, pas entré : le héros prend la hauteur de ce qu'il porte (il ne s'étire plus en un grand panneau
   vide), et le groupe héros, action, tuiles se tient au milieu de la place, au-dessus du carnet (deux marges
   automatiques, qui retombent à zéro quand la place manque : le palier « serre » prend alors le relais) */
#ecran-salon:not(.salon-entre) > .salon-heros { flex: 0 0 auto; margin-top: auto; min-height: calc(270 * var(--u)); padding-top: calc(26 * var(--u)); padding-bottom: calc(26 * var(--u)); }
#ecran-salon:not(.salon-entre) > .actions-secondaires { margin-bottom: var(--ecart-groupes); }
#ecran-salon:not(.salon-entre) > #salon-infos { margin-top: auto; }
#ecran-salon > .salon-heros {
  background:
    radial-gradient(ellipse 72% 46% at 50% 46%, rgba(var(--accent-rvb), 0.16), rgba(var(--accent-rvb), 0) 100%),
    var(--verre-fond);
  box-shadow:
    inset 0 0 0 max(1.5px, calc(2.2 * var(--u))) var(--metal-clair),
    inset 0 0 0 max(2.5px, calc(3.4 * var(--u))) rgba(0, 0, 0, 0.55),
    inset 0 0 0 calc(7 * var(--u)) rgba(var(--accent-rvb), 0.1),
    0 0 0 1px rgba(0, 0, 0, 0.75),
    0 0 calc(30 * var(--u)) rgba(var(--accent-rvb), 0.12),
    0 calc(10 * var(--u)) calc(24 * var(--u)) rgba(0, 0, 0, 0.55);
}
/* les deux filets de laiton qui encadrent le grand nombre (décor : des fonds, rien ne s'y touche) */
#salon-rebours { padding: calc(4 * var(--u)) 0 calc(10 * var(--u));
  background:
    linear-gradient(90deg, rgba(var(--metal-clair-rvb), 0), rgba(var(--metal-clair-rvb), 0.6), rgba(var(--metal-clair-rvb), 0)) 50% 100% / 70% max(1px, calc(1.2 * var(--u))) no-repeat; }
#salon-rebours { gap: calc(8 * var(--u)); max-width: 100%; }
/* le libellé peut être long (« Il manque un joueur, nouvel essai dans ») : il passe à la ligne */
#salon-rebours .rebours-label { max-width: 100%; white-space: normal; text-wrap: balance; }
#rebours-chiffre { max-width: 100%; }
/* quand rien ne se compte : la phrase prend la place du compte à rebours, en grand */
#salon-compteur {
  margin: 0; max-width: 100%;
  font-family: var(--police-plateau); font-weight: 900; text-transform: uppercase; letter-spacing: 0.05em; line-height: 1.1;
  font-size: calc(var(--taille-titre) * 0.86); color: var(--accent); text-wrap: balance; overflow-wrap: anywhere;
  text-shadow: 0 0 calc(22 * var(--u)) rgba(var(--accent-rvb), 0.55), 0 2px 0 rgba(0, 0, 0, 0.6);
}
/* Ce qui va avec le compte à rebours (les deux heures, « il manque un joueur »…) : la phrase du héros (socle,
   .heros-texte). Ses lignes ne sont PAS équilibrées : le jeu écrit une espace ordinaire devant ses deux-points
   (« … à 20:45 : la partie commence à 21:00. »), et une coupe équilibrée tombait juste là, les deux-points
   seuls en tête de la seconde ligne. Remplie ligne après ligne, la phrase ne se coupe là que par hasard. */
#salon-invite { max-width: 100%; text-wrap: pretty; }
/* Le motif d'une exclusion, écrit par un admin (300 caractères au plus) : la même
   phrase du héros, marquée à l'alerte d'un filet et d'un fond léger (une
   information, pas une touche). Très long, il défile dans sa place plutôt que
   de chasser le reste de l'écran. */
#salon-invite[data-motif] {
  align-self: stretch; max-width: none; text-align: left; text-wrap: pretty;
  padding: calc(8 * var(--u)) calc(12 * var(--u)) calc(9 * var(--u)) calc(14 * var(--u));
  border-radius: calc(4 * var(--u)) calc(10 * var(--u)) calc(10 * var(--u)) calc(4 * var(--u));
  background: rgba(var(--alerte-rvb), 0.1);
  box-shadow: inset calc(3 * var(--u)) 0 0 var(--alerte);
  max-height: calc(2.3 * var(--hp-bulle)); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--alerte) transparent;
}
/* « Le jeu du soir », une fois la roue tirée : au pied du héros, sous un filet */
#salon-lot {
  align-self: stretch; gap: calc(5 * var(--u)); margin: 0; padding: calc(12 * var(--u)) 0 0; border-radius: 0;
  background: none; box-shadow: none;
  border-top: max(1px, calc(1.2 * var(--u))) solid rgba(var(--metal-clair-rvb), 0.32);
}
#salon-lot-label { display: flex; align-items: center; justify-content: center; gap: calc(10 * var(--u)); letter-spacing: 0.2em; font-size: var(--taille-surtitre); text-align: center; text-wrap: balance; }
#salon-lot-label::before, #salon-lot-label::after { content: ''; flex: 0 0 calc(18 * var(--u)); height: max(1px, calc(1.2 * var(--u))); background: rgba(var(--metal-clair-rvb), 0.6); }
#salon-lot-titre {
  line-height: 1.12; font-size: calc(var(--taille-titre) * 0.68); text-wrap: balance;
  text-shadow: 0 0 calc(16 * var(--u)) rgba(var(--accent-rvb), 0.5), 0 2px 0 rgba(0, 0, 0, 0.6);
}

/* ---------- La salle : les présents ----------
   Une information : du verre à plat sous un filet fin (le cerclage de laiton
   est au héros), des noms en lettres courantes sur une pastille sans relief.
   Une pastille prend la largeur de son pseudo (vingt caractères au plus : aucun
   n'est abrégé) et les rangées se remplissent. La salle a la hauteur de ses
   présents ; quand la place manque, elle ne grandit plus et sa liste défile à
   l'intérieur (seule zone de l'écran qui le fait). « overflow: hidden » : c'est
   ce qui lui permet de céder la place qu'elle n'a pas (sa hauteur naturelle
   compte 200 noms). */
#salon-attente {
  flex: 0 1 auto; align-items: stretch; gap: calc(8 * var(--u)); min-height: calc(120 * var(--u)); overflow: hidden;
  margin-top: var(--ecart-groupes);
  padding: calc(10 * var(--u)) calc(12 * var(--u)) calc(12 * var(--u)); border-radius: calc(14 * var(--u));
  background: linear-gradient(180deg, rgba(var(--verre-haut), 0.66), rgba(var(--verre-bas), 0.78));
  -webkit-backdrop-filter: var(--verre-flou); backdrop-filter: var(--verre-flou);
  box-shadow: inset 0 0 0 max(1px, calc(1.1 * var(--u))) rgba(var(--metal-clair-rvb), 0.24), 0 0 0 1px rgba(0, 0, 0, 0.6);
}
#salon-nb-joueurs { flex: none; font-family: var(--police-texte); font-weight: 700; font-size: var(--taille-texte); color: var(--texte); text-align: center; }
#salon-joueurs {
  flex: 1 1 auto; min-height: 0; max-height: none; padding: calc(2 * var(--u));
  justify-content: flex-start; align-content: flex-start; gap: calc(6 * var(--u));
}
#salon-joueurs > li {
  flex: 1 1 auto; min-height: calc(32 * var(--u)); padding: 0 calc(10 * var(--u)); border-radius: calc(16 * var(--u));
  font-family: var(--police-texte); font-weight: 500; letter-spacing: 0;
  font-size: max(16px, calc(16 * var(--u))); line-height: calc(32 * var(--u)); text-align: center; color: var(--texte);
  background: rgba(255, 255, 255, 0.06); box-shadow: none;
}
/* un admin présent dans le salon (SPECS 8) : sa pastille est à l'accent */
#salon-joueurs > li.badge-admin {
  color: var(--accent-vif);
  background: linear-gradient(90deg, rgba(var(--accent-rvb), 0.24), rgba(var(--accent-rvb), 0.08));
  box-shadow: inset 0 0 0 max(1px, calc(1.2 * var(--u))) rgba(var(--accent-rvb), 0.6);
}

/* ---------- 2. L'action principale ----------
   Le premier bouton montré est la touche de laiton (socle, section 12 bis). */
#salon-entree { align-items: stretch; gap: var(--ecart-pieces); }
#salon-entree > button { margin-top: var(--ecart-groupes); }
#salon-entree > button:not([hidden]) ~ button { margin-top: 0; }
/* Le bouton et la phrase des notifications annoncent l'OUVERTURE du salon : ils
   se montrent tant qu'il est fermé (comme sur la maquette, et comme sur le
   plateau d'aujourd'hui). Salon ouvert ou partie en cours, le menu les garde. */
#ecran-salon:not(.salon-ferme) #btn-notifications, #ecran-salon:not(.salon-ferme) #notifications-aide { display: none; }
/* la cloche de sa ligne d'état, une fois activées, bloquées ou suspendues (le décor pose .ligne-etat) */
#btn-notifications { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 16.8v-5.3a5.7 5.7 0 0 1 11.4 0v5.3l1.6 2.2H4.7zM10 20.2a2 2 0 0 0 4 0'/%3E%3C/svg%3E"); }
#salon-entree > button.ligne-etat { margin-top: calc(var(--ecart-groupes) - 8 * var(--u)); margin-bottom: calc(-8 * var(--u)); }

/* ---------- 3. Les tuiles ---------- */
#ecran-salon > .actions-secondaires { margin-top: var(--ecart-groupes); }
/* un livre ouvert */
#btn-tutoriel { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 6.8c-2.2-1.5-5-1.8-8-1v12.4c3-.8 5.8-.5 8 1 2.2-1.5 5-1.8 8-1V5.8c-3-.8-5.8-.5-8 1zM12 6.8v12.4'/%3E%3C/svg%3E"); }

/* ---------- 4. Le carnet ----------
   Dans la bande du professeur (section 1) : à sa droite, au milieu de la
   hauteur de sa bulle. Un carnet plus long que la bulle fait grandir la bande,
   et le héros se resserre au-dessus. */
#salon-infos {
  align-items: stretch; gap: calc(7 * var(--u)); justify-content: center; min-height: var(--hp-bulle);
  position: relative; --hp-carnet-retrait: calc(var(--hp-retrait) + 8 * var(--u));
  margin: var(--ecart-groupes) 0 0 var(--hp-carnet-retrait); padding: calc(9 * var(--u)) calc(12 * var(--u)) calc(10 * var(--u)) 0;
}
/* Une ombre portée sous les lignes (décor), sans bord ni cerclage : le fond d'ambiance peut être clair à cet
   endroit (une peinture viendra), et un texte à plat doit se lire partout. Elle s'étend sous le professeur,
   qui se tient devant elle. */
#salon-infos::before {
  content: ''; position: absolute; z-index: -1; top: 0; right: 0; bottom: 0; left: calc(-1 * var(--hp-carnet-retrait));
  border-radius: calc(14 * var(--u)); pointer-events: none;
  background: linear-gradient(180deg, rgba(var(--verre-bas), 0) 0%, rgba(var(--verre-bas), 0.5) 24%, rgba(var(--verre-bas), 0.64) 100%);
}
/* (un carnet sans une ligne n'a pas d'ombre : le décor le dit, pupitre.js, direSiLeCarnetEstVide) */
#salon-infos.vide::before { content: none; }
/* un cœur (les vies du profil) ; une cloche ; une médaille */
/* (sous l'invitation, la promesse d'anonymat : sa propre ligne, plus discrète ; « Complètement anonyme » en clair) */
#note-profil-anonyme { display: block; margin-top: calc(3 * var(--u)); color: var(--texte-doux); }
#note-profil-anonyme strong { color: var(--texte); font-weight: 700; }
#note-profil { color: var(--texte); --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 20.6s-7.6-4.7-7.6-10.4A4.35 4.35 0 0 1 12 7.5a4.35 4.35 0 0 1 7.6 2.7c0 5.7-7.6 10.4-7.6 10.4z'/%3E%3C/svg%3E"); }
#notifications-aide { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.3 16.8v-5.3a5.7 5.7 0 0 1 11.4 0v5.3l1.6 2.2H4.7zM10 20.2a2 2 0 0 0 4 0'/%3E%3C/svg%3E"); }
#salon-gagnants { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='14.6' r='5.2'/%3E%3Cpath d='M8.6 10.6L6 3.8h4l2 4 2-4h4l-2.6 6.8'/%3E%3C/svg%3E"); }
/* L'ACCUEIL TROP PLEIN (téléphone debout ; le décor le mesure et pose « serre », pupitre.js, serrerLAccueil) :
   quand le héros, l'action, les tuiles et tout le carnet ne tiennent pas dans l'écran, les derniers vainqueurs
   tiennent sur UNE ligne, abrégée (le plus récent d'abord), au lieu de faire défiler l'écran. */
#ecran-salon.serre #salon-gagnants { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* … le héros reprend un peu de sa marge, les groupes se rapprochent, et les tuiles passent leur pictogramme à
   gauche de leur libellé. Aucun texte ne rétrécit. */
#ecran-salon.serre { --ecart-groupes: calc(13 * var(--u)); }
#ecran-salon.serre > .salon-heros { padding-top: calc(12 * var(--u)); padding-bottom: calc(13 * var(--u)); gap: calc(8 * var(--u)); }
/* (le motif d'une exclusion, lui, défile alors dans sa place au-delà d'une hauteur de bulle et demie environ, sous son ascenseur à l'alerte) */
#ecran-salon.serre #salon-invite[data-motif] { max-height: calc(1.7 * var(--hp-bulle)); }
#ecran-salon.serre .tuile-action { flex-direction: row; justify-content: center; align-items: center; gap: calc(8 * var(--u)); min-height: max(44px, calc(46 * var(--u))); padding: calc(4 * var(--u)) calc(8 * var(--u)); text-align: left; }
/* Le professeur prend la parole (l'équipe du labo, SPECS 13) : sa bulle s'ouvre à la place du carnet, qui s'efface
   le temps de la réplique (le décor pose « professeur-parle » sur la page). Rien ne bouge. */
body.professeur-parle #salon-infos { visibility: hidden; }

/* ---------- Deux colonnes (téléphone couché, ordinateur) ----------
   Le héros à gauche, sur toute la hauteur. À droite, cinq rangées : deux
   rangées souples encadrent la salle, l'action et les tuiles, qui se tiennent
   donc au milieu de la colonne, en face du grand nombre. La salle prend la
   hauteur de ses présents, et pas plus que la place (sa rangée part de rien et
   s'arrête à son contenu) ; les rangées souples lui cèdent alors tout. */
@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : pas de bande (le professeur garde la rangée du socle, à
     côté des liens légaux) ; le carnet est la dernière rangée de droite */
  #ecran-salon {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) minmax(0, auto) auto auto minmax(0, 1fr) auto;
    column-gap: var(--ecart-colonnes); row-gap: 0; align-items: start;
  }
  #ecran-salon > .salon-heros { grid-column: 1; grid-row: 1 / 7; align-self: stretch; gap: calc(7 * var(--u)); padding: calc(10 * var(--u)) calc(14 * var(--u)); }
  #salon-attente { grid-column: 2; grid-row: 2; align-self: stretch; min-height: calc(96 * var(--u)); margin-top: 0; }
  #salon-entree { grid-column: 2; grid-row: 3; }
  #ecran-salon > .actions-secondaires { grid-column: 2; grid-row: 4; }
  #salon-infos { grid-column: 2; grid-row: 6; min-height: 0; margin-left: 0; padding: calc(5 * var(--u)) calc(10 * var(--u)); gap: calc(4 * var(--u)); }
  #salon-infos::before { left: 0; background: rgba(var(--verre-bas), 0.5); }
  /* (pas entré : la grille range, sans les marges automatiques du téléphone debout) */
  #ecran-salon:not(.salon-entre) > .salon-heros { margin-top: 0; min-height: 0; padding: calc(10 * var(--u)) calc(14 * var(--u)); }
  #ecran-salon:not(.salon-entre) > .actions-secondaires { margin-bottom: 0; }
  #ecran-salon:not(.salon-entre) > #salon-infos { margin-top: 0; }
  /* (pas de bande ici : la bulle a sa rangée, le carnet reste) */
  body.professeur-parle #salon-infos { visibility: visible; }
  /* le motif d'une exclusion ne défile pas dans sa place (une pièce qui défile laisse sa rangée rétrécir sous elle) : c'est l'écran qui défile */
  #salon-invite[data-motif] { max-height: none; overflow-y: visible; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  /* Le salon s'étend sur la rangée de la scène ET sur celle de la bulle du
     socle (rangées 3 et 4 de la page) : sa dernière rangée est la place de la
     bulle, où il pose son carnet, à côté du professeur. */
  #ecran-salon {
    grid-area: 3 / 2 / 5 / 7;
    display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
    grid-template-rows:
      minmax(0, 1fr) minmax(0, auto) auto auto minmax(0, 1fr)
      minmax(calc(var(--ecart) + var(--hp-bulle) + 16 * var(--u)), auto);
    column-gap: calc(30 * var(--u)); row-gap: 0; align-items: start; padding-bottom: 0;
    --taille-rebours: calc(108 * var(--u));
  }
  #ecran-salon > .salon-heros {
    grid-column: 1; grid-row: 1 / 6; align-self: stretch;
    gap: calc(18 * var(--u)); padding: calc(26 * var(--u)) calc(30 * var(--u)) calc(30 * var(--u)); border-radius: calc(20 * var(--u));
  }
  /* (0,66 et non 0,9 : à 0,9, « PROGRAMMÉE » ne tenait pas dans la colonne, la dernière lettre passait seule
     à la ligne, « PROGRAMMÉ / E ». Le plus long mot que le jeu écrit ici, « INTERROMPUE », tient à cette taille.) */
  #salon-compteur { font-size: calc(var(--taille-titre) * 0.66); }
  #salon-invite[data-motif] { max-height: none; overflow-y: visible; }
  #salon-lot { padding-top: calc(16 * var(--u)); }
  #salon-attente { grid-column: 2; grid-row: 2; align-self: stretch; margin-top: 0; padding: calc(14 * var(--u)) calc(16 * var(--u)) calc(16 * var(--u)); }
  #salon-joueurs > li { min-height: calc(34 * var(--u)); line-height: calc(34 * var(--u)); padding: 0 calc(12 * var(--u)); font-size: calc(17 * var(--u)); }
  #salon-entree { grid-column: 2; grid-row: 3; }
  #ecran-salon > .actions-secondaires { grid-column: 2; grid-row: 4; }
  /* le carnet : à la place de la bulle, sous les deux colonnes ; ses lignes se suivent sur une rangée, et passent à la ligne */
  #salon-infos {
    grid-column: 1 / -1; grid-row: 6; align-self: center;
    flex-direction: row; flex-wrap: wrap; align-items: center; align-content: center; justify-content: flex-start; gap: calc(8 * var(--u)) calc(34 * var(--u));
    min-height: var(--hp-bulle); margin: var(--ecart) 0 calc(16 * var(--u)); padding: calc(8 * var(--u)) calc(22 * var(--u));
  }
  #salon-infos::before { left: 0; background: linear-gradient(90deg, rgba(var(--verre-bas), 0.62), rgba(var(--verre-bas), 0.36)); }
  #salon-infos > .ligne-info { flex: 0 1 auto; max-width: 100%; }

  /* PAS ENTRÉ (salon fermé, salon ouvert, partie en cours) : UNE COLONNE CENTRÉE (2026-10-16, retour de Gautier
     sur l'attente du salon : « pas centrée », « extrêmement vide »). Le héros, large, au milieu de l'écran ;
     dessous, l'action principale puis les tuiles, à la largeur d'une main ; le carnet reste en bas, à la place
     de la bulle. Une colonne souple (pas une grille) : deux marges automatiques tiennent le groupe au milieu de
     la hauteur, et retombent à zéro quand le contenu est trop haut (le motif d'une exclusion) : l'écran défile
     alors vers le bas, son haut reste atteignable. Une fois entré, la salle a besoin de sa colonne : les deux
     colonnes ci-dessus. */
  #ecran-salon:not(.salon-entre) {
    display: flex; flex-direction: column; align-items: center;
    --taille-rebours: calc(138 * var(--u));
  }
  #ecran-salon:not(.salon-entre) > .salon-heros {
    flex: none; align-self: center; width: min(100%, calc(800 * var(--u))); margin-top: auto;
    min-height: calc(300 * var(--u)); gap: calc(16 * var(--u));
    padding: calc(30 * var(--u)) calc(48 * var(--u)) calc(32 * var(--u));
  }
  #ecran-salon:not(.salon-entre) #salon-entree,
  #ecran-salon:not(.salon-entre) > .actions-secondaires { flex: none; align-self: center; width: min(100%, calc(560 * var(--u))); }
  #ecran-salon:not(.salon-entre) #salon-entree > button { margin-top: calc(24 * var(--u)); }
  #ecran-salon:not(.salon-entre) #salon-entree > button:not([hidden]) ~ button { margin-top: 0; }
  #ecran-salon:not(.salon-entre) > .actions-secondaires { margin-top: calc(18 * var(--u)); margin-bottom: calc(24 * var(--u)); }
  #ecran-salon:not(.salon-entre) > #salon-infos { flex: none; align-self: stretch; margin-top: auto; }
  #ecran-salon:not(.salon-entre) #salon-invite { font-size: calc(var(--taille-texte) * 1.14); max-width: 44ch; }
  #ecran-salon:not(.salon-entre) #salon-compteur { font-size: calc(var(--taille-titre) * 0.86); }
  /* les tuiles, couchées : leur pictogramme à gauche du libellé, sur une ligne */
  #ecran-salon:not(.salon-entre) .tuile-action {
    flex-direction: row; justify-content: center; align-items: center; gap: calc(10 * var(--u));
    min-height: max(44px, calc(56 * var(--u))); padding: calc(6 * var(--u)) calc(16 * var(--u));
  }
}


/* ============================================================================
   4. MON PROFIL (#ecran-profil)
   ----------------------------------------------------------------------------
   Le plus long des formulaires : son panneau défile à l'intérieur. Dans
   l'ordre : la plaque du titre, ce qu'est le profil (la promesse d'anonymat en
   tête), le formulaire (pseudo, puis les trois questions : tranche d'âge,
   département, sexe), l'adresse du compte et ses réseaux, et, bien séparée, la
   suppression.
   ========================================================================== */
/* Comme la fiche d'un formulaire, le panneau prend la hauteur de son contenu
   (pas celle de la scène) et défile à l'intérieur au-delà : avec peu de
   questions, il ne reste pas à moitié vide. Sa hauteur ne dépasse jamais sa
   place : celle de sa rangée, moins la marge qui le sépare de la pièce du
   dessus (un pourcentage se compte sur la rangée entière, marge comprise). */
#ecran-profil {
  align-items: stretch; gap: calc(12 * var(--u));
  align-self: start; max-height: calc(100% - var(--ecart));
  padding: calc(16 * var(--u)) calc(16 * var(--u)) calc(18 * var(--u));
  scroll-padding: calc(16 * var(--u));
}
/* « Mon profil », « Mes statistiques » : une plaque gravée, pas un grand titre (la place va au contenu) */
#ecran-profil > h2, #ecran-stats > h2 {
  align-self: center; display: inline-flex; align-items: center; justify-content: center;
  padding: calc(5 * var(--u)) calc(20 * var(--u)); border-radius: calc(5 * var(--u));
  font-size: var(--taille-plaque); line-height: 1.2; letter-spacing: 0.16em; white-space: nowrap;
  color: var(--plaque-encre); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  /* (gravée en creux, lettres de laiton : une information, pas une touche ; socle, section 5 bis) */
  background: var(--plaque-rivets), var(--plaque-fond);
  box-shadow: var(--plaque-ombre);
  --mesure: etiquette;
}
/* ce qu'est le profil, et ce qu'il rapporte ; l'adresse du compte : deux informations, À PLAT derrière un filet
   de laiton (elles étaient deux cartes de verre cerclées, de la forme des champs qui les suivent : socle,
   section 12 bis, règle 4) */
#ecran-profil > h2 + .note, #profil-reseaux {
  padding: calc(2 * var(--u)) 0 calc(3 * var(--u)) calc(13 * var(--u)); border-radius: 0;
  font-size: var(--taille-texte); line-height: 1.38; text-wrap: pretty; overflow-wrap: anywhere;
  background: none; box-shadow: inset max(2px, calc(2.5 * var(--u))) 0 0 rgba(var(--metal-clair-rvb), 0.55);
}
#profil-bonus { color: var(--texte); }
#profil-bonus strong { color: var(--accent-vif); }
#ecran-profil form { max-width: none; margin: 0; gap: calc(10 * var(--u)); }
/* LA PROMESSE D'ANONYMAT (Gautier, 2026-10-16 : « il faut bien appuyer sur le fait que c'est complètement
   anonyme ») : la première phrase de l'écran, en clair et en gras. Une information : rien ne s'y touche. */
#profil-anonyme { display: block; margin-bottom: calc(4 * var(--u)); color: var(--texte); font-weight: 700; }

/* LE SEXE : quatre choix à toucher (SPECS 2.1, migration 053). Son nom, « Sexe », est gravé comme celui des
   autres champs ; chaque choix est une TOUCHE DE VERRE sur son pied (socle, section 5 bis) : le <span> est la
   touche, son <label> la zone qu'on touche (44 px au moins), le bouton rond du navigateur est caché mais garde
   le clavier (Tab entre dans le groupe, les flèches passent d'un choix à l'autre, l'anneau commun s'allume sur
   la touche). Sous la souris elle se soulève, sous le doigt elle s'enfonce ; CHOISIE, elle reste enfoncée et
   s'allume à l'ambre, comme une réponse choisie. Trois sur une ligne, « Je préfère ne pas répondre » dessous,
   sur toute la largeur : il est aussi visible que les autres. */
#profil-sexe { display: flex; flex-direction: column; gap: calc(6 * var(--u)); min-width: 0; margin: 0; padding: 0; border: 0; }
#profil-sexe > legend {
  padding: 0; margin: 0 0 calc(5 * var(--u));
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  font-size: max(11px, calc(11.5 * var(--u))); line-height: 1.25; color: var(--metal-clair);
  --mesure: etiquette;
}
#profil-sexe-choix { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(12 * var(--u)) calc(10 * var(--u)); }
#profil-sexe-choix > label:last-child { grid-column: 1 / -1; }
#profil-sexe-choix > label {
  position: relative; display: flex; flex-direction: row; align-items: stretch; min-width: 0; min-height: var(--hauteur-bouton);
  margin: 0 0 var(--pied); cursor: pointer; -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
#profil-sexe-choix input { position: absolute; top: 50%; left: 50%; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
#profil-sexe-choix > label > span {
  flex: 1; display: flex; align-items: center; justify-content: center; min-width: 0; min-height: var(--hauteur-bouton);
  padding: calc(4 * var(--u)) calc(10 * var(--u)); border-radius: calc(12 * var(--u));
  font-family: var(--police-texte); font-weight: 700; font-size: var(--taille-texte); line-height: 1.2;
  text-align: center; text-wrap: balance; overflow-wrap: anywhere; color: var(--metal-vif); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  background: var(--verre-touche);
  box-shadow: var(--ombre-verre);
  transition: transform 0.1s ease, filter 0.15s ease, box-shadow 0.15s ease;
}
#profil-sexe-choix > label:hover { --lueur-verre: 0.36; --filet-touche: var(--accent-vif); }
#profil-sexe-choix > label:hover > span { transform: translateY(calc(-2 * var(--u))); filter: brightness(1.12); }
/* sous le doigt : la touche descend de sa course, son pied s'écrase */
#profil-sexe-choix > label:active { --pied: calc(1 * var(--u)); }
#profil-sexe-choix > label:active > span { transform: translateY(calc(var(--course) + 1 * var(--u))); filter: brightness(0.96); }
#profil-sexe-choix input:focus-visible + span { outline: var(--anneau-clavier); outline-offset: 3px; }
/* CHOISIE : enfoncée de sa course, sans pied, cerclée d'ambre, ses lettres à l'ambre, et cochée. Une teinte
   légère, pas une lueur de laiton : elle dit « c'est ton choix », elle ne ressemble pas à « Enregistrer mon
   profil », la seule touche dorée de l'écran. */
#profil-sexe-choix input:checked + span {
  gap: calc(8 * var(--u));
  transform: translateY(var(--course)); color: var(--accent-vif);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.02) 48%, rgba(255, 255, 255, 0) 52%),
    linear-gradient(180deg, rgba(var(--accent-rvb), 0.16), rgba(var(--accent-rvb), 0.06)),
    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 0 calc(12 * var(--u)) rgba(var(--accent-rvb), 0.25);
}
/* la coche de la touche choisie (dessinée, comme celle d'une réponse choisie) */
#profil-sexe-choix input:checked + span::before {
  content: ''; flex: none; width: calc(6 * var(--u)); height: calc(12 * var(--u)); margin: 0 calc(2 * var(--u)) calc(3 * var(--u)) 0;
  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);
}
#form-profil > button[type="submit"] { margin-top: calc(4 * var(--u)); margin-bottom: calc(4 * var(--u)); }

/* LA SUPPRESSION DU COMPTE : à part, sous un trait, et à l'alerte. Repliée,
   c'est une ligne ; dépliée, la mise en garde, la confirmation et le geste. */
#zone-suppression { margin-top: calc(6 * var(--u)); padding-top: calc(14 * var(--u)); border-top: max(1px, calc(1.2 * var(--u))) solid rgba(var(--alerte-rvb), 0.45); gap: 0; }
#zone-suppression > summary {
  list-style: none; align-self: stretch; padding: calc(6 * var(--u)) calc(18 * var(--u)); border-radius: calc(12 * var(--u));
  font-family: var(--police-plateau); font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; line-height: 1.12;
  font-size: var(--taille-bouton); text-align: center; text-decoration: none; color: var(--alerte);
  background: var(--hp-carte);
  /* une touche de verre à l'alerte, debout sur son pied (socle, section 5 bis) : elle n'avait ni pied ni
     chevron, rien ne la distinguait de la carte d'information posée au-dessus d'elle */
  gap: calc(10 * var(--u)); --socle-teinte: var(--vie-eteinte);
  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);
  transition: transform 0.1s ease, filter 0.15s ease;
}
#zone-suppression > summary::-webkit-details-marker { display: none; }
/* le chevron : vers le bas, repliée ; vers le haut, dépliée (un dessin, pas un texte) */
#zone-suppression > 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);
}
#zone-suppression[open] > summary::after { margin-top: calc(4 * var(--u)); transform: rotate(-135deg); }
#zone-suppression > summary:hover { filter: brightness(1.2); }
#zone-suppression > summary:active { --pied: calc(1 * var(--u)); transform: translateY(var(--course)); }
#zone-suppression > summary:focus-visible { outline: var(--anneau-clavier); outline-offset: 3px; }
/* dépliée : la touche reste enfoncée, éteinte */
#zone-suppression[open] > summary {
  color: var(--texte-doux); --pied: calc(1 * var(--u)); --socle-teinte: rgba(var(--texte-doux-rvb), 0.45); transform: translateY(var(--course));
  box-shadow: inset 0 0 0 max(1px, calc(1.2 * var(--u))) rgba(var(--texte-doux-rvb), 0.45), 0 0 0 1px rgba(0, 0, 0, 0.8), var(--socle-verre);
}
#zone-suppression[open] > :not(summary) { margin-top: calc(12 * var(--u)); }
#zone-suppression .note { text-wrap: pretty; }
#form-suppression { gap: calc(10 * var(--u)); }
/* « Pour confirmer, écris SUPPRIMER » : une consigne, elle se lit telle qu'elle est écrite */
#form-suppression #suppression-confirmation {
  font-family: var(--police-texte); font-weight: 400; text-transform: none; letter-spacing: 0;
  font-size: var(--taille-texte); line-height: 1.3; color: var(--texte);
  --mesure: lu;
}

@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  /* deux colonnes : le formulaire à gauche ; à droite ce qu'est le profil,
     le compte, et la suppression */
  #ecran-profil {
    display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); grid-template-rows: auto auto auto 1fr;
    column-gap: calc(34 * var(--u)); row-gap: calc(14 * var(--u)); align-items: start; align-content: start;
    padding: calc(20 * var(--u)) calc(34 * var(--u)) calc(24 * var(--u));
    scroll-padding: calc(20 * var(--u));
  }
  #ecran-profil > h2 { grid-column: 1 / -1; grid-row: 1; justify-self: center; }
  /* (« align-self: start » : le socle étire le formulaire, ce qui valait pour
     sa LARGEUR dans une colonne ; dans cette grille, c'est sa hauteur qui
     s'étirait, et ses rangées s'écartaient pour la remplir. Les écarts de sa
     grille se disent ICI : écrits sur « #form-profil », ils cédaient à la règle
     « #ecran-profil form » du téléphone, plus précise) */
  #ecran-profil > form { grid-column: 1; grid-row: 2 / 5; align-self: start; column-gap: calc(14 * var(--u)); row-gap: calc(14 * var(--u)); }
  #ecran-profil > h2 + .note { grid-column: 2; grid-row: 2; }
  #profil-reseaux { grid-column: 2; grid-row: 3; }
  #zone-suppression { grid-column: 2; grid-row: 4; margin-top: 0; }
  #ecran-profil > h2 + .note, #profil-reseaux { padding: calc(3 * var(--u)) 0 calc(4 * var(--u)) calc(18 * var(--u)); }
  /* les champs : le pseudo sur toute la largeur, l'âge et le département côte
     à côte, le sexe sur toute la largeur, les deux boutons côte à côte */
  #form-profil { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; }
  /* le nom le plus long (« Département (ex. 75, 2A, 971) ») tient sur une ligne dans sa demi-colonne */
  #form-profil > label { letter-spacing: 0.09em; }
  #form-profil > label:first-of-type, #profil-sexe { grid-column: 1 / -1; }
  #form-profil > button[type="submit"] { margin: calc(4 * var(--u)) 0; }
  #form-profil > #btn-retour-salon { margin: calc(4 * var(--u)) 0; }
}


/* ============================================================================
   5. MES STATISTIQUES (#ecran-stats)
   ----------------------------------------------------------------------------
   La plaque du titre, les chiffres, la plaque « Dernières parties », la liste
   (elle seule défile, à l'intérieur), et les deux gestes de l'écran.
   La hiérarchie (socle, section 12 bis ; refait le 2026-10-09) : LES CHIFFRES
   sont le héros, dans UN panneau cerclé, séparés par des filets (six cartes
   cerclées chacune faisaient six cadres de la taille d'un bouton) ; la liste est
   une information, sous un filet fin ; « Retour au jeu » et le bouton du
   classement sont deux tuiles côte à côte (c'étaient deux barres de verre
   identiques, l'une sous l'autre). Aucune touche de laiton : rien ici n'est à
   faire d'abord.
   LES CARTES : trois aujourd'hui, six demain (un autre chantier en ajoute).
   Sur téléphone, trois par rangée ; quatre : deux par rangée. Sur ordinateur,
   jusqu'à trois : empilées, le chiffre à côté de son nom ; au-delà : deux par
   rangée, le chiffre au-dessus.
   ========================================================================== */
#ecran-stats { gap: var(--ecart); }
#stats-cartes {
  display: flex; flex-wrap: wrap; gap: 0; flex: none; overflow: hidden;
  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), 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);
}
/* (un filet à droite et un filet dessous : ceux du bord du panneau sont rognés par lui) */
#stats-cartes > .carte {
  flex: 1 1 calc(33.333% - var(--ecart-touches)); min-width: 0;
  padding: calc(13 * var(--u)) calc(6 * var(--u)) calc(12 * var(--u)); border-radius: 0;
  background: none;
  box-shadow: 1px 0 0 rgba(var(--metal-clair-rvb), 0.2), 0 1px 0 rgba(var(--metal-clair-rvb), 0.2);
}
#stats-cartes > .carte .valeur { font-size: calc(var(--taille-titre) * 0.94); }
#stats-cartes > .carte .libelle { text-wrap: balance; }
/* exactement quatre cartes : deux par rangée (trois puis une seule serait bancal) */
#stats-cartes > .carte:first-child:nth-last-child(4),
#stats-cartes > .carte:first-child:nth-last-child(4) ~ .carte { flex-basis: calc(50% - var(--ecart-touches)); }
#ecran-stats > h3 { flex: none; }
#stats-dernieres {
  flex: 1 1 0; min-height: calc(92 * var(--u));
  background: linear-gradient(180deg, rgba(var(--verre-haut), 0.66), rgba(var(--verre-bas), 0.78));
  -webkit-backdrop-filter: var(--verre-flou); backdrop-filter: var(--verre-flou);
  box-shadow: inset 0 0 0 max(1px, calc(1.1 * var(--u))) rgba(var(--metal-clair-rvb), 0.24), 0 0 0 1px rgba(0, 0, 0, 0.6);
}
#stats-dernieres > li { min-height: calc(42 * var(--u)); line-height: 1.3; }
#stats-dernieres > li.note { justify-content: center; text-align: center; color: var(--texte-doux); }
#ecran-stats .barre-outils { flex: none; }
#ecran-stats .barre-outils > button { flex: 1 1 0; }
/* une flèche de retour */
#btn-retour-stats { --picto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19.4 12H4.8M10.6 6.2L4.8 12l5.8 5.8'/%3E%3C/svg%3E"); }

@media (orientation: landscape) and (max-height: 560px) {
  /* téléphone couché : les cartes à gauche, la liste à droite */
  #ecran-stats {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); grid-template-rows: auto minmax(0, 1fr) auto;
    column-gap: var(--ecart-colonnes); row-gap: var(--ecart); align-items: stretch;
  }
  #ecran-stats > h2 { grid-column: 1; grid-row: 1; justify-self: center; }
  #stats-cartes { grid-column: 1; grid-row: 2; align-content: center; }
  #ecran-stats .barre-outils { grid-column: 1; grid-row: 3; }
  #ecran-stats > h3 { grid-column: 2; grid-row: 1; justify-self: center; }
  #stats-dernieres { grid-column: 2; grid-row: 2 / 4; min-height: 0; }
  /* Au-delà de trois cartes (six avec le classement général), la colonne de gauche est trop basse pour tout
     empiler : les cartes se serrent, les deux boutons se rangent côte à côte, et si la place manque encore
     les cartes défilent dans LEUR zone (elles passaient sous le titre et sous « Retour au jeu »). */
  #stats-cartes { align-content: start; min-height: 0; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--metal-sombre) transparent; }
  #stats-cartes > .carte:first-child:nth-last-child(n + 4),
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) ~ .carte { padding: calc(5 * var(--u)) calc(4 * var(--u)); border-radius: calc(10 * var(--u)); }
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) .valeur,
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) ~ .carte .valeur { font-size: calc(var(--taille-titre) * 0.74); }
  #ecran-stats .barre-outils { flex-wrap: nowrap; align-items: stretch; }
  #ecran-stats .barre-outils > button { flex: 1 1 0; min-width: 0; padding-left: calc(6 * var(--u)); padding-right: calc(6 * var(--u)); line-height: 1.1; }
}
@media (min-width: 900px) and (min-aspect-ratio: 21/20) and (min-height: 561px) {
  #ecran-stats {
    display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr); grid-template-rows: auto auto minmax(0, 1fr);
    column-gap: var(--ecart-colonnes); row-gap: calc(12 * var(--u)); align-items: stretch;
  }
  /* la plaque du titre au milieu de la rangée du haut, « Retour au jeu » à sa gauche.
     La barre prend toute la rangée : un second bouton (celui du classement général,
     pupitre/classement.css) se range à DROITE de la plaque. Dans la seule colonne de
     gauche, il passait sous « Retour au jeu » et la rangée doublait de hauteur. */
  #ecran-stats > h2 { grid-column: 1 / -1; grid-row: 1; justify-self: center; align-self: center; }
  #ecran-stats .barre-outils { grid-column: 1 / -1; grid-row: 1; justify-content: flex-start; flex-wrap: nowrap; align-items: center; }
  /* (dans la rangée du titre, une tuile est basse : son pictogramme à gauche de son libellé) */
  #ecran-stats .barre-outils > button { flex: none; flex-direction: row; align-items: center; gap: calc(9 * var(--u)); min-height: var(--hauteur-bouton); padding: calc(4 * var(--u)) calc(16 * var(--u)); text-align: left; }
  #stats-cartes { grid-column: 1; grid-row: 2 / 4; }
  #ecran-stats > h3 { grid-column: 2; grid-row: 2; justify-self: center; }
  #stats-dernieres { grid-column: 2; grid-row: 3; min-height: 0; padding: calc(8 * var(--u)) calc(10 * var(--u)); }
  #stats-dernieres > li { min-height: calc(54 * var(--u)); padding: calc(6 * var(--u)) calc(16 * var(--u)); }
  /* jusqu'à trois cartes : empilées, le chiffre à gauche, son nom à droite */
  #stats-cartes > .carte {
    flex: 1 1 100%; flex-direction: row; justify-content: flex-start; gap: calc(26 * var(--u));
    padding: calc(12 * var(--u)) calc(30 * var(--u)); border-radius: 0; text-align: left;
  }
  #stats-cartes > .carte .valeur { flex: 0 0 calc(110 * var(--u)); text-align: center; font-size: calc(var(--taille-titre) * 1.1); }
  #stats-cartes > .carte .libelle { font-size: calc(var(--taille-etiquette) * 1.3); letter-spacing: 0.14em; }
  /* quatre cartes et plus : deux par rangée, le chiffre au-dessus de son nom */
  #stats-cartes > .carte:first-child:nth-last-child(n + 4),
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) ~ .carte {
    flex: 1 1 calc(50% - var(--ecart-touches)); flex-direction: column; justify-content: center; gap: calc(6 * var(--u));
    padding: calc(12 * var(--u)) calc(10 * var(--u)); text-align: center;
  }
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) .valeur,
  #stats-cartes > .carte:first-child:nth-last-child(n + 4) ~ .carte .valeur { flex: none; font-size: var(--taille-titre); }
}
