/* ══════════════════════════════════════════════════════════════════════════
   La Taverne · la coquille (accueil, application, feuilles, île)
   --------------------------------------------------------------------------
   Direction : « la table de taverne », épurée puis ALLÉGÉE (octobre 2026).
   Le caractère vient des OBJETS (le bois de la table, le cuir du gobelet,
   les dés, les portraits gravés) et du logo ; l'interface parle la langue
   d'une app d'aujourd'hui : Inter Tight en gras tracé serré pour les titres,
   des surfaces pleines sur un fond uni, aucun cadre en filet ni pointillé. Les menus suivent le thème
   (clair = papier crème, sombre = la taverne la nuit) ; la scène de jeu,
   elle, est TOUJOURS sombre (une table à la chandelle) et vit dans
   jeu.css.

   Cinq règles qui expliquent le reste :
   1. une seule couleur d'accent, le cuivre, réservée à peu de choses :
      l'encoche de l'onglet courant, le focus, l'action principale, la
      table qu'on doit affronter ;
   2. aucune profondeur molle : un FOND uni, des SURFACES pleines posées
      dessus (une carte se distingue du fond par sa teinte, pas par un
      cadre), des filets d'un pixel seulement ENTRE les lignes d'une liste.
      Les seules ombres sont celles des OBJETS posés (la table, un dé) et
      des couches de verre ;
   3. deux rôles typographiques : Inter Tight pour toute l'interface, titres
      compris (700, tracé serré), JetBrains Mono pour les chiffres
      (tabulaires). IM Fell English n'est plus un rôle de l'interface : elle
      ne vit plus que dans la scène de jeu et l'image de partage, où elle
      garde l'atmosphère de la taverne (les jetons `--tv-titre*` restent
      pour elles) ;
   4. des rayons généreux pour les surfaces (16 à 24 px), les pastilles et la
      capsule de la barre d'onglets ronds ;
   5. UN seul bloc sombre (`:root[data-theme="dark"]`, posé avant le premier
      rendu par theme-init.js) et UNE règle de mouvement
      (`:root[data-anim="off"] *`) : aucune media query de thème ni de
      mouvement ne double ces deux sources.

   Plan : 1 jetons · 2 socle · 3 composants · 4 accueil · 5 coquille ·
          6 les vues · 7 feuilles · 8 île et scène · 9 grands écrans ·
          10 mouvement · 11 survol (en fin de fichier, `hover: none` en dernier)
   ══════════════════════════════════════════════════════════════════════════ */


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 1 · JETONS
   │ Contrastes MESURÉS (tests/test_taverne_coquille.py les recalcule) : toute
   │ encre de texte tient 4,5:1 sur le fond, la surface et la surface 2 ;
   │ tout tracé d'accent tient 3:1. Les lots de la table, de la partie et des
   │ effets lisent ces jetons ; un jeton qu'ils ajoutent vit dans leur feuille.
   └────────────────────────────────────────────────────────────────────────── */

:root {
  /* Le papier crème (clair) */
  --tv-bg: #f6f3ed;
  --tv-surface: #fffefb;
  --tv-surface-2: #ece6da;
  --tv-ink: #1f1912;
  --tv-ink-2: #4b4136;
  --tv-ink-3: #6b5f50;
  --tv-line: rgba(31, 25, 18, .09);
  --tv-line-2: rgba(31, 25, 18, .26);
  /* Le bord d'un champ ou d'un interrupteur : un composant qu'on doit
     REPÉRER tient 3:1 (WCAG 1.4.11), là où un filet de séparation n'en a
     pas besoin. */
  --tv-line-3: rgba(31, 25, 18, .52);

  /* Le cuivre. Trois rôles : le tracé (3:1, jamais du texte), le texte
     (4,5:1), l'aplat qui porte des lettres (et l'encre de ces lettres). */
  --tv-accent: #b4652a;
  --tv-accent-texte: #8c4615;
  --tv-accent-plein: #8c4615;
  --tv-on-accent: #fbf6ea;
  --tv-accent-doux: #f0e0ca;
  --tv-or: #b8892e;

  /* Couleurs de sens : le tracé, et la version qui porte du texte. */
  --tv-vert: #2f7d55;
  --tv-vert-texte: #22603f;
  --tv-rouge: #b3341f;
  --tv-rouge-texte: #9a2a18;
  /* Les lavis de sens : le fond d'une étiquette (la couleur de sens à peine
     teintée), sans filet. */
  --tv-vert-doux: rgba(47, 125, 85, .13);
  --tv-rouge-doux: rgba(179, 52, 31, .11);

  --tv-voile: rgba(246, 243, 237, .86);
  --tv-voile-fort: rgba(18, 14, 10, .5);

  /* Les champs remplis et le contrôle segmenté de l'accueil (style iOS) :
     le fond du champ, son filet, la piste et le pouce du segment. */
  --tv-champ: #f2ece1;
  --tv-champ-bord: rgba(31, 25, 18, .5);
  --tv-seg-fond: #ece5d7;
  --tv-seg-pouce: #fffdf9;
  --tv-seg-bord: rgba(31, 25, 18, .12);

  /* La scène et les objets : identiques dans les deux thèmes (une table à
     la chandelle reste une table à la chandelle). */
  --tv-scene-bg: #120d09;
  --tv-scene-ink: #f3e6cf;
  --tv-scene-ink-2: #cdb995;
  --tv-bois-1: #3d2717;
  --tv-bois-2: #2b1a0f;
  --tv-bois-3: #4c301c;
  --tv-chandelle: rgba(255, 176, 82, .20);
  --tv-parchemin: #eadcc0;
  --tv-parchemin-ink: #2b2016;
  --tv-parchemin-ink-2: #5a4835;
  --tv-selection: #e8b75c;
  --tv-scene-accent: #e8a35b;

  /* Les huit teintes héraldiques des blasons (index `teinte` de l'API) et
     l'émail des emblèmes posés dessus (3:1 au moins sur chacune). */
  --tv-teinte-0: #9b2c20;   /* gueules */
  --tv-teinte-1: #2c4f8c;   /* azur */
  --tv-teinte-2: #2f6b3f;   /* sinople */
  --tv-teinte-3: #2a2420;   /* sable */
  --tv-teinte-4: #6a2d5c;   /* pourpre */
  --tv-teinte-5: #a87a24;   /* or */
  --tv-teinte-6: #6d737b;   /* argent */
  --tv-teinte-7: #9a5520;   /* tanné */
  --tv-embleme: #fbf6ea;

  /* Le verre (barre d'onglets, barre du haut au défilement, lentille de
     verre.js). Assez couvrant pour que l'encre seconde tienne 4,5:1 quoi
     qu'il passe dessous (calculé au pire : du noir sous le verre clair, du
     blanc sous le verre sombre). Le flou ne fait qu'adoucir ce pire cas. */
  --tv-verre-fond: rgba(251, 248, 241, .76);
  --tv-verre-speculaire: rgba(255, 255, 255, .6);
  --tv-verre-lisere: rgba(255, 255, 255, .92);
  --tv-verre-bord: rgba(31, 25, 18, .1);
  --tv-verre-rim: rgba(255, 255, 255, .9);
  --tv-verre-rim-bas: rgba(255, 255, 255, .42);
  --tv-verre-ombre: 0 12px 28px -12px rgba(31, 22, 12, .24), 0 2px 8px -3px rgba(31, 22, 12, .1);
  --tv-lentille-fond: rgba(240, 224, 202, .9);
  --tv-lentille-lisere: rgba(255, 255, 255, 1);
  --tv-lentille-bord: rgba(31, 25, 18, .08);
  --tv-lentille-ombre: 0 1px 1px rgba(31, 25, 18, .06), 0 8px 18px -8px rgba(31, 25, 18, .28);
  --tv-lentille-reflet: rgba(255, 255, 255, .72);

  /* L'ombre d'un objet posé sur le papier. */
  --tv-ombre-objet: 0 1px 2px rgba(40, 24, 10, .22), 0 18px 34px -20px rgba(40, 24, 10, .55);
  /* Celle de la table de l'accueil : courte, de contact. Elle s'arrête
     avant le logo (20 px sous le bois, l'écart en fait 26) : l'encre qui
     découvre le logo à l'arrivée est un calque de la couleur du fond, et
     posé sur une ombre il se verrait en rectangle clair. */
  --tv-ombre-table: 0 1px 2px rgba(40, 24, 10, .2), 0 12px 22px -14px rgba(40, 24, 10, .42);

  --tv-titre: 'IM Fell English', 'Petrona', Georgia, serif;
  --tv-titre-sc: 'IM Fell English SC', 'IM Fell English', Georgia, serif;
  --tv-ui: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --tv-mono: 'JetBrains Mono', ui-monospace, monospace;

  --tv-rayon-s: 6px;
  --tv-rayon-m: 10px;
  --tv-rayon-l: 14px;

  --tv-dur-xs: 140ms;
  --tv-dur-s: 240ms;
  --tv-dur-m: 420ms;
  --tv-dur-l: 700ms;
  --tv-ease-out: cubic-bezier(.2, .7, .2, 1);
  --tv-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --tv-ressort: cubic-bezier(.3, 1.42, .5, 1);

  /* Les zones sûres, à portée des autres feuilles (la scène, la table). */
  --tv-zone-haut: env(safe-area-inset-top, 0px);
  --tv-zone-bas: env(safe-area-inset-bottom, 0px);
  --tv-zone-gauche: env(safe-area-inset-left, 0px);
  --tv-zone-droite: env(safe-area-inset-right, 0px);

  /* La largeur de la colonne de navigation (0 sur téléphone). */
  --tv-nav: 0px;
  --tv-haut-h: 52px;

  color-scheme: light;
}

