/* Les deux consoles — administration et maître du jeu.
 *
 * Elles sont séparées de `style.css` pour la même raison qu'elles sont les
 * seules à charger Preact : ce ne sont pas des terrains de jeu. L'écran partagé
 * et la manette dessinent dans un canvas et n'ont presque pas de chrome ; ces
 * deux pages-ci sont des interfaces de conduite, avec des boutons, des champs,
 * des états et des confirmations. Mélanger les deux vocabulaires dans un seul
 * fichier avait produit des règles qui ne servaient qu'à une page sur cinq.
 *
 * `style.css` reste chargé en premier : il apporte la palette, la remise à zéro
 * et la règle `[hidden]`. Ce fichier n'ajoute que ce qui manque. */

/* ─── Jetons ───────────────────────────────────────────────────────────────── */
/* Les surfaces sont des OPACITÉS sur le fond, pas des couleurs figées : elles
   restent justes si `--bg` change, et elles s'empilent proprement (une carte
   dans un panneau se détache toujours de lui). */
:root {
  --surface: rgba(238, 242, 248, 0.04);
  --surface-2: rgba(238, 242, 248, 0.07);
  --surface-3: rgba(238, 242, 248, 0.11);
  --line: rgba(238, 242, 248, 0.12);
  --line-2: rgba(238, 242, 248, 0.24);

  --ok: #8ac926;
  --live: #50dc8c;
  --warn: #f5b301;
  --danger: #ff595e;

  --r-sm: 0.5rem;
  --r-md: 0.75rem;
  --r-lg: 1.1rem;
  --r-pill: 999px;

  /* Cible tactile minimale. Le nombre est repris tel quel par tous les
     contrôles : le jour où il change, il change partout. */
  --touch: 44px;
}

/* Le focus clavier est VISIBLE partout, sans exception.
 *
 * `:focus-visible` et pas `:focus` : le navigateur ne le pose qu'à la
 * navigation clavier, donc un clic à la souris sur un bouton ne laisse pas de
 * halo derrière lui. C'est ce qui permet de le rendre franchement visible sans
 * que personne ne demande à le retirer. */
.console :focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Les deux consoles sont des documents lisibles, pas des terrains : on doit
   pouvoir sélectionner un lien pour le recopier à la main quand le
   presse-papier est refusé (http en clair). */
.console {
  user-select: text;
  -webkit-user-select: text;
  line-height: 1.45;
}

@media (prefers-reduced-motion: reduce) {
  .console *,
  .console *::before,
  .console *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── Boutons ──────────────────────────────────────────────────────────────── */
/* Un seul bouton pour les deux pages, décliné par modificateurs. Avant, la
   console avait `.mj-btn` et l'administration `.linkish`, qui ne partageaient ni
   leur hauteur, ni leur rayon, ni leur état de survol — deux systèmes pour le
   même geste. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--touch);
  padding: 0.55rem 1rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s,
    transform 0.06s;
}

.btn:hover:not(:disabled) {
  background: var(--surface-2);
  border-color: var(--line-2);
}

.btn:active:not(:disabled) {
  transform: scale(0.98);
  background: var(--surface-3);
}

.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #08202b;
}

.btn.is-primary:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 85%, #fff);
  border-color: color-mix(in srgb, var(--accent) 85%, #fff);
}

/* Discret : la même surface que le fond, la bordure seule le désigne comme
   cliquable. Pour tout ce qu'on ne veut pas voir avant d'en avoir besoin. */
.btn.is-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
  font-weight: 500;
}

.btn.is-ghost:hover:not(:disabled) {
  background: var(--surface);
  color: var(--ink);
}

/* Rouge seulement au survol et à la confirmation : une rangée de boutons rouges
   au repos fait fuir l'œil de toute la liste, alors qu'un seul d'entre eux est
   réellement destructeur. */
.btn.is-danger:hover:not(:disabled),
.btn.is-danger.is-armed {
  border-color: var(--danger);
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 14%, transparent);
}

.btn.is-small {
  min-height: 36px;
  padding: 0.3rem 0.75rem;
  font-size: 0.85rem;
  font-weight: 500;
  border-radius: var(--r-pill);
}

/* Un bouton dont l'appui est ARMÉ : il attend une seconde confirmation et le
   dit, au lieu d'ouvrir une fenêtre modale par-dessus la salle. */
.btn.is-armed {
  border-color: var(--warn);
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 16%, transparent);
}

/* ─── Champs ───────────────────────────────────────────────────────────────── */
.field {
  min-width: 0;
  min-height: var(--touch);
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: rgba(0, 0, 0, 0.28);
  color: var(--ink);
  font-family: inherit;
  /* 16 px minimum : en deçà, iOS zoome sur le champ à la mise au point et toute
     la page saute — sur la console du maître du jeu, en pleine soirée. */
  font-size: 16px;
}

.field::placeholder {
  color: color-mix(in srgb, var(--muted) 75%, transparent);
}

.field:focus {
  outline: none;
  border-color: var(--accent);
}

/* ─── Pastilles d'état ─────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

/* La pastille précède le texte et porte l'information : elle se lit sans se
   lire, à la couleur, dans une liste qu'on parcourt à la verticale. */
.badge::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

.badge.is-live {
  color: var(--live);
  border-color: color-mix(in srgb, var(--live) 35%, transparent);
  background: color-mix(in srgb, var(--live) 10%, transparent);
}

.badge.is-idle::before {
  background: none;
  border: 1px solid currentColor;
}

.badge.is-closed {
  color: color-mix(in srgb, var(--muted) 80%, transparent);
}

.badge.is-closed::before {
  background: none;
  border: 1px dashed currentColor;
}

/* ─── Message éphémère ─────────────────────────────────────────────────────── */
/* Il remplace la ligne de note qui vivait au milieu de la page : un texte qui
   apparaît et disparaît DANS le flux décalait tout ce qu'il y avait dessous, et
   le bouton visé se dérobait sous le doigt. */
.toast {
  position: fixed;
  left: 50%;
  bottom: max(1.25rem, env(safe-area-inset-bottom));
  z-index: 100;
  transform: translateX(-50%);
  max-width: min(92vw, 34rem);
  padding: 0.7rem 1.1rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: #232935;
  color: var(--ink);
  box-shadow: 0 0.6rem 2rem rgba(0, 0, 0, 0.5);
  font-size: 0.9rem;
  text-align: center;
  overflow-wrap: anywhere;
  animation: toast-in 0.18s ease-out;
}

.toast.is-error {
  border-color: var(--danger);
  color: #ffd7d8;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 0.5rem);
  }
}

