/* rosetta — feuille de style écrite à la main, mobile d'abord (lisible dès 380px). */

:root {
  --couleur-fond: #14171c;
  --couleur-carte: #1a1e24;
  --couleur-texte: #e8e6e1;
  --couleur-attenuee: #8a8f98;
  --couleur-accent: #4f8cff;
  --couleur-trouve: #3fb27f;
  --couleur-absent: #3a3f47;
  --couleur-bordure: #2a2e35;
  --couleur-cache: #2a2e35;
  --couleur-near: #c9a227;
  --couleur-erreur: #e5484d;
  --rayon: 6px;
  --espacement: 1rem;
  --hauteur-entete: 3.5rem;
  --largeur-contenu: 42rem;
  --largeur-jeu: 78rem;
  --largeur-essais: 20rem;
}

* {
  box-sizing: border-box;
}

/* Colonne pleine hauteur : le pied reste en bas même sur une page courte. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  margin: 0;
  padding: 0;
  background: var(--couleur-fond);
  color: var(--couleur-texte);
  font-family:
    system-ui,
    -apple-system,
    "Segoe UI",
    sans-serif;
  line-height: 1.5;
}

a {
  color: inherit;
  text-decoration: none;
}

.entete {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  height: var(--hauteur-entete);
  padding: 0 2.5rem;
  background: var(--couleur-fond);
  border-bottom: 1px solid var(--couleur-bordure);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.entete .beta {
  margin-left: 0.5rem;
  padding: 0.1rem 0.4rem;
  border-radius: var(--rayon);
  background: color-mix(in srgb, var(--couleur-near) 20%, transparent);
  color: var(--couleur-near);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: uppercase;
}

.nav-compte {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-left: auto;
  font-size: 0.9rem;
  font-weight: 400;
}

.nav-compte a {
  color: var(--couleur-attenuee);
}

.nav-compte .pseudo {
  color: var(--couleur-texte);
  font-weight: 600;
}

.nav-compte .niveau {
  margin-left: 0.35rem;
  color: var(--couleur-attenuee);
  font-weight: 400;
  font-size: 0.8rem;
}

.barre-niveau {
  display: inline-block;
  width: 3rem;
  height: 0.4rem;
  background: var(--couleur-absent);
  border-radius: var(--rayon);
  overflow: hidden;
}

.barre-niveau-remplissage {
  display: block;
  height: 100%;
  width: var(--pourcentage);
  background: var(--couleur-accent);
}

.lien-bouton {
  padding: 0;
  background: none;
  border: none;
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
  font-weight: 400;
  cursor: pointer;
}

main {
  flex: 1 0 auto;
  width: 100%;
  max-width: var(--largeur-contenu);
  margin: 0 auto;
  padding: 1.5rem 1rem 3rem;
}

main.large {
  max-width: var(--largeur-jeu);
}

.accueil {
  text-align: center;
  margin-top: 4rem;
}

.accueil p {
  color: var(--couleur-attenuee);
  margin-bottom: 1.5rem;
}

.actions-accueil {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.5rem;
  margin-top: 2.5rem;
}

/* `.cta-principale` a son propre padding/taille, plus généreux qu'un bouton par
   défaut (voulu dans le popup de victoire) — ici les deux boutons doivent avoir la
   même hauteur, donc les deux reçoivent le même gabarit explicite, `line-height`
   compris : sans lui, le `<button>` (qui n'a pas de `line-height` propre) hérite du
   `1.5` sans unité de `body`, recalculé contre SA PROPRE taille de police — pas la
   même hauteur de ligne que `.cta-principale`, qui en pose une fixe (1.2rem), même
   avec un `padding`/`font-size` par ailleurs identiques. */
.actions-accueil button,
.actions-accueil a {
  padding: 0.75rem 1.75rem;
  font-size: 1rem;
  line-height: 1.2rem;
}