/* ── Le SEUL bloc sombre du fichier : la taverne la nuit ──────────────── */
:root[data-theme="dark"] {
  --tv-bg: #13100c;
  --tv-surface: #1c1813;
  --tv-surface-2: #26201a;
  --tv-ink: #f2e9da;
  --tv-ink-2: #cfc3b0;
  --tv-ink-3: #a89a85;
  --tv-line: rgba(242, 233, 218, .10);
  --tv-line-2: rgba(242, 233, 218, .20);
  --tv-line-3: rgba(242, 233, 218, .42);

  --tv-accent: #df9a55;
  --tv-accent-texte: #e8ac6c;
  --tv-accent-plein: #df9a55;
  --tv-on-accent: #1a120a;
  --tv-accent-doux: #2e2216;
  --tv-or: #d9b062;

  --tv-vert: #5cbf8a;
  --tv-vert-texte: #7fd3a6;
  --tv-rouge: #e06a52;
  --tv-rouge-texte: #f08a74;
  --tv-vert-doux: rgba(92, 191, 138, .16);
  --tv-rouge-doux: rgba(224, 106, 82, .16);

  --tv-voile: rgba(19, 16, 12, .86);
  --tv-voile-fort: rgba(0, 0, 0, .6);

  --tv-champ: #26201a;
  --tv-champ-bord: rgba(242, 233, 218, .42);
  --tv-seg-fond: #14110d;
  --tv-seg-pouce: #2f2820;
  --tv-seg-bord: rgba(242, 233, 218, .14);

  --tv-verre-fond: rgba(28, 24, 19, .8);
  --tv-verre-speculaire: rgba(255, 240, 220, .07);
  --tv-verre-lisere: rgba(255, 240, 220, .14);
  --tv-verre-bord: rgba(255, 240, 220, .09);
  --tv-verre-rim: rgba(255, 240, 220, .3);
  --tv-verre-rim-bas: rgba(255, 240, 220, .09);
  --tv-verre-ombre: 0 14px 30px -12px rgba(0, 0, 0, .66), 0 2px 8px -3px rgba(0, 0, 0, .4);
  /* En sombre, la lentille ASSOMBRIT le verre : elle porte une icône de
     cuivre clair, qu'un voile blanc ramènerait sous 3:1. */
  --tv-lentille-fond: rgba(46, 34, 22, .82);
  --tv-lentille-lisere: rgba(255, 240, 220, .22);
  --tv-lentille-bord: rgba(255, 240, 220, .14);
  --tv-lentille-ombre: 0 1px 1px rgba(0, 0, 0, .3), 0 8px 18px -8px rgba(0, 0, 0, .7);
  --tv-lentille-reflet: rgba(255, 240, 220, .08);

  --tv-ombre-objet: 0 1px 2px rgba(0, 0, 0, .55), 0 22px 40px -18px rgba(0, 0, 0, .85);
  --tv-ombre-table: 0 1px 2px rgba(0, 0, 0, .5), 0 12px 22px -14px rgba(0, 0, 0, .8);

  color-scheme: dark;
}

/* ┌──────────────────────────────────────────────────────────────────────────
   │ 2 · SOCLE
   └────────────────────────────────────────────────────────────────────────── */

*,
*::before,
*::after { box-sizing: border-box; }

/* `[hidden]` doit gagner sur TOUT `display` posé par une classe (un bouton en
   inline-flex, une grille). C'est la règle qui crée le piège qui doit le
   refermer : une seule fois, ici, pour toute la feuille. */
[hidden] { display: none !important; }

/* Le rectangle gris qu'iOS pose sur l'élément touché est la signature d'une
   page web : chaque bouton a son propre retour à l'appui (`:active`). */
html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  background: var(--tv-bg);
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--tv-bg);
  color: var(--tv-ink);
  font: 400 15px/1.5 var(--tv-ui);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
}

/* Une feuille ouverte, ou la table de jeu : la page derrière ne défile plus,
   et la pastille « Admin » du Portfolio (z-index maximal, en bas à gauche,
   PILE sur un pied de feuille au téléphone) s'efface le temps de la couche.
   Les deux marqueurs sont posés par UN SEUL chemin côté JS. */
body.has-modal,
body.en-scene { overflow: hidden; }
body.has-modal #mn-admin-pill,
body.en-scene #mn-admin-pill { display: none; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--tv-ui);
  font-weight: 700;
  font-synthesis: none;
  letter-spacing: -.02em;
  line-height: 1.15;
}
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font-family: inherit; }
a { color: inherit; }
img, svg { display: block; }
fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; }

:focus-visible { outline: 2px solid var(--tv-accent); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }
/* Un titre de vue reçoit le focus par programme (lecteur d'écran) : pas
   d'anneau, ce n'est pas une commande. */
.vue-titre:focus,
.acc-titre:focus { outline: none; }

::selection { background: var(--tv-accent-doux); color: var(--tv-ink); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.icon-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Les chiffres : chasse fixe partout où il y a un nombre. */
.mono,
.sec-compte,
.ligne-fin,
.combo-pts,
.code-ami-code,
.rang,
.stats dd,
.proba-pct,
.table-objectif,
.seg-chiffres .seg-btn {
  font-family: var(--tv-mono);
  font-variant-numeric: tabular-nums;
}

/* Sans JavaScript (le <noscript> du haut de page). */
.sans-js {
  display: grid;
  gap: 14px;
  max-width: 640px;
  margin: 0 auto;
  padding: max(28px, env(safe-area-inset-top)) 20px 32px;
}
.sans-js-titre { font: 700 32px/1.1 var(--tv-ui); letter-spacing: -.02em; }


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 3 · COMPOSANTS
   └────────────────────────────────────────────────────────────────────────── */

/* ── Icônes : le trait vit ICI, pas dans les symboles ─────────────────── */
.ico {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.marque-logo {
  display: block;
  flex: none;
  height: 28px;
  aspect-ratio: 925 / 256;
  background: url("brand/logo.png") left center / contain no-repeat;
}
:root[data-theme="dark"] .marque-logo { background-image: url("brand/logo-dark.png"); }
.marque-logo[hidden] { display: none; }
/* Le logo (ci-dessus) : le gobelet, les dés et le nom, dessinés. Un
   `<span role="img">` VIDE nommé par son `aria-label` ; la variante sombre
   ne change que l'image de fond (même taille, 925 × 256). Dans la barre de
   l'app, il porte aussi la classe du mot-symbole (scene.js l'encre). */

/* ── Boutons ──────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--tv-rayon-l);
  background: var(--tv-surface-2);
  color: var(--tv-ink);
  font: 600 15px/1.2 var(--tv-ui);
  letter-spacing: -.005em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform var(--tv-dur-xs) var(--tv-ease-out),
              background-color var(--tv-dur-xs) var(--tv-ease-out),
              border-color var(--tv-dur-xs) var(--tv-ease-out);
}
.btn .ico { width: 18px; height: 18px; }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .55; cursor: default; transform: none; }

/* L'action principale : un aplat de cuivre (le SEUL aplat d'accent). */
.btn-principal {
  background: var(--tv-accent-plein);
  border-color: var(--tv-accent-plein);
  color: var(--tv-on-accent);
}
.btn-fantome {
  background: transparent;
  border-color: transparent;
  color: var(--tv-ink-2);
}
.btn-danger { color: var(--tv-rouge-texte); }
.btn-plein { width: 100%; }
/* « Petit » par la typographie et les marges, jamais par la hauteur. */
.btn-petit { padding: 8px 12px; font-size: 14px; }

/* Un bouton occupé (envoi en cours) : la roue tourne, le libellé reste. */
.btn.is-occupe { cursor: progress; }
.btn.is-occupe::after {
  content: "";
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: tv-tourne .8s linear infinite;
}

.ico-btn {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--tv-ink);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform var(--tv-dur-xs) var(--tv-ease-out);
}
.ico-btn .ico { width: 22px; height: 22px; }
.ico-btn:active { transform: scale(.92); }

.lien-btn {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--tv-accent);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* ── Champs ───────────────────────────────────────────────────────────── */
.champ { display: grid; gap: 6px; min-width: 0; }
.champ label {
  font: 600 13px/1.3 var(--tv-ui);
  color: var(--tv-ink-2);
}
/* 16 px au moins : en dessous, iOS zoome au premier tap. */
.champ input {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--tv-line-3);
  border-radius: var(--tv-rayon-m);
  background: var(--tv-surface);
  color: var(--tv-ink);
  font: 400 16px/1.35 var(--tv-ui);
}
.champ input:focus-visible { outline: 2px solid var(--tv-accent); outline-offset: 1px; border-color: var(--tv-accent); }
.champ input[aria-invalid="true"] { border-color: var(--tv-rouge); }
.champ-aide { font-size: 12.5px; line-height: 1.45; color: var(--tv-ink-3); }