/* ─── Fenêtre modale ───────────────────────────────────────────────────────── */
/* `<dialog>` natif : la fermeture par Échap, le piège à focus et le retrait du
   reste de la page de l'arbre d'accessibilité sont fournis par le navigateur.
   Les réécrire à la main, c'est les réécrire à moitié. */
.dlg {
  width: min(92vw, 30rem);
  padding: 1.4rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: #1a1f29;
  color: var(--ink);
  font-family: inherit;
}

.dlg::backdrop {
  background: rgba(8, 10, 14, 0.72);
}

.dlg-title {
  margin: 0 0 0.6rem;
  font-size: 1.15rem;
  font-weight: 700;
}

.dlg-body {
  margin: 0 0 1.3rem;
  color: var(--muted);
  font-size: 0.92rem;
}

.dlg-body code {
  color: var(--ball);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.dlg-foot {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
}

/* ═══ Administration ═══════════════════════════════════════════════════════ */

body.ac {
  overflow: auto;
}

/* Barre collante : la charge de la plateforme et le bouton de déconnexion
   restent atteignables au bas d'une liste de trente évènements. */
.ac-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.8rem clamp(0.9rem, 3vw, 1.6rem);
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
}

.ac-bar h1 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.ac-bar h1 span {
  color: var(--muted);
  font-weight: 400;
}

.ac-bar-gap {
  flex: 1 1 auto;
}

.ac-shell {
  max-width: 64rem;
  margin: 0 auto;
  padding: 1.25rem clamp(0.9rem, 3vw, 1.6rem) 5rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* ─── Charge de la plateforme ──────────────────────────────────────────────── */
/* Elle était une ligne de texte en chasse fixe où sept nombres se suivaient sans
   hiérarchie — il fallait la LIRE en entier pour apprendre que tout allait bien.
   En tuiles, le coup d'œil suffit, et la seule mesure qui décide (le retard de
   boucle) a sa propre jauge. */
.ac-health {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: 0.6rem;
}

.ac-tile {
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

.ac-tile-n {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.ac-tile-k {
  display: block;
  margin-top: 0.15rem;
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
}

/* La tuile du retard prend deux colonnes : elle porte une jauge, et c'est la
   seule des cinq dont la valeur demande un jugement plutôt qu'une lecture. */
.ac-tile.is-lag {
  grid-column: span 2;
}

.ac-gauge {
  height: 4px;
  margin-top: 0.5rem;
  border-radius: 2px;
  background: var(--surface-3);
  overflow: hidden;
}

.ac-gauge-fill {
  height: 100%;
  border-radius: 2px;
  background: var(--live);
  transition: width 0.4s ease-out;
}

.ac-tile.is-warn {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}

.ac-tile.is-warn .ac-tile-n {
  color: var(--danger);
}

.ac-tile.is-warn .ac-gauge-fill {
  background: var(--danger);
}

/* ─── Barre d'outils ───────────────────────────────────────────────────────── */
.ac-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.ac-create {
  display: flex;
  gap: 0.5rem;
  flex: 1 1 20rem;
}

.ac-create .field {
  flex: 1 1 auto;
}

.ac-search {
  flex: 1 1 12rem;
  max-width: 20rem;
}

.ac-filters {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.chip {
  min-height: 36px;
  padding: 0.25rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.chip[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--ink);
  font-weight: 600;
}

/* ─── Liste des évènements ─────────────────────────────────────────────────── */
.ac-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.ac-card {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  transition: border-color 0.15s;
}

.ac-card:hover {
  border-color: var(--line-2);
}

/* Un évènement fermé s'efface, mais reste LISIBLE : à 0.5 d'opacité, son nom
   passait sous le seuil de contraste et on ne pouvait plus décider lequel
   supprimer sans le rouvrir. C'est la bordure qui porte l'état, pas le texte. */
.ac-card.is-closed {
  background: transparent;
  border-style: dashed;
}

.ac-card.is-closed .ac-name,
.ac-card.is-closed .ac-code {
  color: var(--muted);
}

.ac-card-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.5rem 0.9rem;
  padding: 0.7rem 0.85rem;
}

/* Tant que l'évènement n'est pas étendu, tout le rectangle l'étend — le code
   et le nom n'ont pas encore leur rôle habituel (copier, renommer), donc ce
   n'est qu'une fois déplié qu'ils redeviennent cliquables pour eux-mêmes. */
.ac-card-head.is-expandable {
  cursor: pointer;
}

.ac-card-head.is-expandable:hover {
  background: var(--surface);
}

.ac-card-head.is-expandable .ac-code,
.ac-card-head.is-expandable .ac-name {
  cursor: pointer;
}

.ac-code {
  appearance: none;
  padding: 0.25rem 0.55rem;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ball);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.ac-code:hover {
  border-color: var(--ball);
}

/* Le nom est un BOUTON, pas un libellé : c'est ce qui donne accès au renommage,
   et la route existait côté serveur sans qu'aucune interface ne l'appelle. Il ne
   se déguise pas en champ tant qu'on ne le survole pas — trente cadres de saisie
   empilés donneraient l'air d'un formulaire à remplir. */
.ac-name {
  min-width: 0;
  padding: 0.3rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: text;
}

.ac-name:hover {
  border-color: var(--line-2);
  background: var(--surface);
}

.ac-name-edit {
  min-width: 0;
  width: 100%;
  min-height: 36px;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.3);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  font-weight: 600;
}

.ac-name-edit:focus {
  outline: none;
}

.ac-acts {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}

/* ─── Panneau d'un évènement : ses réglages, puis ses liens ────────────────── */
/* Les réglages AVANT les liens : les liens se relèvent une fois et se collent
   dans un message, le thème des pseudos se relit à chaque ouverture du panneau
   pour vérifier ce qui est en service. */
.ac-panel {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 0.9rem 0.85rem;
  border-top: 1px solid var(--line);
}

.ac-setting {
  display: grid;
  grid-template-columns: 12rem minmax(0, 22rem);
  align-items: center;
  gap: 0.4rem 0.9rem;
}

.ac-setting-k {
  color: var(--muted);
  font-size: 0.82rem;
}

.ac-setting-v {
  width: 100%;
}

/* La conséquence du réglage, écrite sous lui : il se pose des semaines avant la
   soirée, par quelqu'un qui ne verra jamais l'écran d'une manette. */
.ac-setting-note {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.45;
}

/* La case du réglage voisin, sur toute la largeur : elle n'a pas d'étiquette à
   gauche — sa phrase EST son étiquette, et une grille à deux colonnes l'aurait
   coupée en deux pour rien. Cible large : on coche ça d'un doigt sur un
   portable, entre deux autres réglages. */
.ac-setting-check {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.15rem;
  padding: 0.35rem 0;
  font-size: 0.88rem;
  cursor: pointer;
}

.ac-setting-check input {
  width: 1rem;
  height: 1rem;
  accent-color: var(--accent);
}

/* ─── Les visuels d'une soirée ──────────────────────────────────────────────
   La vignette est ce qui compte : on vient là pour vérifier qu'on a déposé la
   bonne image, et un nom de fichier ne le dit pas. Le damier derrière elle
   montre la TRANSPARENCE — un PNG mal détouré se voit à son fond blanc, ce qui
   est précisément l'erreur qu'on ne repère qu'en salle sinon. */
/* Repliée par défaut, donc sur une seule colonne : l'en-tête cliquable prend
   toute la largeur, et ce qu'il déplie se pose dessous plutôt qu'à sa droite. */
.ac-setting.is-skins {
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

/* L'en-tête est un BOUTON et doit se voir comme tel.
 *
 * Il était transparent, sans bordure ni fond, son intitulé écrit dans le même
 * gris à 0.82rem que les étiquettes des réglages voisins (« Thème des
 * pseudos »…) et son chevron à 0.7rem dans ce même gris. Autrement dit : la
 * seule chose cliquable du panneau était dessinée exactement comme les choses
 * qui ne le sont pas, et rien ne disait qu'il y avait quelque chose dessous.
 * Qui ne l'avait pas déjà ouvert une fois ne l'ouvrait jamais.
 *
 * Il devient donc une barre — fond, bordure, rayon, hauteur de cible tactile —
 * et son intitulé cesse d'être une étiquette de champ pour devenir un titre. */
.ac-skin-toggle {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: var(--touch);
  padding: 0.4rem 0.5rem 0.4rem 0.75rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.12s ease,
    border-color 0.12s ease;
}

@media (hover: hover) {
  .ac-skin-toggle:hover {
    background: var(--surface-3);
    border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  }
}

/* Déplié, la barre s'accroche à son contenu : elle prend la couleur d'accent et
   perd ses coins bas, pour qu'on lise « ceci ouvre ce qui suit » et pas « deux
   blocs sans rapport ». */
.ac-skin-toggle.is-open {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* Un titre, pas une étiquette : c'est le seul `.ac-setting-k` du panneau qui
   annonce une section repliée plutôt qu'un champ posé à sa droite. */
.ac-skin-toggle .ac-setting-k {
  color: var(--ink);
  font-size: 0.88rem;
  font-weight: 600;
}

/* Le compte pousse le chevron à droite : « 2 sur 4 déposés » se lit sans
   déplier, ce qui est toute la raison d'avoir replié. En pastille : posé nu, il
   se lisait comme la suite de la phrase du titre. */
.ac-skin-sum {
  margin-left: auto;
  padding: 0.12rem 0.5rem;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--muted);
  font-size: 0.78rem;
  white-space: nowrap;
}

/* Le chevron dans une pastille ronde, à la taille d'une vraie affordance : à
   0.7rem et en gris, il passait pour un signe de ponctuation. */
.ac-skin-chev {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--ink);
  font-size: 0.72rem;
  line-height: 1;
  transition: transform 0.15s ease;
}

.ac-skin-toggle.is-open .ac-skin-chev {
  transform: rotate(180deg);
}

/* Le panneau prolonge la barre : même bordure, coins hauts supprimés. Sans ça,
   le contenu déplié flottait sous un en-tête qui ne le revendiquait pas. */
.ac-setting.is-skins .ac-skins {
  margin-top: -0.5rem;
  padding: 0.7rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-top: 0;
  border-bottom-left-radius: var(--r-md);
  border-bottom-right-radius: var(--r-md);
}

.ac-skins {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  min-width: 0;
}

.ac-skin-game-k {
  color: var(--muted);
  font-size: 0.78rem;
}

.ac-skin-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.35rem;
}

.ac-skin {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.1rem 0.6rem;
  padding: 0.45rem 0.6rem 0.45rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.2);
}