.invite-connexion {
  padding: 0.75rem 1rem;
  margin-bottom: 1.25rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

.invite-connexion a {
  color: var(--couleur-accent);
  text-decoration: underline;
}

.formulaire-compte {
  max-width: 24rem;
  margin: 2rem auto 0;
}

.formulaire-compte h1 {
  font-size: 1.5rem;
  margin-bottom: 1.5rem;
}

.formulaire-compte form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.formulaire-compte label {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.9rem;
  color: var(--couleur-attenuee);
}

.formulaire-compte input {
  padding: 0.6rem 0.75rem;
  font-size: 1rem;
  background: var(--couleur-absent);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
}

.formulaire-compte input:focus {
  outline: 2px solid var(--couleur-accent);
  outline-offset: 1px;
}

.formulaire-compte button {
  margin-top: 0.5rem;
}

.erreur {
  padding: 0.6rem 0.75rem;
  margin-bottom: 1rem;
  background: color-mix(in srgb, var(--couleur-erreur) 18%, transparent);
  border-radius: var(--rayon);
  color: var(--couleur-erreur);
  font-size: 0.9rem;
}

.lien-secondaire {
  margin-top: 1.25rem;
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

.lien-secondaire a {
  color: var(--couleur-accent);
  text-decoration: underline;
}

/* Jeu à gauche, essais à droite ; une seule colonne sous 64rem. */
.plateau {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
}

.titre {
  font-size: 1.4rem;
  font-weight: 700;
  margin: 0 0 1rem;
}

.corps {
  white-space: pre-wrap;
  line-height: 1.7;
  color: var(--couleur-texte);
}

.mot {
  color: var(--couleur-texte);
}

.mot.cache {
  display: inline-block;
  width: calc(var(--n) * 1ch);
  height: 1em;
  vertical-align: text-bottom;
  background: var(--couleur-cache);
  border-radius: 3px;
}

.mot.cache.near {
  --proximite: 0.5; /* filet de sécurité si jamais non défini */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* `height` fixée en `rem`, pas en `em` : sinon elle se recalculerait sur le
     `font-size` réduit ci-dessous plutôt que sur celui, ambiant, des boîtes vides
     (`.mot.cache`), et la boîte deviendrait plus basse qu'elles. */
  height: 1rem;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.8rem;
  font-weight: 600;
  color: color-mix(
    in srgb,
    var(--couleur-near) calc(var(--proximite) * 100%),
    var(--couleur-attenuee)
  );
}

.statut {
  margin: 1rem 0;
  padding: 0.5rem 0.75rem;
  border-radius: var(--rayon);
  font-weight: 600;
}

/* Le badge « Gagné ! » (`.statut.victoire`, avec ses actions secondaires) et le CTA
   « Nouvelle partie » / « Retourner dans le salon » sont deux frères, posés côte à
   côte — voir le commentaire dans `_jeu.html`. `flex-wrap` : sur un écran étroit
   (mobile d'abord, lisible dès 380px), le CTA passe à la ligne plutôt que de
   comprimer le badge ou déborder. Cette ligne porte l'espacement vertical à la
   place de `.statut` (`margin`, pensé pour un badge isolé, qui doublerait ici).
   `align-items: stretch` (le défaut flex, posé ici explicitement) : le badge et le
   CTA prennent la même hauteur, celle du plus grand des deux — voir `.cta-fantome`
   et `.ligne-victoire form` pour ce que ça implique côté bouton. */
.ligne-victoire {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1rem 0;
}

/* Formulaire du CTA solo (nécessaire pour le POST) : sans boîte propre, sinon
   `.cta-fantome` ne serait pas l'enfant flex direct de `.ligne-victoire` et
   n'hériterait pas de son `align-items: stretch` — le bouton resterait à sa hauteur
   naturelle pendant que le formulaire, lui, s'étirerait autour de lui à vide. */
.ligne-victoire form {
  display: contents;
}

.statut.victoire {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  background: color-mix(in srgb, var(--couleur-trouve) 25%, transparent);
  color: var(--couleur-trouve);
}

.actions-victoire .lien-bouton {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
}

/* « Voir mes résultats » + « Voir l'article complet » : actions secondaires DANS le
   badge « Gagné ! », à côté de son texte. */
.actions-victoire {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Version compacte et « fantôme » de `.cta-principale` — même couleur d'accent
   (`--couleur-near`), mais fond teinté à faible opacité plutôt qu'un remplissage
   plein : un vrai bouton (fond, coins), pas juste un lien comme les autres actions
   du groupe — c'est celle qui mène à la partie suivante, en retrait du `.cta-principale`
   plein du popup, réservé à l'action la plus engageante de l'écran. */
.cta-fantome {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.4rem 1rem;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  background: color-mix(in srgb, var(--couleur-near) 20%, transparent);
  color: var(--couleur-near);
  border: none;
  border-radius: var(--rayon);
  cursor: pointer;
}

/* `[open]` est nécessaire, pas cosmétique : sans lui, ces règles (feuille auteur)
   l'emportent sur `dialog:not([open]) { display: none }` du navigateur (feuille
   user-agent, toujours perdante face à l'auteur, quelle que soit la spécificité) —
   le popup resterait visible, hors de la top layer, après sa propre fermeture. */
.popup-victoire[open] {
  position: fixed;
  margin: auto;
  width: calc(100vw - 3rem);
  max-width: 40rem;
  max-height: calc(100dvh - 4rem);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 2.25rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
}

.popup-victoire[open]::backdrop {
  background: rgba(0, 0, 0, 0.6);
}

.popup-victoire h2 {
  margin: 0;
  font-size: 1.4rem;
}

.stats-partie {
  display: flex;
  gap: 2rem;
  margin: 0;
}

.stats-partie > div {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.stats-partie dt {
  font-size: 0.75rem;
  color: var(--couleur-attenuee);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.stats-partie dd {
  margin: 0;
  font-size: 1.4rem;
  font-weight: 700;
}

.bloc-xp {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.xp-total {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--couleur-near);
}

/* Détail des bonus : plus petit et plus discret que le total — c'est lui
   l'explication, le total au-dessus reste la seule chose qui saute aux yeux. */
.xp-detail {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8rem;
  color: var(--couleur-attenuee);
}

/* Sépare visuellement les bonus de groupe (avec leur multiplicateur) des bonus
   solo au-dessus — pour que celui-ci ne semble pas s'appliquer à toute la liste. */
.xp-detail-groupe {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--couleur-bordure);
}

/* Masquées par défaut : `game.js` ajoute `.visible` ligne par ligne, une fois le
   décompte du total terminé — jamais au chargement, sinon l'apparition n'aurait
   plus rien à montrer. */
.xp-detail li {
  display: flex;
  gap: 1.5rem;
  opacity: 0;
  transform: translateX(0.75rem);
  transition:
    opacity 0.35s ease,
    transform 0.35s ease;
}

.xp-detail li.visible {
  opacity: 1;
  transform: none;
}

.xp-detail-montant {
  flex-shrink: 0;
  width: 2.25rem;
  color: var(--couleur-near);
  font-weight: 600;
}

/* Écran d'attente du popup de victoire (partie de room, manche pas encore close) :
   remplace le détail XP tant que `room_victory.bonus` est vide — voir _jeu.html. */
.attente-manche {
  margin: 0.5rem 0;
}

.statut-manche {
  margin: 0 0 0.75rem;
  font-weight: 600;
  color: var(--couleur-texte);
}

.lien-article {
  text-align: center;
  margin: 1rem 0 1rem;
  font-size: 0.9rem;
}

.lien-article a {
  color: var(--couleur-accent);
  text-decoration: underline;
}

/* CTA principale du popup : après les stats et l'XP, avant tout le reste — c'est
   l'action attendue, pas la notation ni le signalement. « Jouer en groupe » s'y
   ajoute, même poids visuel, seulement pour un compte (une room n'est pas jouable
   anonymement). */
.nouvelle-partie {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  margin: 1.5rem 0 1.5rem;
}

/* Autonome (pas seulement un `background` posé sur `button`) : utilisée aussi bien
   sur un `<button>` que sur un `<a>` (« Jouer en groupe »), qui n'hérite d'aucun
   style de bouton par défaut. */
.cta-principale {
  display: inline-block;
  padding: 0.85rem 2rem;
  line-height: 1.2rem;
  font-size: 1.05rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  background: var(--couleur-near);
  color: #fff;
  border: none;
  border-radius: var(--rayon);
  cursor: pointer;
}

/* « Lancer un nouveau round » : désactivé tant que le salon n'a pas assez de
   joueurs, même logique que `.bouton-secondaire:disabled`. */
.cta-principale:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.statut.abandon,
.statut.message {
  font-weight: 400;
  font-size: 0.9rem;
  background: color-mix(in srgb, var(--couleur-attenuee) 20%, transparent);
  color: var(--couleur-attenuee);
}

/* Notation et signalement sont secondaires face à « Nouvelle partie » — même
   traitement que `.actions-secondaires button` (bordé, atténué, sans accent). */
.bouton-secondaire {
  background: transparent;
  color: var(--couleur-attenuee);
  border: 1px solid var(--couleur-bordure);
  font-weight: 400;
}

.avis {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 0;
}

.deja-envoye {
  margin: 0;
  color: var(--couleur-attenuee);
  font-size: 0.85rem;
}

.formulaire-avis {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.75rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
}

.titre-avis {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--couleur-texte);
}

.champs-avis {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.formulaire-avis label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--couleur-attenuee);
}

.formulaire-avis select {
  padding: 0.4rem 0.5rem;
  background: var(--couleur-absent);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
}

.retrait {
  position: relative;
  font-size: 0.85rem;
}

/* `.avis` empile ses enfants en colonne sans `align-items`, donc `.retrait`
   s'étire par défaut sur toute sa largeur — ce qui décale d'autant le popup
   ancré en `left: 100%`. Dans `.actions-secondaires` (ligne), l'alignement
   centré du conteneur suffit déjà : pas besoin d'y toucher. */
.avis .retrait {
  align-self: flex-start;
}

.retrait summary {
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
  line-height: 1.5;
  cursor: pointer;
}

/* Popup flottant : ancré au coin bas-droit du lien, sans jamais pousser le reste de
   la mise en page — le `<details>` ne mesure que son `<summary>` puisque le
   formulaire, en position absolue, en sort du flux. */
.retrait form {
  position: absolute;
  left: 100%;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  width: 16rem;
  max-width: calc(100vw - 2rem);
  margin-left: 0.75rem;
  padding: 1.75rem 0.75rem 0.75rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}

/* `.avis .retrait { align-self: flex-start }` réduit `.retrait` à la largeur de
   son lien — voulu quand le formulaire flotte à côté, pas ici où il doit occuper
   la largeur du popup en dessous. Même spécificité que cette règle : la seule
   garantie de gagner est de rester après elle dans ce fichier. */
.popup-victoire .retrait {
  align-self: stretch;
}

/* Dans le popup de victoire, pas la place de flotter à droite du lien — le
   formulaire reprend un flux normal sous lui. */
.popup-victoire .retrait form {
  position: static;
  width: 100%;
  max-width: none;
  margin: 0.5rem 0 0;
  padding: 0.75rem;
  box-shadow: none;
}

/* Le popup de victoire a déjà sa propre croix de fermeture — en ajouter une
   seconde ici, identique, ne fait que dupliquer un même geste sans rien
   clarifier. Le lien « Signaler cette page » reste le moyen de refermer ce
   sous-formulaire, comme n'importe quel <details>. */
.popup-victoire .retrait .fermer-retrait {
  display: none;
}

.fermer-retrait {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--couleur-attenuee);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}

.fermer-retrait:hover {
  background: var(--couleur-absent);
  color: var(--couleur-texte);
}

.retrait label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--couleur-attenuee);
}