.champ-mdp { position: relative; }
.champ-mdp input { padding-right: 48px; }
.champ-oeil { position: absolute; top: 50%; right: 0; transform: translateY(-50%); color: var(--tv-ink-2); }
.champ-oeil:active { transform: translateY(-50%) scale(.92); }

.erreur {
  color: var(--tv-rouge-texte);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
}

.form-ligne { display: flex; align-items: flex-end; gap: 8px; }
.form-ligne .champ { flex: 1 1 auto; }
.form-ligne .btn { flex: none; }
.form-pile { display: grid; gap: 14px; }

/* ── Contrôle segmenté : une piste, un pouce sous le choix ────────────── */
/* La même langue que le contrôle de l'accueil (`.acc-seg`) : une piste
   teintée, le choix courant posé dessus sur un pouce clair. Pas de filet,
   pas de soulignement : la teinte et la graisse disent le choix. */
.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 2px;
  min-width: 0;
  padding: 3px;
  border-radius: 14px;
  background: var(--tv-seg-fond);
}
.seg-btn {
  position: relative;
  min-width: 0;
  min-height: 44px;
  padding: 8px 6px;
  border: 0;
  border-radius: 11px;
  background: transparent;
  color: var(--tv-ink-2);
  font: 500 14px/1.2 var(--tv-ui);
  cursor: pointer;
  touch-action: manipulation;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background-color var(--tv-dur-s) var(--tv-ease-out), color var(--tv-dur-s) var(--tv-ease-out);
}
.seg-btn[aria-checked="true"] {
  background: var(--tv-seg-pouce);
  color: var(--tv-ink);
  font-weight: 600;
  box-shadow: 0 0 0 1px var(--tv-seg-bord), 0 1px 2px rgba(31, 25, 18, .08);
}
.seg-btn[disabled] { color: var(--tv-ink-3); cursor: default; }
.seg-btn:focus-visible { outline-offset: -2px; }
.seg-chiffres .seg-btn { font-size: 13px; }

.reglage { display: grid; gap: 8px; min-width: 0; }
.reglage-nom { font: 600 13px/1.3 var(--tv-ui); color: var(--tv-ink-2); }

/* ── Interrupteur ─────────────────────────────────────────────────────── */
/* Le bord et la bille tiennent 3:1 éteints comme allumés (un état qu'on
   doit pouvoir lire). */
.inter {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 8px 2px;
  cursor: pointer;
}
.inter-texte { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.inter-nom { font-weight: 500; }
.inter-sous { font-size: 13px; line-height: 1.4; color: var(--tv-ink-3); }
.inter input {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  flex: none;
  width: 50px;
  height: 30px;
  margin: 0;
  border: 1.5px solid var(--tv-line-3);
  border-radius: 999px;
  background: var(--tv-surface-2);
  cursor: pointer;
  transition: background-color var(--tv-dur-s) var(--tv-ease-out),
              border-color var(--tv-dur-s) var(--tv-ease-out);
}
.inter input::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background: var(--tv-ink-3);
  transition: transform var(--tv-dur-s) var(--tv-ressort), background-color var(--tv-dur-s) var(--tv-ease-out);
}
.inter input:checked { background: var(--tv-accent-plein); border-color: var(--tv-accent-plein); }
.inter input:checked::before { transform: translateX(20px); background: var(--tv-on-accent); }
.inter input:focus-visible { outline: 2px solid var(--tv-accent); outline-offset: 2px; }
.inter input[disabled] { opacity: .5; cursor: default; }

/* ── Le blason : un emblème monoligne sur une teinte héraldique ──────── */
.blason {
  --b: 40px;
  position: relative;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--b);
  height: var(--b);
  border-radius: 50%;
  background: var(--tv-blason, var(--tv-teinte-6));
  color: var(--tv-embleme);
  /* La bordure d'un écu : un liseré clair à l'intérieur. */
  box-shadow: inset 0 0 0 calc(var(--b) * .045) rgba(251, 246, 234, .26);
}
.blason .ico { width: 60%; height: 60%; stroke-width: 1.6; }
.blason-petit { --b: 30px; }
.blason-moyen { --b: 44px; }
.blason-grand { --b: 88px; }
.blason-grand .ico { stroke-width: 1.5; }
.teinte-0 { --tv-blason: var(--tv-teinte-0); }
.teinte-1 { --tv-blason: var(--tv-teinte-1); }
.teinte-2 { --tv-blason: var(--tv-teinte-2); }
.teinte-3 { --tv-blason: var(--tv-teinte-3); }
.teinte-4 { --tv-blason: var(--tv-teinte-4); }
.teinte-5 { --tv-blason: var(--tv-teinte-5); }
.teinte-6 { --tv-blason: var(--tv-teinte-6); }
.teinte-7 { --tv-blason: var(--tv-teinte-7); }
/* Une table de la tournée encore fermée : le blason se ternit (le texte,
   lui, garde son contraste). */
.blason.is-terni { filter: grayscale(1); opacity: .55; }
/* Le médaillon d'un adversaire qui a un portrait (TaverneApp.medaillon) :
   la gravure remplit le rond, sur sa crème, cerclée d'un liseré fin posé
   PAR-DESSUS l'image (un `box-shadow` inset passerait dessous). Terni, il
   se grise comme l'emblème. */
.blason.a-portrait { background: #efe3c9; box-shadow: none; overflow: hidden; }
.blason.a-portrait::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(43, 32, 22, .24);
  pointer-events: none;
}
.blason-portrait {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  -webkit-user-drag: none;
  user-select: none;
}
/* Le sable sur la nuit : un liseré plus marqué, sinon l'écu se perd. */
:root[data-theme="dark"] .blason.teinte-3 { box-shadow: inset 0 0 0 calc(var(--b) * .045) rgba(251, 246, 234, .38); }

/* Choisir son emblème et sa teinte (inscription, profil). */
.emblemes {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 6px;
}
.teintes {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 4px;
}
.embleme-btn,
.teinte-btn {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  touch-action: manipulation;
}
.embleme-btn .blason { --b: 40px; transition: transform var(--tv-dur-xs) var(--tv-ease-out); }
.teinte-btn .pastille-teinte {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--tv-blason);
  box-shadow: inset 0 0 0 1.5px rgba(251, 246, 234, .26);
}
.embleme-btn[aria-checked="true"] .blason,
.teinte-btn[aria-checked="true"] .pastille-teinte {
  box-shadow: 0 0 0 2px var(--tv-bg), 0 0 0 4px var(--tv-accent);
}
.embleme-btn:active .blason { transform: scale(.92); }