/* Ce qui vient de la soirée se distingue de ce qui vient du dépôt : sans ce
   liseré, « déposé » et « pas encore déposé » se ressemblent trop pour qu'on
   sache, la veille au soir, ce qui reste à faire. */
.ac-skin.is-own {
  border-color: rgba(76, 201, 240, 0.45);
}

.ac-skin-img {
  grid-row: 1 / 4;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  background:
    repeating-conic-gradient(rgba(255, 255, 255, 0.14) 0% 25%, transparent 0% 50%) 50% / 12px 12px;
}

/* Rien de déposé et aucun fichier de repli : une pastille creuse à la place de
   la vignette, qui dit « cet emplacement est libre » sans ressembler à une
   image cassée. */
.ac-skin-img.is-missing {
  background: rgba(255, 255, 255, 0.05);
  border: 1px dashed rgba(255, 255, 255, 0.22);
  box-sizing: border-box;
}

.ac-skin-k {
  color: var(--ink);
  font-size: 0.82rem;
}

.ac-skin-state {
  color: var(--muted);
  font-size: 0.74rem;
}

.ac-skin-acts {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.2rem;
}

/* Le champ de fichier est masqué et l'étiquette fait le bouton : le contrôle
   natif affiche « Aucun fichier sélectionné » à côté de lui, texte qu'on ne peut
   ni traduire ni faire taire, et qui mentirait dès le premier dépôt. */
.ac-skin-acts .btn {
  cursor: pointer;
}

/* ─── Les diapos de la soirée ──────────────────────────────────────────────── */

/* Une carte par diapo, plus large que celles des visuels : c'est une image de
   16:9 qu'on reconnaît, pas une pastille de bille qu'on identifie au libellé. */
.ac-diapo-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.35rem;
}

.ac-diapo {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  width: 9.5rem;
  padding: 0.45rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.2);
}

/* `contain` sur fond noir : la vignette de l'administration montre EXACTEMENT
   ce que la salle verra, bandes comprises. C'est le seul endroit où l'on peut
   encore corriger un mauvais cadrage. */
.ac-diapo-img {
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 3px;
  object-fit: contain;
  background: #000;
}

/* Le numéro d'ordre, en gros et en coin : c'est celui du bouton de la console,
   et c'est la seule chose que l'on vient vérifier ici une fois les images
   déposées. */
.ac-diapo-n {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
  min-width: 1.2rem;
  padding: 0 0.3rem;
  border-radius: 3px;
  background: rgb(0 0 0 / 0.65);
  color: #fff;
  font-size: 0.78rem;
  text-align: center;
}

.ac-diapo-add {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.ac-diapo-add .btn {
  cursor: pointer;
}

/* ─── Les sons de la soirée ────────────────────────────────────────────────── */
/* Une ligne par son, pas une carte : il n'y a pas de vignette à montrer, et le
   nom — souvent plus long qu'un numéro de diapo — a besoin de toute la largeur
   disponible plutôt que d'une carte de 9.5rem qui le couperait. */
.ac-sound-row {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.35rem;
}

.ac-sound {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.2);
}