.retrait select,
.retrait textarea {
  padding: 0.5rem 0.6rem;
  font: inherit;
  background: var(--couleur-absent);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
  resize: vertical;
}

form.essai {
  display: flex;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
}

form.essai input {
  flex: 1;
  min-width: 0;
  padding: 0.6rem 0.75rem;
  font-size: 1rem;
  background: var(--couleur-absent);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
}

form.essai input:focus {
  outline: 2px solid var(--couleur-accent);
  outline-offset: 1px;
}

/* Remplace « Nouvelle partie » (bouton par défaut) quand la partie appartient à une
   manche de room — même gabarit visuel, mais un lien plutôt qu'un bouton puisqu'il
   n'y a pas de formulaire à soumettre, juste une navigation. */
.lien-salon-retour {
  display: inline-block;
  margin: 0 0 1.25rem;
  padding: 0.6rem 1rem;
  font-size: 1rem;
  font-weight: 600;
  background: var(--couleur-accent);
  color: #fff;
  border-radius: var(--rayon);
  text-decoration: none;
}

button {
  /* Les boutons n'héritent pas `font-family`/`line-height` du body par défaut
     (contrairement à un `<a>`) — sans ça, deux `.cta-principale` sur deux lignes,
     l'un un `<button>` et l'autre un `<a>`, n'ont pas la même hauteur malgré un
     padding et une taille de police identiques. `font-size`/`font-weight`
     ci-dessous se réappliquent après pour garder l'apparence voulue. */
  font: inherit;
  padding: 0.6rem 1rem;
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: var(--rayon);
  background: var(--couleur-accent);
  color: #fff;
  cursor: pointer;
}