/* ── Les bandes réglées : des listes séparées par des filets d'un pixel ─ */
.bande {
  display: grid;
  gap: 1px;
  min-width: 0;
  background: var(--tv-line);
}
.bande > li { background: var(--tv-bg); min-width: 0; }
.ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 62px;
  padding: 10px 2px;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
}
.ligne-action { cursor: pointer; touch-action: manipulation; transition: background-color var(--tv-dur-xs) var(--tv-ease-out); }
.ligne-action:active { background: var(--tv-surface-2); }
.ligne-action:focus-visible { outline-offset: -2px; }
.ligne-ico {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  color: var(--tv-ink-2);
}
.ligne-ico .ico { width: 24px; height: 24px; }
.ligne-texte { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.ligne-nom { font-weight: 500; overflow-wrap: anywhere; }
.ligne-nom.fell,
.fell { font-family: var(--tv-ui); font-size: 17px; font-weight: 650; letter-spacing: -.015em; line-height: 1.2; font-synthesis: none; }
.ligne-sous { font-size: 13px; line-height: 1.4; color: var(--tv-ink-3); overflow-wrap: anywhere; }
.ligne-fin { flex: none; font-size: 13px; color: var(--tv-ink-2); text-align: right; }
.ligne-chevron { flex: none; width: 18px; height: 18px; color: var(--tv-ink-3); }
.ligne .btn { flex: none; }

/* Une étiquette d'état (« À vous », « Battue ») : mono, filet, jamais un
   aplat criard. */
.etiquette {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border: 0;
  border-radius: 999px;
  background: var(--tv-surface-2);
  font: 500 11px/1.5 var(--tv-mono);
  letter-spacing: .02em;
  color: var(--tv-ink-2);
  white-space: nowrap;
}
.etiquette .ico { width: 13px; height: 13px; }
.etiquette-accent { color: var(--tv-accent-texte); background: var(--tv-accent-doux); }
.etiquette-vert { color: var(--tv-vert-texte); background: var(--tv-vert-doux); }
.etiquette-rouge { color: var(--tv-rouge-texte); background: var(--tv-rouge-doux); }

/* Le niveau d'un adversaire : cinq points, pleins jusqu'à son niveau. */
.niveau { display: inline-flex; gap: 3px; align-items: center; }
.niveau span { width: 6px; height: 6px; border-radius: 50%; border: 1px solid var(--tv-ink-3); }
.niveau span.is-plein { background: var(--tv-accent); border-color: var(--tv-accent); }

/* Un dé dessiné (miniature) et une rangée de dés. */
.des-rangee { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.de-mini { flex: none; display: block; }

.vide {
  padding: 18px 2px;
  color: var(--tv-ink-3);
  font-size: 14.5px;
  line-height: 1.5;
}

.appel {
  display: grid;
  gap: 12px;
  justify-items: start;
  padding: 18px;
  border-radius: 20px;
  background: var(--tv-surface);
  color: var(--tv-ink-2);
}

.actions-duo { display: flex; flex-wrap: wrap; gap: 8px; }
.actions-duo .btn { flex: 1 1 auto; min-width: 0; }

.sous-titre {
  font: 650 17px/1.25 var(--tv-ui);
  letter-spacing: -.015em;
  font-synthesis: none;
}

/* Les combinaisons (accueil et règles) : les dés dessinés, le nom, les
   points. Une bande réglée. */
.combos {
  display: grid;
  gap: 1px;
  background: var(--tv-line);
}
.combo {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  min-height: 46px;
  padding: 8px 2px;
  background: var(--tv-bg);
}
.combo-des { display: flex; gap: 3px; min-height: 22px; }
.combo-nom { font-size: 14px; line-height: 1.35; color: var(--tv-ink); }
.combo-pts { font-size: 14px; font-weight: 500; color: var(--tv-ink); text-align: right; }


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 4 · L'ACCUEIL : la table, le logo, la carte du compte
   │ Épuré (octobre 2026). Le caractère vient des OBJETS (le bois de la
   │ table, le gobelet de cuir, les dés en 3D, les portraits gravés) et du
   │ logo ; le texte et l'interface restent sobres : Inter Tight, des titres
   │ en 700 au tracé serré, beaucoup d'air, l'accent seul, des surfaces
   │ lisses et des filets fins. Ni parchemin, ni petites capitales, ni
   │ italique gravé, ni carte posée de travers. La démonstration « Comment on
   │ joue » a sa feuille (accueil.css) ; ce bloc ne pose que le cadre.
   └────────────────────────────────────────────────────────────────────────── */

/* La règle des titres de l'app (IM Fell, §2) s'arrête à la porte de
   l'accueil : ici, les titres sont ceux de l'interface. */
.accueil h1,
.accueil h2,
.accueil h3 {
  font-family: var(--tv-ui);
  font-weight: 700;
  letter-spacing: -.02em;
}

.accueil {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  max-width: 560px;
  min-height: 100dvh;
  margin: 0 auto;
  padding: max(8px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right))
           calc(32px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
}

.acc-haut { display: flex; justify-content: flex-end; min-height: 44px; margin-bottom: -10px; }

/* ── Le héros : la table, le logo, deux phrases ───────────────────────── */
.acc-scene { display: grid; gap: 26px; min-width: 0; }

/* La table : un OBJET (une vraie planche de bois), dans les deux thèmes.
   TaverneTable (le lot de la table) s'y installe et y fait rouler les dés ;
   sans lui, app.js y pose six dés dessinés. La lueur d'une chandelle tombe
   dessus, et le bas s'assombrit sous elle : l'éclairage de l'objet, pas un
   dégradé de décor. */
.acc-table {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 11;
  max-height: 50dvh;
  overflow: hidden;
  border-radius: 24px;
  background-color: var(--tv-bois-2);
  background-image:
    radial-gradient(105% 85% at 30% 22%, var(--tv-chandelle), rgba(255, 176, 82, 0) 64%),
    linear-gradient(180deg, rgba(10, 6, 3, 0) 52%, rgba(10, 6, 3, .34)),
    url("img/bois.webp");
  background-position: center, center, 50% 50%;
  background-size: auto, auto, cover;
  background-repeat: no-repeat;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .32), var(--tv-ombre-table);
  isolation: isolate;
}
/* Le bouton pause (WCAG 2.2.2 : un mouvement qui dure se met en pause). */
.acc-pause {
  position: absolute;
  z-index: 5;
  right: 10px;
  top: 10px;
  color: var(--tv-scene-ink);
  background: rgba(18, 13, 9, .46);
  -webkit-backdrop-filter: blur(10px) saturate(1.4);
  backdrop-filter: blur(10px) saturate(1.4);
}
.acc-pause .ico { width: 20px; height: 20px; }

/* Sans TaverneTable : six dés dessinés, posés de travers sur le bois. */
.acc-des-poses { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.acc-des-poses .de-mini {
  position: absolute;
  filter: drop-shadow(0 6px 5px rgba(0, 0, 0, .55)) drop-shadow(0 1px 1px rgba(0, 0, 0, .6));
}

.acc-titres { display: grid; gap: 12px; justify-items: center; text-align: center; min-width: 0; }
/* Le titre EST le logo (un dessin, nommé par son `aria-label`). */
.acc-titre { margin: 0; line-height: 0; }
.acc-logo { height: 64px; margin: 0 auto; }
.acc-phrase {
  max-width: 23ch;
  font: 600 21px/1.28 var(--tv-ui);
  letter-spacing: -.015em;
  color: var(--tv-ink);
  text-wrap: balance;
}
.acc-sous {
  max-width: 36ch;
  font-size: 15px;
  line-height: 1.5;
  color: var(--tv-ink-2);
  text-wrap: pretty;
}

.acc-invite {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 18px;
  background: var(--tv-accent-doux);
  font-size: 14.5px;
  line-height: 1.45;
}

/* ── La carte du compte ───────────────────────────────────────────────── */
/* Une surface lisse, un filet, un grand rayon : une carte d'app. Elle garde
   l'id `#registre` (scene.js la fait entrer, des tests la visent). */
.acc-carte {
  display: grid;
  gap: 18px;
  min-width: 0;
  padding: 16px;
  border-radius: 26px;
  background: var(--tv-surface);
}

/* Le contrôle segmenté : une piste, un pouce qui glisse sous le choix
   (posé par `data-onglet`, app.js). Le pouce est un pseudo-élément : il ne
   prend jamais le pointeur, et le libellé reste le bouton. */
.acc-seg {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding: 3px;
  border-radius: 14px;
  background: var(--tv-seg-fond);
  isolation: isolate;
}
.acc-seg::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  border-radius: 11px;
  background: var(--tv-seg-pouce);
  box-shadow: 0 0 0 1px var(--tv-seg-bord);
  transition: transform var(--tv-dur-m) var(--tv-ressort);
  pointer-events: none;
}
.acc-seg[data-onglet="inscription"]::before { transform: translateX(100%); }
.acc-seg-btn {
  min-width: 0;
  min-height: 44px;
  padding: 8px 10px;
  border: 0;
  border-radius: 11px;
  background: transparent;
  color: var(--tv-ink-2);
  font: 500 15px/1.2 var(--tv-ui);
  letter-spacing: -.005em;
  cursor: pointer;
  touch-action: manipulation;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color var(--tv-dur-s) var(--tv-ease-out);
}
.acc-seg-btn.is-on { color: var(--tv-ink); font-weight: 600; }
.acc-seg-btn:focus-visible { outline-offset: -2px; }

.acc-form { display: grid; gap: 14px; min-width: 0; }

/* Les champs façon iOS : le libellé au-dessus, un fond rempli, 17 px (16
   au moins : en dessous, iOS zoome au premier tap). Le filet du champ suit
   le focus et l'erreur. */
.champ-ios { gap: 7px; }
.champ-ios label { padding-left: 4px; }
.champ-ios input {
  min-height: 50px;
  padding: 13px 14px;
  border: 1px solid var(--tv-champ-bord);
  border-radius: var(--tv-rayon-l);
  background: var(--tv-champ);
  font: 400 17px/1.3 var(--tv-ui);
  transition: border-color var(--tv-dur-xs) var(--tv-ease-out), background-color var(--tv-dur-xs) var(--tv-ease-out);
}
.champ-ios input:focus-visible { outline: 2px solid var(--tv-accent); outline-offset: 2px; border-color: var(--tv-accent); }
.champ-ios .champ-mdp input { padding-right: 52px; }
.champ-ios .champ-oeil { right: 3px; }
.champ-ios .champ-aide { padding: 0 4px; }

/* Le blason, facultatif : un résumé replié qui le montre (tiré au hasard),
   et dessous les emblèmes et les teintes pour qui veut en changer. */
.acc-blason {
  border-radius: var(--tv-rayon-l);
  background: var(--tv-champ);
  box-shadow: inset 0 0 0 1px var(--tv-champ-bord);
}
.acc-blason-resume {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 8px 10px 8px 10px;
  border-radius: var(--tv-rayon-l);
  list-style: none;
  cursor: pointer;
  touch-action: manipulation;
}
.acc-blason-resume::-webkit-details-marker { display: none; }
.acc-blason-resume::marker { content: ""; }
.acc-blason-resume:focus-visible { outline-offset: -2px; }
.acc-blason-resume .blason { --b: 38px; }
.acc-blason-nom { flex: 1 1 auto; min-width: 0; font: 500 15px/1.3 var(--tv-ui); color: var(--tv-ink); }
.acc-blason-changer { flex: none; font: 500 14.5px/1.3 var(--tv-ui); color: var(--tv-accent-texte); }
.acc-blason-chevron {
  width: 18px;
  height: 18px;
  color: var(--tv-ink-3);
  transition: transform var(--tv-dur-s) var(--tv-ease-out);
}
.acc-blason[open] .acc-blason-chevron { transform: rotate(90deg); }
.acc-blason-corps { display: grid; gap: 10px; padding: 2px 10px 12px; }
.acc-blason .embleme-btn[aria-checked="true"] .blason,
.acc-blason .teinte-btn[aria-checked="true"] .pastille-teinte {
  box-shadow: 0 0 0 2px var(--tv-champ), 0 0 0 4px var(--tv-accent);
}

.acc-envoyer {
  min-height: 52px;
  margin-top: 2px;
  border-radius: var(--tv-rayon-l);
  font-size: 16px;
  font-weight: 600;
}

.acc-sans {
  display: grid;
  gap: 8px;
  justify-items: center;
  text-align: center;
  color: var(--tv-ink-3);
  font-size: 13.5px;
  line-height: 1.45;
}
.acc-sans-btn {
  min-height: 50px;
  padding: 12px 26px;
  border-radius: 999px;
  background: var(--tv-surface-2);
  font-size: 15.5px;
  font-weight: 600;
}

/* ── Sous le pli : des sections, un titre chacune ─────────────────────── */
.acc-section { display: grid; gap: 14px; min-width: 0; align-content: start; }
.acc-h2 { font-size: 26px; line-height: 1.12; }
.acc-section > p { max-width: 60ch; font-size: 15.5px; line-height: 1.55; color: var(--tv-ink-2); }
.acc-comment { margin-top: 26px; }

.acc-suite { display: grid; gap: 44px; margin-top: 18px; }

/* Ce qui marque : une liste groupée, des lignes séparées par des filets
   d'un pixel dans une carte arrondie. */
.acc-marque .combos {
  border-radius: 20px;
  overflow: hidden;
}
.acc-marque .combo { min-height: 50px; padding: 9px 14px; background: var(--tv-surface); }
.acc-marque .combo-nom { font-size: 14.5px; }

/* La tournée : un rail de huit médaillons, qu'on fait glisser au doigt.
   Le dégradé du bord droit dit qu'il y en a d'autres. */
.acc-tables {
  display: flex;
  gap: 6px;
  margin: 0 -16px;
  padding: 4px 16px 6px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 16px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 40px), transparent);
}
.acc-tables::-webkit-scrollbar { display: none; }
.acc-tables:focus-visible { outline-offset: -2px; }
.acc-tables > li {
  flex: 0 0 92px;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 8px;
  min-width: 0;
  text-align: center;
  scroll-snap-align: start;
}
.acc-tables .blason { --b: 64px; }
.acc-table-texte { display: grid; gap: 2px; min-width: 0; }
.acc-table-nom { font: 600 13.5px/1.2 var(--tv-ui); letter-spacing: -.01em; overflow-wrap: anywhere; }
.acc-table-lieu { font-size: 12px; line-height: 1.3; color: var(--tv-ink-3); overflow-wrap: anywhere; }