.ac-sound-k {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--ink);
  font-size: 0.82rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ac-sound-add {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.ac-sound-add input[type="text"] {
  flex: 1 1 14rem;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.2);
  color: var(--ink);
  font: inherit;
  font-size: 0.82rem;
}

.ac-sound-add .btn {
  cursor: pointer;
}

.ac-links-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1rem;
}

.ac-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
}

.ac-link {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.6rem;
}

.ac-link-k {
  color: var(--muted);
  font-size: 0.82rem;
}

/* L'URL ne se coupe PAS en plusieurs lignes : on la relit pour vérifier qu'on a
   copié la bonne, et une adresse repliée sur trois lignes se compare mal. Elle
   défile plutôt, dans sa propre boîte. */
.ac-link-v {
  min-width: 0;
  padding: 0.35rem 0.55rem;
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.3);
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.82rem;
  white-space: nowrap;
  overflow-x: auto;
  text-decoration: none;
}

.ac-link-v:hover,
.ac-link-v:focus-visible {
  background: rgba(0, 0, 0, 0.45);
  color: var(--accent);
  text-decoration: underline;
}

/* Bouton icône : carré, ton discret, il ne doit pas peser plus que l'adresse
   qu'il accompagne. Il reprend son contraste au survol. */
.ac-copy {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.ac-copy:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.ac-qr {
  width: 9.5rem;
  height: 9.5rem;
  padding: 0.35rem;
  border-radius: var(--r-sm);
  background: #fff;
}

.ac-qr-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  color: var(--muted);
  font-size: 0.78rem;
}

.ac-empty {
  padding: 2.5rem 1rem;
  border: 1px dashed var(--line);
  border-radius: var(--r-md);
  color: var(--muted);
  text-align: center;
}

/* ─── Connexion ────────────────────────────────────────────────────────────── */
.ac-login {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.4rem;
  padding: 2rem 1.2rem;
}

.ac-login form {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  width: min(22rem, 100%);
}

/* Le titre passe APRES la signature, et donc au second rang : c'est le logo et
   le nom qui disent ou l'on est, « Administration » ne dit plus que ce qu'on y
   fait. Il garde la balise `h1` — la hierarchie du document ne suit pas la
   taille des caracteres. */
.ac-login h1 {
  margin: 0;
  font-size: clamp(1rem, 3.6vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* La signature se colle a son titre : les deux forment un seul bloc au-dessus
   du formulaire, sinon le `gap` de 1.4rem les detache l'un de l'autre autant
   que du champ. */
.ac-login .brand {
  margin-bottom: -0.6rem;
}

.ac-login-note {
  margin: 0;
  max-width: 24rem;
  color: var(--danger);
  font-size: 0.9rem;
  text-align: center;
}

/* Sous 40 rem, la carte cesse d'être une rangée : le code et l'état prennent la
   première ligne, le nom la deuxième, les actions la troisième. Chaque zone
   garde alors sa largeur utile au lieu d'être comprimée à l'ellipse. */
@media (max-width: 40rem) {
  .ac-card-head {
    grid-template-columns: auto 1fr;
  }

  .ac-name {
    grid-column: 1 / -1;
    white-space: normal;
  }

  .ac-acts {
    grid-column: 1 / -1;
  }

  .ac-links-wrap {
    grid-template-columns: minmax(0, 1fr);
  }

  .ac-setting {
    grid-template-columns: minmax(0, 1fr);
  }

  .ac-link {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .ac-link-k {
    grid-column: 1 / -1;
  }

  .ac-tile.is-lag {
    grid-column: 1 / -1;
  }
}

/* ═══ Console du maître du jeu ═════════════════════════════════════════════ */

/* Trois bandes fixes et une seule zone qui défile. Avant, toute la page
   défilait : le bouton « Lancer une partie » changeait de place selon la scène
   et le nombre d'équipes affichées, et il fallait REGARDER la console pour le
   viser — alors que le maître du jeu a les yeux sur la salle. */
/* La mise en page vit sur `#root` et PAS sur `body` : c'est dans `#root` que
   Preact dessine, et un `display: flex` posé sur le parent du conteneur n'aurait
   eu qu'un seul enfant à disposer — les trois bandes se seraient empilées en
   flux normal, sans hauteur fixe, et la page entière aurait défilé. */
body.mc {
  height: 100dvh;
  overflow: hidden;
}

body.mc > #root {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 0.75rem;
  padding:
    max(0.75rem, env(safe-area-inset-top)) max(0.9rem, env(safe-area-inset-right))
    max(0.75rem, env(safe-area-inset-bottom)) max(0.9rem, env(safe-area-inset-left));
}

.mc-top {
  position: relative;
  flex: 0 0 auto;
  text-align: center;
}

/* L'aide se pose DANS l'angle et hors du flux : la bande du haut a une hauteur
   qui suit déjà la phase et les effectifs, et un bouton en flux l'aurait fait
   respirer d'une scène à l'autre. Écrit « Aide » plutôt qu'un « ? » : il n'est
   pressé qu'une fois par soirée, souvent par quelqu'un qui n'a jamais tenu la
   console, et un point d'interrogation demande de deviner. Assez pâle pour ne
   pas concurrencer la phase, qui est ce que le maître du jeu lit en continu. */
.mc-help {
  position: absolute;
  top: -0.15rem;
  right: -0.2rem;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
}

.mc-help:hover {
  border-color: var(--accent);
  color: var(--ink);
}

/* Symétrique de l'Aide, à l'opposé : le son continue de jouer pendant une
   manche, contrairement aux réglages et aux équipes, et doit donc rester
   atteignable en un geste depuis n'importe quel écran. `aria-pressed` dit si
   la télécommande est déjà ouverte — c'est un bouton qui BASCULE, pas qui
   ouvre seulement. */
.mc-sound {
  left: -0.2rem;
  right: auto;
}

.mc-sound[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--ink);
}

.mc-phase {
  font-size: clamp(1.35rem, 6.5vw, 2.1rem);
  font-weight: 700;
  line-height: 1.15;
}

.mc-phase.is-running {
  color: var(--ball);
}

.mc-phase.is-won {
  color: var(--live);
}

.mc-phase.is-countdown {
  color: var(--accent);
}

/* Le chronomètre est le seul texte de la page qui change vingt fois par
   seconde : en chiffres à chasse fixe, il cesse de danser. */
.mc-status {
  margin: 0.15rem 0 0;
  color: var(--muted);
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
  min-height: 1.4em;
}

.mc-squads {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem;
  margin-top: 0.5rem;
}

.mc-squad {
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--team);
  border-radius: var(--r-sm);
  color: var(--team);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

/* L'effectif en direct, détaché du texte de l'épreuve : une pastille pleine à
   la couleur de l'équipe, lisible d'un coup d'œil quelle que soit la manche. */
.mc-squad-n {
  display: inline-block;
  min-width: 1.4em;
  margin-left: 0.4rem;
  padding: 0 0.3rem;
  border-radius: var(--r-sm);
  background: var(--team);
  color: #111;
  font-weight: 700;
  text-align: center;
}

.mc-squad.is-done {
  background: color-mix(in srgb, var(--team) 25%, transparent);
  font-weight: 700;
}

/* Manettes sans équipe : neutres et discrètes, mais jamais absentes — lancer une
   partie en les oubliant, c'est autant de joueurs qui ne pilotent rien. */
.mc-squad.is-pending {
  border-color: var(--muted);
  color: var(--muted);
}

/* ─── Navigation : les moments, puis l'épreuve ─────────────────────────────── */
/* UN SEUL rang, qui défile à l'horizontale plutôt que de gagner une ligne à
   chaque épreuve installée — l'architecture en plugins est faite pour qu'il y
   en ait davantage, et un second rang était souvent vide (« Aucune épreuve à
   l'écran »), simplement pour garder une hauteur constante. Le défilement fait
   ce travail sans le payer en hauteur. */
.mc-nav {
  flex: 0 0 auto;
}

/* Chaque bouton garde sa largeur de contenu et ne se compresse plus pour tenir
   à quatre de front : le rang défile au lieu de rétrécir les libellés. */
.mc-moments {
  display: flex;
  gap: 0.35rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}

.mc-moment {
  flex: 0 0 auto;
  scroll-snap-align: start;
  min-width: 4.6rem;
  min-height: 3rem;
  padding: 0 0.8rem;
  white-space: nowrap;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: clamp(0.75rem, 3.4vw, 0.95rem);
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s;
}

.mc-moment[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--ink);
  font-weight: 700;
}