.actions-secondaires {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-top: 1.5rem;
}

.actions-secondaires button {
  background: transparent;
  color: var(--couleur-attenuee);
  border: 1px solid var(--couleur-bordure);
  font-weight: 400;
  font-size: 0.9rem;
}

.zone-essais {
  padding: 0 1rem 1rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
}

.compteur {
  margin: 0;
  padding: 0.75rem 0 0.5rem;
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

.zone-essais .vide {
  margin: 0 0 0.25rem;
  color: var(--couleur-attenuee);
  font-size: 0.85rem;
}

table.historique {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

table.historique th,
table.historique td {
  padding: 0.4rem 0.5rem;
  text-align: left;
  border-bottom: 1px solid var(--couleur-bordure);
}

/* L'en-tête reste visible quand la liste défile dans son propre bloc. */
table.historique th {
  position: sticky;
  top: 0;
  background: var(--couleur-carte);
  color: var(--couleur-attenuee);
  font-weight: 600;
}

td.points {
  cursor: default;
}

/* Repère la ligne du joueur connecté sur /classement. */
table.historique tr.moi {
  background: color-mix(in srgb, var(--couleur-accent) 12%, transparent);
}

table.historique tr.moi td {
  font-weight: 600;
}

/* Repère la ligne « Partie en cours » dans l'historique du profil (titre masqué
   tant que la partie n'est pas terminée, voir `pipeline.profile.GameHistoryRow`) —
   distincte visuellement d'un vrai titre de page, pas juste par le texte. */
.page-en-cours {
  color: var(--couleur-accent);
  font-style: italic;
  font-weight: 600;
}

.compte {
  margin-right: 0.4rem;
}

.point {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  margin-right: 0.6rem;
  border-radius: 50%;
}

.point:last-child {
  margin-right: 0;
}

.point.trouve {
  background: var(--couleur-trouve);
}

.point.proche {
  background: var(--couleur-near);
}

.pied {
  padding: 1rem;
  border-top: 1px solid var(--couleur-bordure);
  text-align: center;
}

.pied a {
  color: var(--couleur-attenuee);
  font-size: 0.85rem;
}

.pied .version {
  color: var(--couleur-attenuee);
  font-size: 0.75rem;
}

.mentions dt {
  margin-top: 1rem;
  font-weight: 700;
}

.mentions dd {
  margin: 0.25rem 0 0;
  color: var(--couleur-attenuee);
}

.mentions a {
  color: var(--couleur-accent);
  text-decoration: underline;
}

.vide {
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

.dim {
  color: var(--couleur-attenuee);
  font-weight: 400;
}

.admin-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--couleur-bordure);
}

.admin-nav a {
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

.stats-admin {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  margin: 0 0 2rem;
}

.stats-admin dt {
  margin: 0;
  font-size: 0.75rem;
  color: var(--couleur-attenuee);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.stats-admin dd {
  margin: 0.2rem 0 0;
  font-size: 1.6rem;
  font-weight: 700;
}

/* Légende d'un chiffre de `.stats-admin` (ex. la page de la meilleure partie sur
   /profil) — sur sa propre ligne dans la même `dd`, mais nettement plus discrète
   que le chiffre pour rester une précision, pas une deuxième statistique. */
.stats-admin-detail {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--couleur-attenuee);
}

.groupe-demandes {
  padding: 1rem 0;
  border-bottom: 1px solid var(--couleur-bordure);
}

.groupe-demandes h2 {
  margin: 0 0 0.75rem;
  font-size: 1.1rem;
}

.actions-page {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.salon-panneau {
  margin-top: 1.5rem;
  padding: 1rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
}

.titre-section {
  margin: 0 0 0.75rem;
  font-size: 1.1rem;
}

.salon-hote,
.salon-manche {
  margin: 0 0 0.5rem;
}

.salon-code {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.5rem;
}

.salon-membres {
  margin: 0 0 1rem;
  padding: 0;
  list-style: none;
  color: var(--couleur-attenuee);
}

.salon-copier-conteneur {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.bouton-copier {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  background: transparent;
  color: var(--couleur-attenuee);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  cursor: pointer;
}

.bouton-copier:hover {
  color: var(--couleur-texte);
  border-color: var(--couleur-accent);
}

/* Le clic doit toujours résoudre sur le bouton, jamais sur le SVG qu'il contient. */
.bouton-copier svg {
  pointer-events: none;
}

/* Étiquette de confirmation, flottante à droite de l'icône — masquée par défaut,
   révélée pour `DUREE_CONFIRMATION_COPIE_MS` par `game.js` au clic. */
.salon-copier-confirmation {
  position: absolute;
  left: calc(100% + 0.5rem);
  top: 50%;
  padding: 0.25rem 0.6rem;
  background: var(--couleur-carte);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-trouve);
  font-size: 0.8rem;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-4px, -50%);
  transition:
    opacity 0.2s ease,
    transform 0.2s ease;
  pointer-events: none;
}

.salon-copier-confirmation.visible {
  opacity: 1;
  transform: translate(0, -50%);
}

/* Lobby « Jouer en groupe » : deux options de poids égal, côte à côte au-delà d'un
   petit écran — même carte que le reste du panneau social (`.salon-panneau`). */
.salon-options {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.salon-option {
  flex: 1 1 16rem;
  margin-top: 0;
  display: flex;
  flex-direction: column;
}

.salon-explication {
  margin: 0 0 1rem;
  color: var(--couleur-attenuee);
  font-size: 0.9rem;
}

/* Centre le bouton « Créer un salon » à la fois horizontalement et dans le reste de
   hauteur du panneau, une fois le titre et le texte posés au-dessus. */
.salon-option-action {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.salon-code-label {
  margin: 1.25rem 0 0.4rem;
  color: var(--couleur-attenuee);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.salon-code-champs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.salon-code-case {
  width: 2.5rem;
  height: 3rem;
  padding: 0;
  font: inherit;
  font-size: 1.4rem;
  font-weight: 600;
  text-align: center;
  text-transform: uppercase;
  background: var(--couleur-absent);
  border: 1px solid var(--couleur-bordure);
  border-radius: var(--rayon);
  color: var(--couleur-texte);
}

.salon-code-case:focus {
  outline: 2px solid var(--couleur-accent);
  outline-offset: 1px;
}

/* Transparent (`.bouton-secondaire`) tant que les cases ne sont pas toutes remplies,
   couleur pleine une fois le code complet — le bouton lui-même signale qu'il est
   prêt, sans texte d'aide supplémentaire. */
.bouton-secondaire.pret {
  background: var(--couleur-accent);
  color: #fff;
  border-color: transparent;
  font-weight: 600;
}

/* `.bouton-secondaire` est déjà transparent/atténué à l'état normal — sans ceci, un
   bouton désactivé (ex. « Démarrer une manche » à un seul joueur) est quasiment
   indiscernable d'un bouton actif, et un clic dessus ne fait simplement rien
   (formulaire non soumis) sans que ce soit visible pourquoi. */
.bouton-secondaire:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

@media (min-width: 640px) {
  .titre {
    font-size: 1.75rem;
  }
}

@media (min-width: 64rem) {
  .plateau {
    grid-template-columns: minmax(0, 1fr) var(--largeur-essais);
    align-items: start;
    gap: 2rem;
  }

  .zone-essais {
    position: sticky;
    top: calc(var(--hauteur-entete) + 1.5rem);
    max-height: calc(100dvh - var(--hauteur-entete) - 3rem);
    overflow-y: auto;
  }
}