.acc-pied {
  display: grid;
  gap: 6px;
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--tv-line);
  color: var(--tv-ink-3);
  font-size: 13px;
  line-height: 1.5;
}
.acc-pied a { color: var(--tv-ink-2); text-decoration-color: var(--tv-accent); text-underline-offset: 3px; }
.acc-liens a { display: inline-block; padding: 6px 0; }


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 5 · LA COQUILLE : barre du haut, bandeaux, vues, onglets
   └────────────────────────────────────────────────────────────────────────── */

.coquille { min-height: 100dvh; padding-left: var(--tv-nav); }

/* La barre du haut. Deux calques derrière son contenu : le papier (au
   repos) et le verre (le contenu passe dessous). Seules leurs opacités
   changent quand app.js pose `.is-verre` : le flou est posé une fois. */
.barre-haut {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: calc(var(--tv-haut-h) + env(safe-area-inset-top));
  margin-left: calc(-1 * var(--tv-nav));
  padding: env(safe-area-inset-top) max(6px, env(safe-area-inset-right)) 0 max(16px, env(safe-area-inset-left));
  isolation: isolate;
}
.barre-haut::before,
.barre-haut::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  transition: opacity var(--tv-dur-s) var(--tv-ease-out);
}
.barre-haut::before { background: var(--tv-bg); }
.barre-haut::after {
  opacity: 0;
  border-bottom: 1px solid var(--tv-verre-bord);
  background-color: var(--tv-verre-fond);
  background-image: linear-gradient(180deg, var(--tv-verre-speculaire) 0, transparent 80%);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
}
.barre-haut.is-verre::before { opacity: 0; }
.barre-haut.is-verre::after { opacity: 1; }
.barre-actions { display: flex; align-items: center; gap: 2px; }
.barre-haut .mot-symbole { transform-origin: 0 50%; transition: scale var(--tv-dur-m) var(--tv-ressort); }
.barre-haut.is-verre .mot-symbole { scale: .94; }

/* ── Bandeaux ─────────────────────────────────────────────────────────── */
.bandeau {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  max-width: 760px;
  margin: 10px auto 0;
  margin-inline: max(16px, calc((100% - 760px) / 2));
  padding: 12px 14px;
  border-radius: 18px;
  background: var(--tv-surface);
  font-size: 14px;
  line-height: 1.45;
}
.bandeau > .ico { flex: none; color: var(--tv-ink-2); }
.bandeau p { flex: 1 1 200px; min-width: 0; }
.bandeau .btn { flex: none; }
.bandeau-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.bandeau-alerte { background: var(--tv-accent-doux); }
.bandeau-alerte > .ico { color: var(--tv-accent-texte); }
.bandeau-calme { background: var(--tv-surface-2); color: var(--tv-ink-2); }

/* ── Les vues ─────────────────────────────────────────────────────────── */
.vues {
  max-width: 760px;
  margin: 0 auto;
  padding: 8px 16px calc(108px + env(safe-area-inset-bottom));
}
/* `minmax(0, 1fr)` et non la colonne implicite `auto` : une piste `auto`
   grandit jusqu'à la largeur minimale de son contenu, et un rail de cartes
   ou une ligne insécable élargirait toute la vue au-delà de l'écran. */
.vue {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px;
  align-content: start;
}
.vue-titre { font-size: 32px; line-height: 1.08; letter-spacing: -.03em; margin-top: 4px; }

.sec { display: grid; gap: 10px; min-width: 0; }
.sec-tete { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; min-width: 0; }
.sec-titre { font-size: 19px; font-weight: 650; letter-spacing: -.02em; min-width: 0; }
.sec-compte { flex: none; font-size: 12px; letter-spacing: .03em; color: var(--tv-ink-3); }
.sec-texte { font-size: 14.5px; line-height: 1.5; color: var(--tv-ink-2); }

/* ── La barre d'onglets : une capsule de verre qui flotte ─────────────── */
/* Sur téléphone, la barre ne touche pas les bords : elle flotte au-dessus
   du contenu, en verre (le contenu passe dessous, flouté). verre.js y pose
   sa lentille ; sans lui, l'encoche de cuivre dit l'onglet courant. */