/* L'épreuve, dans le même rang que les trois moments et non plus sur une ligne
   à elle : son nom peut être plus long, d'où un `min-width` plus généreux — le
   rang défile de toute façon si ça ne tient pas.

   Elle porte la même peau que les trois autres (`.mc-moment`) parce qu'elle
   fait la même chose : nommer une destination, et s'allumer quand c'est elle
   que la salle voit. */
.mc-game {
  min-width: 8rem;
}

/* Rien à nommer : aucune épreuve n'a encore été montrée, ou aucune n'est
   chargée. Le rang RESTE — la navigation garde une hauteur constante, c'est la
   règle sur laquelle toute cette page est bâtie — mais il ne prétend plus mener
   quelque part. Le trait discontinu dit « emplacement », le plein dit
   « destination ». */
.mc-game:disabled {
  border-style: dashed;
  color: var(--muted);
  opacity: 0.7;
  cursor: default;
}

/* Le rappel de préparation. Discret — il n'est pas une commande — mais jamais
   absent : une préparation ouverte et oubliée dans un onglet serait une surprise
   au prochain « Mettre à l'écran ». C'est aussi le chemin pour y revenir. */
.mc-prepnote {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.3rem 0.6rem;
  border: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 0.75rem;
  text-align: center;
  cursor: pointer;
}

/* ─── Corps : la vignette en haut, les commandes en bas ────────────────────── */
/* La bande qui reste se partage en deux blocs qui ne se disputent rien : ce
   qu'on REGARDE (la vignette) monte, ce qu'on PRESSE descend. L'action
   principale est la dernière chose avant le bord — c'est la zone que le pouce
   atteint sans changer la prise du téléphone.

   Rien d'autre ne descend là. « Composer les équipes » y était, SOUS « Lancer
   une partie » : la cible qu'on visait sans regarder était donc un réglage de
   mise en place. */
.mc-main {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 0.6rem;
}

/* Seul bloc qui défile : la vignette a une taille bornée, mais la prose d'une
   scène sans commande peut être longue sur un petit téléphone. */