.onglets {
  position: fixed;
  z-index: 40;
  left: max(12px, env(safe-area-inset-left));
  right: max(12px, env(safe-area-inset-right));
  bottom: max(10px, calc(env(safe-area-inset-bottom, 0px) - 6px));
  max-width: 460px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  padding: 5px;
  border-radius: 999px;
  background-color: var(--tv-verre-fond);
  background-image: linear-gradient(180deg, var(--tv-verre-speculaire) 0, transparent 48%);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  backdrop-filter: blur(22px) saturate(1.6);
  box-shadow: var(--tv-verre-ombre), 0 0 0 .5px var(--tv-verre-bord), inset 0 1px 0 var(--tv-verre-lisere);
  transform-origin: 50% 100%;
}
/* Le liseré du bord : la réfraction d'un verre épais (masque composé). */
.onglets::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(135deg, var(--tv-verre-rim) 0, transparent 34%, transparent 66%, var(--tv-verre-rim-bas) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  pointer-events: none;
}
.onglet {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 2px;
  min-width: 0;
  min-height: 52px;
  padding: 5px 2px 4px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--tv-ink-2);
  /* La barre d'onglets est du mobilier, pas du texte de lecture. */
  font: 500 11px/1.15 var(--tv-ui);
  cursor: pointer;
  touch-action: manipulation;
  transition: color var(--tv-dur-xs) var(--tv-ease-out);
}
.onglet .ico { width: 23px; height: 23px; transition: transform var(--tv-dur-xs) var(--tv-ease-out); }
.onglet > span:not(.onglet-pastille) { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.onglet:active .ico { transform: scale(.9); }
.onglet.is-on { color: var(--tv-ink); font-weight: 600; }
.onglet.is-on .ico { color: var(--tv-accent-texte); }
/* L'encoche d'accent de l'onglet courant (la lentille de verre.js porte la
   sienne : `.has-lentille` efface celle-ci, jamais sans elle). */
.onglet.is-on::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 50%;
  width: 16px;
  height: 3px;
  margin-left: -8px;
  border-radius: 2px;
  background: var(--tv-accent);
}
.onglets.has-lentille .onglet.is-on::after { content: none; }
/* Le nombre de duels où c'est mon tour. */
.onglet-pastille {
  position: absolute;
  top: 3px;
  left: calc(50% + 7px);
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--tv-accent-plein);
  color: var(--tv-on-accent);
  font: 600 11px/18px var(--tv-mono);
  text-align: center;
  box-shadow: 0 0 0 2px var(--tv-surface);
}

/* Sans flou (navigateur ancien), un verre qu'on ne peut pas lire à travers
   serait une tache : le papier opaque. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .onglets,
  .barre-haut::after { background-color: var(--tv-surface); }
}

/* L'application ouverte au téléphone : la pastille « Admin » du Portfolio
   remonte au-dessus de la barre d'onglets (sinon elle se pose PILE sur
   « Jouer » et « Défis »). La spécificité (2,0,1) bat le style injecté. */
@media (max-width: 899px) {
  body:has(#app:not([hidden])) #mn-admin-pill {
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  }
}


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 6 · LES VUES
   └────────────────────────────────────────────────────────────────────────── */

/* ── Jouer : reprendre, la tournée, la partie rapide, à deux ─────────── */
.reprise {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 14px 14px 18px;
  border-radius: 20px;
  background: var(--tv-accent-doux);
}
.reprise-texte { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
.reprise-texte p { font-size: 14px; color: var(--tv-ink-2); }
.reprise .btn { flex: none; }

/* La tournée : un rail de huit tables, à faire glisser, reliées par le
   chemin (un pointillé entre deux cartes). */
.rail {
  display: flex;
  gap: 12px;
  margin: 0 -16px;
  padding: 4px 16px 14px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 16px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.rail::-webkit-scrollbar { display: none; }
.rail > li { position: relative; flex: 0 0 auto; scroll-snap-align: start; }
.table-carte {
  position: relative;
  display: grid;
  align-content: start;
  justify-items: start;
  gap: 4px;
  width: 188px;
  min-height: 240px;
  padding: 16px;
  border: 0;
  border-radius: 24px;
  background: var(--tv-surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform var(--tv-dur-xs) var(--tv-ease-out), box-shadow var(--tv-dur-xs) var(--tv-ease-out);
}
.table-carte:active { transform: scale(.98); }
.table-carte .blason { --b: 54px; margin: 6px 0 6px; }
.table-rang { font: 500 11px/1.4 var(--tv-mono); letter-spacing: .06em; color: var(--tv-ink-3); }
.table-tete { display: flex; align-items: center; justify-content: space-between; gap: 6px; width: 100%; }
.table-nom { font: 700 19px/1.15 var(--tv-ui); letter-spacing: -.02em; font-synthesis: none; }
.table-titre { font: 500 14px/1.3 var(--tv-ui); font-synthesis: none; color: var(--tv-ink-2); }
.table-lieu { display: flex; align-items: center; gap: 4px; font-size: 12.5px; line-height: 1.35; color: var(--tv-ink-3); }
.table-lieu .ico { width: 14px; height: 14px; flex: none; }
.table-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  margin-top: auto;
  padding-top: 12px;
}
.table-objectif { font-size: 12.5px; color: var(--tv-ink-2); }
.table-recompense { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--tv-ink-2); }
/* La prochaine table à affronter : un anneau de cuivre. Une table fermée
   garde sa surface ; son état se dit par l'étiquette « Fermée » et un nom
   plus discret, pas par un filet. */
.table-carte.is-prochaine { box-shadow: inset 0 0 0 2px var(--tv-accent); }
.table-carte.is-fermee { cursor: pointer; }
.table-carte.is-fermee .table-nom { color: var(--tv-ink-2); }

/* Une ligne d'adversaire (partie rapide, duel, ami, classement). */
.ligne .blason { --b: 44px; }

/* ── Défis ────────────────────────────────────────────────────────────── */
.defi-scores { font-family: var(--tv-mono); font-variant-numeric: tabular-nums; }
.defi-resultat { display: grid; gap: 10px; justify-items: start; }
.defi-resultat-titre { font: 700 20px/1.2 var(--tv-ui); letter-spacing: -.02em; font-synthesis: none; }
.defi-lien {
  max-width: 100%;
  font: 400 13px/1.4 var(--tv-mono);
  color: var(--tv-ink-2);
  overflow-wrap: anywhere;
}

/* ── Dés : la main et la collection ───────────────────────────────────── */
.main-slots {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.slot {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 6px;
  min-width: 0;
  min-height: 104px;
  padding: 14px 4px 12px;
  border: 0;
  border-radius: 20px;
  background: var(--tv-surface);
  color: inherit;
  font: inherit;
  cursor: pointer;
  touch-action: manipulation;
}
.slot[disabled] { cursor: default; }
.slot-nom { max-width: 100%; font-size: 12px; line-height: 1.25; color: var(--tv-ink-2); text-align: center; overflow-wrap: anywhere; }
.slot.is-choisi { box-shadow: inset 0 0 0 2px var(--tv-accent); background: var(--tv-accent-doux); }
.slot:active:not([disabled]) .de-mini { transform: scale(.92); }
.slot .de-mini { transition: transform var(--tv-dur-xs) var(--tv-ease-out); }
.main-choix { display: grid; gap: 8px; }
.main-choix-titre { font-size: 14px; color: var(--tv-ink-2); }

.de-apercu {
  display: grid;
  place-items: center;
  height: 220px;
  border-radius: var(--tv-rayon-l);
  background-color: var(--tv-bois-1);
  background-image: radial-gradient(90% 80% at 50% 35%, var(--tv-chandelle), transparent 65%),
    linear-gradient(180deg, var(--tv-bois-3), var(--tv-bois-2));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .5), inset 0 -18px 30px rgba(0, 0, 0, .35);
  overflow: hidden;
  position: relative;
}
.de-apercu > .de-mini { filter: drop-shadow(0 10px 8px rgba(0, 0, 0, .55)); }
.de-matiere { font: 500 12px/1.4 var(--tv-mono); letter-spacing: .05em; text-transform: uppercase; color: var(--tv-ink-3); }

/* Les probabilités d'un dé : une barre par face, à l'échelle de la face la
   plus probable (la comparaison qu'on vient chercher), la valeur écrite. */
.probas { display: grid; gap: 8px; }
.proba {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) 52px;
  align-items: center;
  gap: 10px;
}
.proba-barre { height: 8px; border-radius: 4px; background: var(--tv-line); overflow: hidden; }
.proba-barre > span {
  display: block;
  height: 100%;
  background: var(--tv-accent);
  transform-origin: 0 50%;
  transform: scaleX(var(--p, 0));
  transition: transform var(--tv-dur-l) var(--tv-ease-out);
}
.proba-pct { font-size: 13px; text-align: right; color: var(--tv-ink-2); }

/* ── Classement ───────────────────────────────────────────────────────── */
.rang { flex: none; width: 30px; font-size: 14px; font-weight: 500; color: var(--tv-ink-3); text-align: center; }
.classement li.est-moi { background: var(--tv-accent-doux); }
.classement li.est-moi .rang { color: var(--tv-accent-texte); }
.classement .ligne { padding-inline: 4px; }

/* ── Profil ───────────────────────────────────────────────────────────── */
.identite { display: flex; align-items: center; gap: 16px; min-width: 0; }
.identite-texte { min-width: 0; display: grid; gap: 4px; }
.identite-nom { font: 700 28px/1.1 var(--tv-ui); letter-spacing: -.03em; font-synthesis: none; overflow-wrap: anywhere; }
.identite-pseudo { font: 500 13px/1.4 var(--tv-mono); color: var(--tv-ink-3); overflow-wrap: anywhere; }
.profil-compte { display: grid; gap: 26px; }

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.stats > div { display: grid; gap: 2px; padding: 14px 16px; border-radius: 18px; background: var(--tv-surface); min-width: 0; }
.stats dt { font-size: 12.5px; line-height: 1.3; color: var(--tv-ink-3); }
.stats dd { font-size: 20px; font-weight: 500; color: var(--tv-ink); overflow-wrap: anywhere; }
/* Un nombre impair de cases : la dernière prend la rangée, plutôt que de
   laisser une case vide (un aplat gris sans rien dedans). */
.stats > div:last-child:nth-child(odd) { grid-column: 1 / -1; }

.trophees .ligne { align-items: flex-start; }
.trophees .ligne-ico { width: 32px; height: 32px; color: var(--tv-ink-3); }
.trophees li.est-obtenu .ligne-ico { color: var(--tv-accent); }
.trophees li:not(.est-obtenu) .ligne-nom { color: var(--tv-ink-2); }

.code-ami { display: grid; gap: 6px; padding: 14px 0 6px; }
.code-ami-label { font-size: 13px; color: var(--tv-ink-3); }
.code-ami-code { font-size: 28px; font-weight: 500; letter-spacing: .18em; color: var(--tv-ink); }