.mc-view {
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.mc-controls {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* La phrase de présentation, sous la vignette et jusqu'au lancement. C'est ce
   que le maître du jeu dit à voix haute avant de lancer : elle est donc plus
   lisible que les notes de la page — même corps que la ligne d'état, et en
   italique pour qu'on la reconnaisse comme une CITATION, pas comme un réglage. */
.mc-pitch {
  margin: 0.6rem 0 0;
  padding: 0 0.5rem;
  color: var(--ink);
  font-size: 0.88rem;
  font-style: italic;
  text-align: center;
  text-wrap: balance;
}

/* Ce qui se passe sur cet écran, pour qui ne le sait pas encore. Elle était
   réservée aux scènes SANS commande — donc aux écrans où le maître du jeu était
   le plus démuni — et elle disparaissait dès qu'il y avait quelque chose à
   presser. Elle est maintenant permanente hors partie, et partage sa place avec
   le `pitch` d'une épreuve, qui s'adresse à la salle là où celle-ci s'adresse à
   lui. */
.mc-empty {
  margin: 0.5rem 0 0;
  padding: 0 0.5rem;
  color: var(--muted);
  font-size: 0.85rem;
  text-align: center;
  text-wrap: balance;
}

/* ─── Vignette de l'écran partagé ──────────────────────────────────────────── */
/* Symbolique et jamais le vrai rendu : voir l'en-tête de `Preview` dans
   master.js. Sa hauteur est bornée en `dvh` pour qu'elle cède la place aux
   boutons sur un petit téléphone plutôt que de les pousser dehors. */
.mc-preview {
  width: min(100%, calc(24dvh * 16 / 9));
  margin: 0 auto;
}

.pv {
  display: block;
  width: 100%;
  height: auto;
}

.pv-frame {
  fill: var(--surface);
  stroke: var(--line-2);
  stroke-width: 1.2;
}

/* ─── Le choix de la diapo ─────────────────────────────────────────────────── */

/* Une rangée qui défile horizontalement plutôt qu'une grille qui grandit : la
   vignette au-dessus ne doit jamais être poussée hors de l'écran par le nombre
   de diapos, et la hauteur de cette bande reste la même à deux diapos comme à
   douze. */
.mc-diapos {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  margin-top: 0.5rem;
  padding: 0.1rem;
  scrollbar-width: none;
}

.mc-diapos::-webkit-scrollbar {
  display: none;
}

.mc-diapo {
  position: relative;
  flex: 0 0 auto;
  width: 4.6rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: #000;
  overflow: hidden;
  cursor: pointer;
}

/* La diapo affichée se voit de loin : c'est la seule information que le maître du
   jeu cherche en baissant les yeux sur sa console. */
.mc-diapo[aria-pressed="true"] {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}

/* `contain` ici aussi : la vignette montre les bandes que la salle verra. Une
   miniature rognée mentirait sur le cadrage au moment précis où on le vérifie. */
.mc-diapo-img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain;
}

/* Le numéro, en coin : il ne sert pas à choisir — on choisit sur l'image — mais
   à se dire « le wifi, c'est le trois » avant de monter sur scène. */
.mc-diapo-n {
  position: absolute;
  right: 0.15rem;
  bottom: 0.1rem;
  padding: 0 0.25rem;
  border-radius: 3px;
  background: rgb(0 0 0 / 0.6);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1.4;
}

/* Le bouton de veille : la même vignette que ce que l'écran montre alors — un
   cadre sombre et le logo estompé — pour qu'il se reconnaisse à l'image et non
   au libellé, comme les diapos à côté de lui. */
.mc-diapo.is-idle {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  background: #0b0d12;
}

.mc-diapo-idle {
  width: 45%;
  height: 45%;
  color: var(--ball);
  opacity: 0.4;
}

/* « veille » est un mot, pas un numéro : il déborderait de la pastille des
   chiffres, qui est calibrée pour un caractère. */
.mc-diapo.is-idle .mc-diapo-n {
  right: auto;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.62rem;
  letter-spacing: 0.04em;
}

/* La veille dans la vignette de l'écran partagé : le cadre que la salle voit, et
   le logo au centre — un disque, à cette taille. */
.pv-idle-frame {
  fill: none;
  stroke: var(--ball);
  stroke-opacity: 0.22;
  stroke-width: 0.8;
}

.pv-idle-mark {
  fill: var(--ball);
  fill-opacity: 0.16;
}

/* Le fond de la vignette quand c'est une diapo qui est à l'écran : le même noir
   que l'écran partagé, pour que les bandes se lisent au même endroit. */
.pv-dark {
  fill: #0b0d12;
  stroke: var(--line-2);
  stroke-width: 1;
}

/* Le terrain est en pointillé : c'est une SILHOUETTE, pas le plateau. Un trait
   plein aurait laissé croire à un mur réellement dessiné là. */
.pv-stage {
  fill: none;
  stroke: var(--line-2);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.pv-zone {
  fill: color-mix(in srgb, var(--team) 14%, transparent);
  stroke: var(--team);
  stroke-width: 1;
}

/* ─── Le terrain dessiné par l'épreuve ─────────────────────────────────────── */
/* L'épreuve donne la GÉOMÉTRIE et le rôle de chaque forme ; ces règles-ci
   décident de quoi un mur a l'air. C'est ce partage qui permet à un jeu neuf de
   dessiner son plateau sans emporter une ligne de style avec lui — et à un
   changement de palette de le suivre partout d'un coup. */
.pv-art .pv-wall {
  fill: var(--line-2);
  stroke: none;
}

/* L'arrivée est le seul élément que la salle cherche des yeux : c'est la couleur
   de la bille, la plus chaude de la palette. */
.pv-art .pv-goal {
  fill: var(--ball);
}

.pv-art .pv-start {
  fill: var(--muted);
}

/* Un départ tenu par une équipe prend sa couleur — c'est ce qui rend le plateau
   central lisible d'un coup d'œil : autant de départs que d'équipes. */
.pv-art .pv-start.is-team {
  fill: var(--team);
}

.pv-art .pv-edge {
  fill: none;
  stroke: var(--line-2);
  stroke-width: 1;
}

.pv-art line {
  stroke: var(--line-2);
  stroke-width: 1;
}

.pv-art line.is-team {
  stroke: var(--team);
}

.pv-ball {
  fill: var(--team);
}

.pv-vec {
  stroke: var(--team);
  stroke-width: 1.6;
  stroke-linecap: round;
}

.pv-side > rect {
  fill: var(--surface-2);
  stroke: var(--line);
  stroke-width: 0.8;
}

.pv-qr {
  color: var(--ink);
}

.pv-peers rect {
  fill: var(--surface-2);
  stroke: var(--line-2);
  stroke-width: 0.6;
}

.pv-board rect {
  fill: color-mix(in srgb, var(--team) 55%, transparent);
}

.pv-code {
  fill: var(--ink);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2px;
  text-anchor: middle;
}

.pv-note {
  fill: var(--muted);
  font-size: 6px;
  text-anchor: middle;
}

.pv-rule {
  stroke: var(--line);
  stroke-width: 0.8;
}

.pv-big {
  fill: var(--accent);
  font-size: 26px;
  font-weight: 700;
  text-anchor: middle;
}

.pv-chrono {
  fill: var(--ink);
  font-size: 8px;
  font-variant-numeric: tabular-nums;
  text-anchor: middle;
}

/* La légende nomme les panneaux ouverts. Une pastille de trois unités se devine
   mal sous l'éclairage d'une salle, et le maître du jeu ne doit jamais plisser
   les yeux pour savoir si le QR est affiché. */
.mc-preview-cap {
  margin-top: 0.3rem;
  color: var(--muted);
  font-size: 0.72rem;
  text-align: center;
}

.mc-btn {
  width: 100%;
  min-height: 4rem;
  font-size: clamp(1rem, 4.2vw, 1.25rem);
  border-radius: var(--r-lg);
}

/* L'action principale est la plus haute de la page. La hiérarchie ne tient pas
   à la couleur seule : sous un vidéoprojecteur, ou pour un daltonien, c'est la
   TAILLE qui dit lequel des boutons est celui qu'on cherche. */
.mc-btn.is-primary {
  min-height: 5.5rem;
  font-size: clamp(1.15rem, 5vw, 1.5rem);
}

.mc-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 0.5rem;
}

.mc-row .mc-btn {
  min-height: 3.4rem;
  font-size: 1rem;
}

/* ─── Ouvertures de réglage ────────────────────────────────────────────────── */
/* Un bouton discret, entre la vignette et les commandes de partie : il se
   presse en REGARDANT la console, pas en regardant la salle, et n'a donc rien
   à faire dans la zone du pouce. Plus bas et plus gros, il entrerait en
   concurrence avec « Lancer une partie ».

   Réglages et équipes n'y font plus qu'un (deux onglets d'une même feuille,
   voir `.sheet-tabs`) ; le son a migré dans l'en-tête, seul des trois à
   continuer de jouer pendant une manche. */
.mc-util {
  display: flex;
}

.mc-utilbtn {
  flex: 1 1 auto;
  min-height: 2.9rem;
  padding: 0 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}

/* ─── Bascules (feuille des réglages) ──────────────────────────────────────── */
/* Même dessin pour les options de l'épreuve et pour les panneaux de l'écran,
   parce que c'est le même geste — un appui qui change un état, pas une commande.
   Ce qui les distingue est leur SECTION, `sheet-sub` : sur l'ancienne console
   elles se ressemblaient sans rien pour les séparer, et « Taille » se cherchait
   parmi les panneaux. */
.mc-toggle {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  min-height: 3.4rem;
  padding: 0.35rem 0.2rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.78rem;
  line-height: 1.2;
  cursor: pointer;
}

/* La précision se lit après le titre, jamais à sa place : elle reste plus
   petite et plus pâle même quand le panneau est allumé. */
.mc-toggle-hint {
  font-size: 0.62rem;
  line-height: 1.15;
  color: var(--muted);
  font-weight: 400;
  text-wrap: balance;
}

.mc-toggle[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--ink);
  font-weight: 700;
}

/* Grisée et NON cachée pendant la partie : le serveur refuse déjà de changer un
   plateau en cours de course, et une section qui disparaît se cherche ensuite.
   La feuille explique pourquoi juste en dessous. */
.mc-toggle:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.mc-foot {
  flex: 0 0 auto;
  margin: 0;
  color: var(--muted);
  font-size: 0.8rem;
  text-align: center;
}

/* La liaison coupée n'est pas une note parmi d'autres : tant qu'elle dure,
   AUCUN bouton de la page n'a d'effet, et le maître du jeu doit l'apprendre de
   la console plutôt qu'en constatant que la salle ne réagit pas. */
.mc-foot.is-down {
  color: var(--danger);
  font-weight: 600;
}

/* ─── Feuille modale (équipes) ─────────────────────────────────────────────── */
/* Une feuille qui monte du bas, pas un bloc inséré dans le flux : l'ancien
   panneau poussait les boutons de partie hors de l'écran en s'ouvrant, et les
   ramenait ailleurs en se fermant. */
.sheet {
  position: relative;
  width: 100%;
  max-width: 34rem;
  max-height: 88dvh;
  overflow-y: auto;
  margin: auto auto 0;
  padding: 1.1rem 1.1rem max(1.1rem, env(safe-area-inset-bottom));
  border: 1px solid var(--line-2);
  border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: #1a1f29;
  color: var(--ink);
  font-family: inherit;
}

.sheet::backdrop {
  background: rgba(8, 10, 14, 0.72);
}

.sheet-close {
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sheet-title {
  margin: 0 0 0.2rem;
  font-size: 1.1rem;
  font-weight: 700;
}

.sheet-lead {
  margin: 0 0 1rem;
  color: var(--muted);
  font-size: 0.85rem;
}

/* Deux onglets pour la feuille des réglages, à la place de deux boutons
   distincts dans la zone des commandes : ce que règle l'épreuve et ce que
   règle la soirée (les équipes) ne se pressent pas au même moment, mais
   partagent le même bouton d'entrée. */
.sheet-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  margin: 0 0 0.9rem;
}

.sheet-tab {
  min-height: 2.6rem;
  padding: 0 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.sheet-tab[aria-selected="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--ink);
  font-weight: 700;
}

/* Les sections de la feuille des réglages. C'est la seule chose qui sépare un
   réglage d'ÉPREUVE (la taille du plateau) d'un panneau d'ÉCRAN (le QR) : ils
   portent la même bascule, mais ne se touchent pas au même moment de la
   soirée. */
.sheet-sub {
  margin: 1rem 0 0.5rem;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.sheet-opts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: 0.4rem;
}

/* La liste des épreuves : pleine largeur, une par ligne. Un nom d'épreuve peut
   être long, et une soirée en compte assez peu pour qu'on les lise toutes d'un
   coup d'œil — c'est ce qui permet à la navigation de garder une hauteur fixe
   quand un jeu de plus est installé. */
.sheet-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

.sheet-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  min-height: 3.4rem;
  padding: 0 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.sheet-item[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  font-weight: 700;
}

/* Une épreuve dont le module de console n'a pas pu être chargé reste dans la
   liste — le serveur, lui, sait y jouer — mais elle le dit : sans ce mot, ses
   boutons manquants passeraient pour une panne de la console. */
.sheet-item-warn {
  flex: 0 0 auto;
  color: var(--danger);
  font-size: 0.7rem;
}

/* ─── Feuille de préparation ───────────────────────────────────────────────── */
/* Deux temps dans une seule feuille : la liste, puis les réglages de l'épreuve
   choisie. Le vocabulaire réutilise les primitives déjà là — `.sheet-*` pour la
   feuille, `.mc-toggle` pour un choix, `.pv-*` pour le dessin — et n'ajoute que
   ce que le parcours a de propre : la carte d'épreuve et la vignette du plateau
   PRÉPARÉ, celle qui ne montre pas l'écran en cours. */

.prep-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

/* Une carte par épreuve : sa vignette à gauche, son nom et sa phrase à droite.
   La vignette n'est pas un ornement — sans elle, choisir une épreuve revient à
   lire trois noms, et c'est exactement ce qui faisait mettre à l'écran un
   plateau qu'on n'avait pas vu. */
.prep-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.prep-card[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.prep-card .prep-board {
  flex: 0 0 auto;
  width: 6.4rem;
}

.prep-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.prep-card-name {
  font-size: 1rem;
  font-weight: 700;
}

.prep-card-pitch {
  color: var(--muted);
  font-size: 0.76rem;
  line-height: 1.25;
}

/* Le second temps. L'en-tête doit dire SANS AMBIGUÏTÉ qu'on regarde une
   préparation et pas l'écran en cours : le retour nommé « ‹ Épreuves » à gauche
   du titre est ce qui l'ancre. */
.prep-head {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
}

.prep-head .sheet-title {
  flex: 1 1 auto;
  text-align: right;
}

.prep-back {
  flex: 0 0 auto;
  padding: 0.2rem 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.prep-pitch {
  margin: 0.3rem 0 0.8rem;
  color: var(--ink);
  font-size: 0.88rem;
  font-style: italic;
  text-wrap: balance;
}

/* La vignette du plateau préparé — ce que la salle VERRA. Bordée comme le reste
   de la feuille, et pas comme la vignette de la console : là-haut c'est l'écran
   partagé, ici c'est une proposition. */
.prep-board {
  display: block;
  width: 100%;
  border-radius: var(--r-sm);
}

.prep-shuffle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin: 1rem 0 1.1rem;
}

/* La graine se lit à voix haute : c'est elle que la salle demandera d'une soirée
   à l'autre, et elle doit être celle de la VIGNETTE — pas une neuve tirée à la
   validation. */
.prep-seed {
  color: var(--muted);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.sheet-rows {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.sheet-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

/* La pastille est le seul repère de couleur : le nom, lui, est libre. C'est
   aussi l'interrupteur de la ligne, d'où une cible tactile pleine hauteur
   autour d'un disque qui, lui, reste petit. */
.sheet-dot {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--touch);
  height: var(--touch);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.sheet-dot::before {
  content: "";
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: var(--team);
}

/* Équipe éteinte : le cercle se vide, pour qu'on lise l'état sans relire le champ. */
.sheet-dot[aria-pressed="false"]::before {
  background: none;
  box-shadow: inset 0 0 0 2px var(--team);
  opacity: 0.5;
}

.sheet-row .field {
  flex: 1 1 auto;
}

.sheet-row .field:focus {
  border-color: var(--team);
}

.sheet-check {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: var(--touch);
  margin-top: 0.9rem;
  cursor: pointer;
}

.sheet-check input {
  width: 1.4rem;
  height: 1.4rem;
  accent-color: var(--accent);
}

.sheet-hint {
  margin: 0.2rem 0 1.1rem;
  color: var(--muted);
  font-size: 0.85rem;
  min-height: 2.4em;
}

/* Le volume, dans la feuille des sons : une cible tactile pleine largeur, à la
   hauteur d'une bascule plutôt qu'au trait fin par défaut du navigateur. */
.sheet input[type="range"] {
  width: 100%;
  height: var(--touch);
  accent-color: var(--accent);
}

.sheet-foot {
  display: flex;
  gap: 0.6rem;
}

.sheet-foot .btn {
  flex: 1 1 0;
  min-height: 3.4rem;
}

/* Sur un écran large — un maître du jeu qui pilote depuis un portable — la
   console cesse de s'étirer : des boutons de soixante centimètres de large ne
   se visent pas mieux, ils se lisent juste moins bien. */
@media (min-width: 34rem) {
  body.mc > #root {
    max-width: 30rem;
    margin: 0 auto;
  }
}

/* ─── Qui est connecté ──────────────────────────────────────────────────────
   Dans la barre, entre le titre et les boutons. Sans ce nom, un utilisateur qui
   ne retrouve pas un évènement n'a aucun moyen de deviner qu'il est entré avec
   le mauvais compte — et la console est rigoureusement la même pour tous. */
.ac-me {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--muted);
  font-size: 0.85rem;
}

.ac-me-tag {
  padding: 0.1rem 0.4rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--ball) 18%, transparent);
  color: var(--ball);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Le propriétaire d'un évènement, sur sa carte. Affiché au super administrateur
   seulement, et seulement pour les évènements qui ne sont pas les siens :
   l'absence de marque est déjà l'information. */
.ac-owner {
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--muted);
  font-size: 0.72rem;
  white-space: nowrap;
}