.reglages .inter { padding-inline: 2px; }
.suppr { padding: 16px; border-radius: 20px; background: var(--tv-rouge-doux); }
.apropos p { color: var(--tv-ink-2); line-height: 1.55; }
.apropos a { text-decoration-color: var(--tv-accent); text-underline-offset: 3px; }
.apropos-liens a { display: inline-block; padding: 6px 0; }
.apropos .btn { justify-self: start; }


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 7 · LES FEUILLES
   │ Au téléphone, une carte qui monte du bas (feuille.js en fait un ressort
   │ et fait reculer l'app) ; au-delà de 720 px, une fenêtre centrée. Le voile
   │ est une ombre étalée sur toute la fenêtre : un élément fixe et transformé
   │ ne peut pas porter un voile en pseudo-élément.
   └────────────────────────────────────────────────────────────────────────── */

.feuille {
  position: fixed;
  z-index: 60;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  max-height: calc(100dvh - max(26px, env(safe-area-inset-top)) - 10px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  border-radius: 26px 26px 0 0;
  background: var(--tv-surface);
  color: var(--tv-ink);
  box-shadow: 0 0 0 100vmax var(--tv-voile-fort), 0 -1px 0 var(--tv-line);
  outline: none;
}
.feuille-longue { height: calc(100dvh - max(26px, env(safe-area-inset-top)) - 10px); }
.feuille-tete {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 60px;
  padding: 14px 8px 6px 18px;
  border-bottom: 1px solid var(--tv-line);
}
/* La poignée : on tire la carte vers le bas pour la fermer (feuille.js). */
.feuille-tete::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  width: 36px;
  height: 4px;
  margin-left: -18px;
  border-radius: 2px;
  background: var(--tv-line-2);
}
.feuille-tete h2 { flex: 1 1 auto; min-width: 0; font-size: 21px; overflow-wrap: anywhere; }
/* Colonne flexible et non grille (le corps a une hauteur définie et défile :
   une grille y sizerait un enfant qui défile à zéro). */
.feuille-corps {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 18px 22px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.feuille-corps > * { flex: none; min-width: 0; }
.feuille-pied {
  flex: none;
  display: flex;
  gap: 10px;
  padding: 10px 18px 12px;
  border-top: 1px solid var(--tv-line);
  background: var(--tv-surface);
}
.feuille .bande > li,
.feuille .combo { background: var(--tv-surface); }
.feuille .stats > div { background: var(--tv-surface-2); }

/* La fiche d'un adversaire. */
.adv-carte { display: flex; align-items: center; gap: 14px; min-width: 0; }
.adv-carte .blason { --b: 56px; }
.adv-carte-texte { min-width: 0; display: grid; gap: 2px; }
.adv-tete { display: flex; align-items: center; gap: 16px; min-width: 0; }
.adv-tete > div { min-width: 0; }
/* Le buste gravé de l'adversaire (quand il en a un) : un carré arrondi,
   sur sa crème, le liseré posé par-dessus l'image (`outline` en retrait). */
.adv-portrait {
  flex: none;
  width: clamp(120px, 38vw, 168px);
  height: auto;
  aspect-ratio: 1;
  border-radius: 18px;
  background: #efe3c9;
  object-fit: cover;
  outline: 1px solid rgba(43, 32, 22, .22);
  outline-offset: -1px;
}
.adv-titre { font: 500 16px/1.3 var(--tv-ui); font-synthesis: none; color: var(--tv-ink-2); }
.adv-lieu { display: flex; align-items: center; gap: 5px; margin-top: 4px; font-size: 13.5px; color: var(--tv-ink-3); }
.adv-lieu .ico { width: 15px; height: 15px; flex: none; }
.adv-texte { font-size: 15px; line-height: 1.55; color: var(--tv-ink-2); }
.adv-replique {
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--tv-accent-doux);
  font: 500 16px/1.45 var(--tv-ui);
  font-synthesis: none;
  color: var(--tv-ink);
}
.adv-recompense { display: flex; align-items: center; gap: 12px; }
.adv-recompense-texte { display: grid; gap: 2px; min-width: 0; }
.adv-etat { font-size: 14px; color: var(--tv-ink-2); }

/* Les règles. */
.regles p { line-height: 1.6; color: var(--tv-ink-2); }
.regles-chapo { font: 600 17px/1.45 var(--tv-ui); letter-spacing: -.01em; font-synthesis: none; color: var(--tv-ink) !important; }
.etapes { display: grid; gap: 10px; }
.etapes li { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 8px; align-items: baseline; line-height: 1.5; }
.etape-n { font: 700 16px/1 var(--tv-ui); color: var(--tv-accent-texte); text-align: center; }


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 8 · L'ÎLE ET LA SCÈNE
   └────────────────────────────────────────────────────────────────────────── */

/* L'île : le message éphémère, en haut de l'écran (là où iOS pose les
   siens), au-dessus de tout. */
.ile {
  position: fixed;
  z-index: 95;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 50%;
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: min(92vw, 460px);
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--tv-ink);
  color: var(--tv-bg);
  font: 500 14px/1.35 var(--tv-ui);
  text-align: left;
  transform: translateX(-50%);
  box-shadow: 0 10px 28px -10px rgba(0, 0, 0, .5);
  pointer-events: none;
}
.ile .ico { width: 18px; height: 18px; }
.ile[data-ton="ok"] .ico { color: var(--tv-vert); }
:root[data-theme="dark"] .ile[data-ton="ok"] .ico { color: #2f7d55; }
.ile[data-ton="err"] .ico { color: var(--tv-rouge); }
:root[data-theme="dark"] .ile[data-ton="err"] .ico { color: #b3341f; }

/* La table de jeu : VIDE ici, jeu.js la construit (jeu.css). Toujours
   sombre ; elle couvre l'app, sous les feuilles (une règle qu'on rouvre en
   pleine partie passe devant). */
.scene {
  position: fixed;
  inset: 0;
  z-index: 55;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--tv-scene-bg);
  color: var(--tv-scene-ink);
  color-scheme: dark;
}


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 9 · GRANDS ÉCRANS
   └────────────────────────────────────────────────────────────────────────── */

@media (min-width: 520px) {
  .main-slots { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* Un très petit téléphone (320 px) : les titres et le logo se resserrent. */
@media (max-width: 359px) {
  .acc-h2 { font-size: 22px; }
  .acc-logo { height: 56px; }
  .acc-phrase { font-size: 19px; }
  .acc-carte { padding: 14px 12px; }
  .acc-seg-btn { padding-inline: 4px; font-size: 14.5px; letter-spacing: -.01em; }
}

/* À partir de 720 px, une feuille devient une fenêtre centrée. */
@media (min-width: 720px) {
  .feuille {
    inset: auto;
    top: 50%;
    left: 50%;
    width: min(560px, calc(100vw - 48px));
    max-height: min(88dvh, 860px);
    border-radius: 26px;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 0 100vmax var(--tv-voile-fort), 0 30px 60px -20px rgba(0, 0, 0, .45);
  }
  .feuille-longue { height: min(88dvh, 860px); width: min(640px, calc(100vw - 48px)); }
  .feuille-tete::before { content: none; }
  .feuille-tete { padding-top: 10px; }
  .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stats > div:last-child:nth-child(odd) { grid-column: auto; }
  .stats > div:last-child:nth-child(3n+1) { grid-column: 1 / -1; }
  .stats > div:last-child:nth-child(3n+2) { grid-column: span 2; }
}

/* À partir de 900 px : la navigation devient une colonne à gauche, et
   l'accueil pose la table à gauche, la carte du compte à droite. */
@media (min-width: 900px) {
  .coquille { --tv-nav: 220px; }
  .onglets {
    top: calc(var(--tv-haut-h) + env(safe-area-inset-top));
    left: 0;
    right: auto;
    bottom: 0;
    width: var(--tv-nav);
    max-width: none;
    margin: 0;
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    gap: 2px;
    padding: 18px 12px calc(16px + env(safe-area-inset-bottom));
    border-radius: 0;
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: inset -1px 0 0 var(--tv-line);
  }
  .onglets::before { content: none; }
  .onglet {
    grid-template-columns: 24px minmax(0, 1fr);
    justify-items: start;
    align-items: center;
    gap: 12px;
    min-height: 46px;
    padding: 8px 14px;
    border-radius: var(--tv-rayon-m);
    font-size: 15px;
  }
  .onglet.is-on { background: transparent; }
  .onglet.is-on::after { top: 50%; left: -12px; width: 3px; height: 24px; margin: -12px 0 0; border-radius: 0 2px 2px 0; }
  .onglet-pastille { position: static; justify-self: end; grid-column: 3; box-shadow: none; }
  .onglet { grid-template-columns: 24px minmax(0, 1fr) auto; }
  .vues { padding: 18px 32px 48px; }
  .vue-titre { font-size: 38px; }
  .rail { margin: 0; padding-inline: 0; scroll-padding-inline: 0; }

  /* L'accueil : le héros à gauche, la carte du compte à droite ; le reste
     dans une colonne de lecture, « Ce qui marque » et la tournée côte à
     côte. */
  .accueil {
    max-width: 1120px;
    grid-template-columns: minmax(0, 1.2fr) minmax(360px, 1fr);
    column-gap: 48px;
    row-gap: 22px;
    align-items: start;
    padding-top: max(16px, env(safe-area-inset-top));
    padding-inline: max(32px, env(safe-area-inset-left)) max(32px, env(safe-area-inset-right));
  }
  .acc-haut { grid-column: 1 / -1; margin-bottom: -6px; }
  .acc-scene { grid-column: 1; grid-row: 2 / span 3; }
  .acc-invite,
  .acc-carte,
  .acc-sans { grid-column: 2; }
  .acc-carte { padding: 20px; }
  .acc-table { max-height: none; }
  .acc-logo { height: 76px; }
  .acc-phrase { max-width: 30ch; font-size: 23px; }
  .acc-comment,
  .acc-suite,
  .acc-pied { grid-column: 1 / -1; }
  .acc-comment { margin-top: 44px; }
  .acc-h2 { font-size: 28px; }
  .acc-suite {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    column-gap: 56px;
    row-gap: 40px;
    align-items: start;
    margin-top: 36px;
  }
  /* La carte des combinaisons occupe deux rangées : sans « start », la
     grille répartissait sa hauteur entre la tournée et les duels. */
  .acc-marque { grid-row: span 2; }
  /* À cette largeur, les huit tables tiennent : une grille, plus un rail. */
  .acc-tables {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px 8px;
    margin: 0;
    padding: 0;
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .acc-tables > li { flex: none; }
}

@media (min-width: 1200px) {
  .vues { max-width: calc(820px + 64px); }
}


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 10 · MOUVEMENT
   │ Les modules d'effets (anim.js, feuille.js, verre.js) jouent leurs
   │ ressorts en WAAPI et posent leur classe d'activation sur <html>
   │ (`tv-anim`, `tv-feuille`) : les entrées CSS ci-dessous ne sont que le
   │ repli quand ils manquent. Transform et opacité seulement.
   └────────────────────────────────────────────────────────────────────────── */

@keyframes tv-tourne { to { transform: rotate(1turn); } }
@keyframes tv-monte-bas {
  from { transform: translateY(28px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes tv-monte-centre {
  from { transform: translate(-50%, calc(-50% + 16px)); opacity: 0; }
  to { transform: translate(-50%, -50%); opacity: 1; }
}
@keyframes tv-ile {
  from { transform: translateX(-50%) translateY(-8px) scale(.9); opacity: 0; }
  to { transform: translateX(-50%); opacity: 1; }
}
@keyframes tv-vue {
  from { transform: translateY(8px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

html:not(.tv-feuille) .feuille:not([hidden]) { animation: tv-monte-bas var(--tv-dur-m) var(--tv-ease-out); }
html:not(.tv-anim) .ile:not([hidden]) { animation: tv-ile var(--tv-dur-s) var(--tv-ease-out); }
html:not(.tv-anim) .vue:not([hidden]) { animation: tv-vue var(--tv-dur-s) var(--tv-ease-out); }
@media (min-width: 720px) {
  html:not(.tv-feuille) .feuille:not([hidden]) { animation-name: tv-monte-centre; }
}

/* LA règle de mouvement (patron La Singer) : `data-anim="off"` (posé par
   theme-init.js : le réglage d'abord, l'appareil ensuite) ramène toute
   animation et toute transition à une durée quasi nulle. Quasi nulle et
   non `none` : `animationend` et `transitionend` arrivent quand même. */
:root[data-anim="off"] *,
:root[data-anim="off"] *::before,
:root[data-anim="off"] *::after {
  animation-duration: .01ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
  transition-delay: 0s !important;
  scroll-behavior: auto !important;
}


/* ┌──────────────────────────────────────────────────────────────────────────
   │ 11 · SURVOL (pointeur fin seulement), puis `hover: none` EN DERNIER
   │ Une media query n'ajoute aucune priorité : seul l'ordre tranche. Posé
   │ plus haut, un `:hover` déclaré après resterait collé après un tap.
   └────────────────────────────────────────────────────────────────────────── */

@media (hover: hover) and (pointer: fine) {
  .btn:hover:not([disabled]) { border-color: var(--tv-line-3); }
  .btn-principal:hover:not([disabled]) { border-color: var(--tv-accent-plein); filter: brightness(1.08); }
  .btn-fantome:hover:not([disabled]) { color: var(--tv-ink); }
  .ico-btn:hover { background: var(--tv-surface-2); }
  .acc-pause:hover { background: rgba(18, 13, 9, .75); }
  .ligne-action:hover { background: var(--tv-surface-2); }
  .table-carte:hover { border-color: var(--tv-line-3); }
  .table-carte.is-prochaine:hover { border-color: var(--tv-accent); }
  .slot:hover:not([disabled]) { background: var(--tv-surface-2); }
  .onglet:hover { color: var(--tv-ink); }
  .seg-btn:hover:not([aria-checked="true"]):not([disabled]) { color: var(--tv-ink); background: var(--tv-surface-2); }
  .acc-seg-btn:hover:not(.is-on) { color: var(--tv-ink); }
  .acc-sans-btn:hover { background: var(--tv-surface); border-color: var(--tv-line-3); }
  .acc-blason-resume:hover .acc-blason-changer { text-decoration: underline; text-underline-offset: 3px; }
  .embleme-btn:hover .blason { transform: scale(1.06); }
}

@media (hover: none) {
  /* Au doigt, le retour vient de l'appui, jamais d'un survol resté collé. */
  .btn:hover,
  .ligne-action:hover,
  .table-carte:hover { filter: none; }
  .ligne-action:active,
  .slot:active:not([disabled]) { background: var(--tv-surface-2); }
}

/* Administration (compte admin seul) : la liste des inscrits défile dans son
   cadre plutôt que d'élargir la page sur téléphone. */
.admin-liste { overflow-x: auto; margin-top: 14px; border-block: 1px solid var(--tv-line); }
.admin-table { width: 100%; border-collapse: collapse; font-size: 14px; white-space: nowrap; }
.admin-table th, .admin-table td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--tv-line); }
.admin-table thead th { font-size: 12.5px; font-weight: 500; color: var(--tv-ink-3); }
.admin-table tbody th { font-weight: 500; color: var(--tv-ink); }
.admin-table td { color: var(--tv-ink); font-variant-numeric: tabular-nums; }