/* ─── Les comptes ───────────────────────────────────────────────────────────
   Replié par défaut : on crée un compte deux fois par an, et ce panneau est
   au-dessus de la liste, qui est ce qu'on vient voir chaque fois. Le nombre de
   comptes reste lisible sans déplier. */
.ac-users {
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}

/* Même dessin que le panneau des visuels : ces deux sections sont les seules de
   l'administration qui se replient, et elles partagent leur en-tête
   (`.ac-skin-toggle`) — il serait incohérent qu'elles n'ouvrent pas de la même
   façon. */
.ac-users-body {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 0.8rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-top: 0;
  border-bottom-left-radius: var(--r-md);
  border-bottom-right-radius: var(--r-md);
}

.ac-user-new {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.ac-user-new .field {
  flex: 1 1 10rem;
  min-width: 0;
}

.ac-user-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Une ligne par compte : l'identifiant, ce qu'il tient, et ses deux actions.
   Le nombre d'évènements est là pour une seule raison — c'est ce qui se déplace
   quand on supprime le compte, et ça doit se lire avant de cliquer. */
.ac-user {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.8rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}

.ac-user-k {
  font-weight: 600;
}

.ac-user-n {
  color: var(--muted);
  font-size: 0.78rem;
}

.ac-user-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

/* Ce que la suppression déplace, écrit à côté du bouton rouge et pas dans une
   fenêtre : elle ne détruit rien — les évènements survivent — mais elle ne doit
   pas partir sur un clic malheureux dans une liste. */
.ac-user-warn {
  color: var(--muted);
  font-size: 0.78rem;
}

.field.is-small {
  padding: 0.3rem 0.5rem;
  font-size: 0.85rem;
}

/* ─── Feuille des antisèches ──────────────────────────────────────────────── */

/* La phrase-pivot : le contresens que toute la soirée essaie de lever tient
   là-dedans, et elle ne dépend d'aucune version du pitch. Encadrée pour qu'un
   pouce qui fait défiler la feuille la retrouve sans lire. */
.mc-pivot {
  margin: 0.2rem 0 0.9rem;
  padding: 0.7rem 0.8rem;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--ink);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  text-wrap: balance;
}

/* Le seul bloc de la console écrit pour être LU À VOIX HAUTE : debout, à bout
   de bras, dans une salle mal éclairée. D'où le corps plus gros que partout
   ailleurs et l'interligne large — on y reprend sa ligne après avoir regardé la
   salle, et une antisèche où l'on perd sa ligne ne sert à rien. */
.mc-say {
  margin: 0.7rem 0 0.5rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--line-2);
}

.mc-say p {
  margin: 0 0 0.7rem;
  font-size: 1.02rem;
  line-height: 1.5;
  text-wrap: pretty;
}

.mc-say p:last-child {
  margin-bottom: 0;
}

/* Ce qu'il faut appuyer en le disant. La couleur suffit : en gras SEUL, la
   marque se perdait dans un bloc déjà dense. */
.mc-say strong {
  color: var(--accent);
}

/* La démo : ce qu'on ANNONCE d'un côté, ce que la salle VOIT de l'autre. Les
   deux ne se confondent pas — le premier se lit à voix haute, le second se
   regarde. */
.mc-steps,
.mc-tips {
  margin: 0.5rem 0 0;
  padding-left: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.mc-tips {
  list-style: none;
  padding-left: 0;
}

.mc-steps li,
.mc-tips li {
  font-size: 0.9rem;
  line-height: 1.35;
}

.mc-steps b,
.mc-tips b {
  display: block;
  color: var(--ink);
}

.mc-steps span,
.mc-tips span {
  display: block;
  margin-top: 0.15rem;
  color: var(--muted);
  font-size: 0.82rem;
}

/* Les formulations à éviter portent la couleur du danger sur le MOT, pas sur
   l'explication : c'est le mot qu'il ne faut pas prononcer. */
.mc-tips.is-avoid b {
  color: var(--danger);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
