﻿/* ═══════════════════════════════════════════════════════════════════════════
   DEVINE LE PARTI — LAYOUT V3 (page de jeu)
   ───────────────────────────────────────────────────────────────────────────
   Chargé APRÈS style.css + v3-integration.css. Re-style la charpente legacy en
   langage néo-brut V3 : grille bleue animée en fond, suppression des cadres-
   panneaux (carte / hémicycle / stats flottent comme des stickers), typo
   Syne 800 italic (titres + gros chiffres) / Space Mono (corps).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Fond : grille bleue animée (remplace les points legacy) ───────────── */
/* Défilement de la grille via TRANSFORM (GPU, fluide) plutôt que background-position
   (recalculé à chaque frame sur le CPU → saccadé). Le pseudo-élément déborde d'une
   cellule de chaque côté ; on le translate d'exactement une cellule → boucle sans
   couture (la grille se répète tous les --grid-size). */
@keyframes dlp-grid-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-1 * var(--grid-size, 32px)), calc(-1 * var(--grid-size, 32px)), 0); }
}
body[data-bg], body {
  background: var(--paper, #FFFDF5) !important;
}
body::before {
  content: '';
  position: fixed;
  top: calc(-1 * var(--grid-size, 32px));
  left: calc(-1 * var(--grid-size, 32px));
  width: calc(100vw + 2 * var(--grid-size, 32px));
  height: calc(100dvh + 2 * var(--grid-size, 32px));
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  var(--grid-blue, rgba(116,185,255,0.35)) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-blue, rgba(116,185,255,0.35)) 1px, transparent 1px) !important;
  background-size: var(--grid-size, 32px) var(--grid-size, 32px) !important;
  background-repeat: repeat !important;
  animation: dlp-grid-scroll var(--grid-speed, 24s) linear infinite;
  will-change: transform;
}
.reduce-motion body::before { animation: none !important; }

/* Le contenu passe au-dessus de la grille. */
.app, .header, .main, .card-stack, .right-col { position: relative; z-index: 1; }

/* ─── Typographie V3 ──────────────────────────────────────────────────────
   Syne 800 italic = gros titres + gros chiffres + verdict.
   Space Mono = corps / sous-lignes. Archivo Black (legacy --font-display)
   reste pour labels / nav / boutons. */
.site-title .accent {
  font-family: 'Syne', sans-serif !important;
  font-style: italic;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.stat-num,
.reveal-verdict,
.go-score,
.trigger-num,
.combo-intro-num {
  font-family: 'Syne', sans-serif !important;
  font-style: italic;
  font-weight: 800;
}
.stat-sub,
.mode-desc,
.panel-title,
.reveal-name,
.reveal-party-sub,
.stat-head {
  font-family: 'Space Mono', monospace !important;
}

/* ─── Suppression des cadres-panneaux ─────────────────────────────────────
   La carte (DLPCard, son propre cadre), l'hémicycle (DLPHemi) et le bloc
   stats/modes flottent directement sur la grille. */
.deputy-card,
.deputy-card-shadow {
  background: none !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
}
/* Coins décoratifs « dossier » de la carte legacy (L blancs) — masqués. */
.deputy-card > .corner,
.deputy-card-shadow > .corner,
.card-stack > .corner { display: none !important; }

.game-panel,
.controls-panel {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}
/* Le panneau hémicycle garde un fond paper léger UNIQUEMENT derrière le reveal
   (géré par reveal-overlay-bg) ; au repos il est transparent → grille visible. */

/* ─── Titre de page : sticker tilté ──────────────────────────────────────── */
.site-title .accent {
  transform: rotate(var(--rot-3, -1.5deg));
  display: inline-block;
}

/* ─── Stat-cards : léger rythme de rotations (sticker) ───────────────────── */
.stats-compact .stat-card:nth-child(1) { transform: rotate(var(--rot-1, -2.2deg)); }
.stats-compact .stat-card:nth-child(2) { transform: rotate(var(--rot-2, 1.8deg)); }
.stats-compact .stat-card:nth-child(3) { transform: rotate(var(--rot-3, -1.5deg)); }
.stats-compact .stat-card:nth-child(4) { transform: rotate(var(--rot-4, 2.5deg)); }   /* 4e carte Bulletins (Campagne) */

/* La carte elle-même : léger tilt sticker (cohérent Game Mobile). #11 : la
   carte-ombre (= carte suivante) doit partager EXACTEMENT la même rotation,
   sinon petit « jump » de rotation au swap carte→carte. */
.card-stack .deputy-card,
.card-stack .deputy-card-shadow { transform: rotate(-2deg); }


/* ═══════════════════════════════════════════════════════════════════════════
   FICHE DOSSIER INSTITUTIONNELLE (B9 — 2026-06-18, révisée)
   ───────────────────────────────────────────────────────────────────────────
   Petite fiche « dossier » papier néo-brut, clipsée par un TROMBONE en
   HAUT-GAUCHE de la carte (comme agrafée sur le haut de la photo). Le sceau rond
   (.fx-stamp-rf) reste ABANDONNÉ/masqué.
   Classe PARTAGÉE `.dossier-fiche` :
     · carte active  = #deputy-card .fx-stamp-rect.dossier-fiche (alimentée par
       applyStamps : institution + n° + --fiche-rot via window.DLPFiche.tilt) ;
     · cartes du deck = .deck-under-card .dossier-fiche (bâties par card-deck.js
       renderInto) → pré-chargées avec le stack, jamais de pop-in.
   Tilt déterministe PAR RP (window.DLPFiche.tilt) → identique deck↔active, donc
   le swap (promote) ne fait pas sauter la fiche. Tailles en cqw : #deputy-card
   ET .deck-under-card sont des query-containers → proportion identique partout.
   Ces règles overrident le display:none de v3-integration.css (chargé avant) +
   les positions/warp/encre du legacy style.css. */
.card-stack .deputy-card,
.card-stack .deck-under-card { container-type: inline-size; }

/* Sceau rond : abandonné (déjà masqué par v3-integration, explicite ici). */
.deputy-card .fx-stamp-rf,
.deputy-card-shadow .fx-stamp-rf { display: none !important; }

.card-stack .dossier-fiche {
  display: flex !important;
  flex-direction: column;
  align-items: center;
  position: absolute !important;
  /* (retour user) NE PLUS déborder à l'excès (sinon tronquée par le cadre du jeu).
     Le TROMBONE est calé près du HAUT de la carte ; la fiche pend juste dessous,
     posée sur la photo. Légère sortie en haut seulement (le trombone straddle le
     bord), corps de la fiche dans le cadre. */
  top: 7.5% !important;
  left: 3% !important;
  right: auto !important;
  bottom: auto !important;
  width: max-content !important;
  max-width: 52cqw;
  box-sizing: border-box;
  background: var(--paper);
  color: var(--ink);
  border: clamp(2px, 1.2cqw, 3.5px) solid var(--ink);
  box-shadow: clamp(2px, 1.3cqw, 4px) clamp(2px, 1.3cqw, 4px) 0 var(--ink);
  padding: 2.8cqw 4cqw 3cqw;
  text-align: center;
  line-height: 1.02;
  letter-spacing: normal;
  white-space: normal;                  /* override legacy white-space:nowrap */
  transform: rotate(var(--fiche-rot, 2.5deg)) !important;  /* tilt HORAIRE random/RP ; ignore --rot legacy */
  transform-origin: 84% -6px;           /* PIVOT = le point du trombone (haut-droite) → la fiche pend du trombone */
  filter: none !important;              /* tue le warp legacy */
  opacity: 1 !important;                /* tue l'opacité legacy randomisée */
  z-index: 6;
  pointer-events: none;
}
/* trombone : à DROITE de la fiche (retour user), straddle son haut, déborde
   au-dessus. NOIR, épaisseur calée sur les autres contours (≈ bordure fiche). */
.card-stack .dossier-fiche .fiche-clip {
  position: absolute;
  top: clamp(-13px, -5cqw, -8px);       /* trombone plus court → straddle réduit */
  right: 11%;
  left: auto;
  width: clamp(15px, 8.4cqw, 26px);     /* (retour user) PLUS LARGE */
  height: auto;
  z-index: 2;
  pointer-events: none;
}
.card-stack .dossier-fiche .fiche-clip svg { display: block; width: 100%; height: auto; overflow: visible; }
.card-stack .dossier-fiche .fiche-clip svg path {
  stroke: var(--ink) !important;        /* trombone entièrement NOIR */
  stroke-width: 5.5;                    /* viewBox 36 large → ~3.7px rendu = épaisseur des contours */
}
/* ligne 1 — institution (Archivo Black, casse haute, wrap équilibré) */
.card-stack .dossier-fiche .l1 {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(6px, 3.7cqw, 10.5px);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
  max-width: 32cqw;
  margin: 0 0 1.3cqw;
}
/* séparateur trait plein néo-brut */
.card-stack .dossier-fiche .sep {
  display: block;
  width: 100%;
  height: clamp(1.5px, .6cqw, 2.5px);
  background: var(--ink);
  margin: .2cqw 0 1.4cqw;
}
/* ligne 2 — étiquette mono espacée « DOSSIER N° » */
.card-stack .dossier-fiche .l2 {
  display: block;
  font-family: 'Space Mono', var(--font-mono);
  font-weight: 700;
  font-size: clamp(4.5px, 2.4cqw, 7px);
  letter-spacing: .2em;
  text-indent: .2em;
  color: var(--ink);
  margin: 0;
  opacity: 1;
}
/* ligne 3 — le numéro de dossier (Space Mono). Format réel alphanumérique
   (« AN-24-7213 », ~10-11 car.) → UNE ligne (nowrap). Taille RÉDUITE (retour
   user : baisser la hauteur de la fiche en diminuant le numéro). */
.card-stack .dossier-fiche .l3,
.card-stack .dossier-fiche .l3.num {
  display: block;
  font-family: 'Space Mono', var(--font-mono);
  font-weight: 700;
  font-size: clamp(7.5px, 4.4cqw, 11.5px);
  letter-spacing: .02em;
  white-space: nowrap;
  color: var(--ink);
  margin: .3cqw 0 0;
}


/* --- Carte-ombre : TOUJOURS masquée (sert uniquement de cible de rendu pour la
   carte suivante). #R4-2 : on ne la révèle PLUS pendant le swipe-out — sa
   silhouette (cadre du rôle suivant, souvent différent : festonné, arche…)
   dépassait derrière la carte courante puis disparaissait au swap = « stagger »
   visuel. La carte suivante apparaît proprement après le swipe via son
   slide-in. --- */
.deputy-card-shadow { opacity: 0 !important; }
/* La nouvelle carte courante glisse en place après le swap (au lieu d'un pop sec
   ou d'un peek d'ombre mal assorti). */
@keyframes dlp-card-enter {
  from { opacity: 0; transform: translateX(-14px) rotate(calc(-2deg - 5deg)); }
  to   { opacity: 1; transform: translateX(0) rotate(-2deg); }
}
.card-stack .deputy-card:not(.swiping-out):not(.revealed) .dlp-card-host.card-entering {
  animation: dlp-card-enter 260ms var(--ease-out, ease-out) both;
}
.reduce-motion .card-stack .deputy-card .dlp-card-host.card-entering { animation: none; }

/* --- Header : empeche le titre Syne (plus large) de manger la nav --- */
.header { flex-wrap: wrap; gap: 10px 14px; }
.site-title { flex: 0 1 auto; min-width: 0; }
.header-actions { flex: 0 0 auto; }


/* ════════════ MOBILE : une page, stats a droite de la photo ════════════ */
@media (min-width: 0px) {
  /* Titre : tient sur la largeur (B1 — ne plus déborder à droite). */
  .site-title { font-size: clamp(14px, 4.6vw, 18px) !important; letter-spacing: -0.015em !important; gap: 6px !important; }
  .site-title .accent { font-size: clamp(14px, 4.6vw, 18px) !important; padding: 4px 8px !important; }
  .site-emoji { font-size: 18px !important; }
  .header { padding: 8px 8px !important; }

  /* .main devient une grille flex ; on aplatit .right-col pour reordonner */
  .main#game { display: flex !important; flex-wrap: wrap !important; align-items: flex-start !important;
               gap: 8px 10px !important; padding: 8px 10px 0 !important; }
  .right-col { display: contents !important; }

  /* Carte a gauche (compacte) */
  .card-stack { order: 1 !important; flex: 0 0 46% !important; max-width: 46% !important; margin: 0 !important; }

  /* Stats empilees a DROITE de la carte */
  .controls-panel { order: 2 !important; flex: 1 1 0 !important; min-width: 0 !important;
    position: static !important; transform: none !important; visibility: visible !important; opacity: 1 !important;
    background: transparent !important; border: none !important; box-shadow: none !important;
    padding: 0 !important; max-height: none !important; height: auto !important; inset: auto !important; }
  .controls-panel > .section-title, .controls-panel .modes, .controls-panel .mode-desc,
  .controls-panel .specialiste-family-picker, .controls-panel .specialiste-role-picker,
  .controls-panel .mode-option-picker, .controls-panel .stats-close-btn { display: none !important; }
  .controls-panel .stats-compact { display: flex !important; flex-direction: column !important; gap: 8px !important; margin: 0 !important; }
  .controls-panel .stats-compact .stat-card { width: 100% !important; box-sizing: border-box !important; }

  /* Hemicycle : pleine largeur sous le hero */
  .game-panel { order: 3 !important; flex: 0 0 100% !important; width: 100% !important; }

  /* Trigger mobile inutile (stats deja visibles) ; nav en bas pleine largeur */
  .stats-trigger { display: none !important; }
  .mobile-footer-nav { order: 4 !important; flex: 0 0 100% !important; }

  /* Carte un peu moins haute pour laisser respirer */
  .card-stack .deputy-card { transform: rotate(-2deg); }
}


@media (min-width: 0px) {
  .game-panel { display: block !important; }
  #hemicycle-container { width: 100% !important; }
  .main#game { margin: 0 !important; }
}


/* ── Mobile : compacite + hemicycle qui reserve sa hauteur (anti-scroll) ── */
@media (min-width: 0px) {
  /* Carte plus etroite -> plus courte, laisse la place a l'hemicycle */
  .card-stack { flex: 0 0 42% !important; max-width: 165px !important; }
  /* Stats compactes */
  .controls-panel .stats-compact .stat-card { padding: 7px 10px !important; }
  .controls-panel .stats-compact .stat-num { font-size: 26px !important; }
  /* Hemicycle : le slot reserve sa hauteur via aspect-ratio, le svg le remplit */
  #hemi-slot { aspect-ratio: 400 / 240 !important; width: 100% !important; max-width: 460px !important; margin: 4px auto 0 !important; }
  #hemi-slot .hemicycle { display: block !important; height: 100% !important; width: 100% !important; max-width: none !important; }
  #hemi-slot .hemi-svg, #hemi-slot > .hemicycle > svg { height: 100% !important; width: 100% !important; }
  .game-panel { min-height: 0 !important; margin-top: 4px !important; }
  /* Reserve l'espace bas pour la nav fixe */
  .main#game { padding-bottom: 84px !important; }
}


/* ════════════ MOBILE v2 : grille deterministe (remplace le flex) ════════════ */
@media (min-width: 0px) {
  .main#game {
    display: grid !important;
    grid-template-columns: 156px 1fr !important;
    grid-auto-rows: min-content !important;
    gap: 10px 12px !important;
    align-content: start !important;
    padding: 8px 12px 86px !important;
    margin: 0 !important;
  }
  .right-col { display: contents !important; }
  .card-stack  { grid-column: 1 !important; grid-row: 1 !important; flex: none !important; max-width: none !important; width: auto !important; }
  .controls-panel { grid-column: 2 !important; grid-row: 1 !important; align-self: start !important; }
  .game-panel  { grid-column: 1 / -1 !important; grid-row: 2 !important; margin: 0 !important; }
  .stats-trigger { display: none !important; }
  .mobile-footer-nav { grid-column: 1 / -1 !important; }
  .card-stack .deputy-card, .card-stack .dlp-card-host { width: 100% !important; }
  /* Stats : plus compactes pour tenir a cote d'une carte courte */
  .controls-panel .stats-compact { gap: 7px !important; }
  .controls-panel .stats-compact .stat-card { padding: 6px 10px !important; }
  .controls-panel .stats-compact .stat-num { font-size: 24px !important; }
  /* Hemicycle : reserve sa hauteur, centre */
  #hemi-slot { aspect-ratio: 400 / 240 !important; width: 100% !important; max-width: 440px !important; margin: 0 auto !important; }
}


@media (min-width: 0px) {
  /* Le panneau stats ne doit pas etre un conteneur scrollable (c'etait un tiroir) */
  .controls-panel { overflow: visible !important; height: auto !important; max-height: none !important;
    min-height: 0 !important; -webkit-overflow-scrolling: auto !important; }
  .controls-panel .stats-compact { overflow: visible !important; max-height: none !important; height: auto !important; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   ROUND 2 — Corrections retours utilisateur (2026-05-31)
   Bloc ajouté EN DERNIER : ses règles priment sur tout ce qui précède.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── #4 · Pin-tag « ÉPINGLÉE » retiré partout (3 stats fixes, plus de pick) ── */
.pin-tag { display: none !important; }

/* ─── #1 (renfort) · La carte trading pilote sa taille ; bornée sur desktop pour
   ne pas devenir gigantesque (la colonne legacy était dimensionnée pour une
   photo pleine hauteur). Centrée, légère inclinaison sticker. ──────────────── */
.card-stack .deputy-card,
.card-stack .deputy-card-shadow { max-width: 340px; margin-left: auto; margin-right: auto; }
.card-stack { align-items: center; }

/* ─── #5/#9/#10 · Reveal = ENCART opaque sur la zone hémicycle (bas de l'écran) ──
   PAS plein écran (retour user R3). L'identité (nom/parti) apparaît dans un
   encart V3 (paper opaque + stroke 3px + ombre) qui recouvre l'hémicycle ; le
   verdict balistique se pose AU-DESSUS de TOUT (stat-cards incluses). Clé du
   #10 : on remonte .game-panel à --z-overlay dès l'apparition du VERDICT (pas
   seulement au reveal-screen) — sinon le verdict passait sous les stat-cards. */
.main#game:has(.reveal-verdict.show) .game-panel,
.main#game:has(.reveal-screen.visible) .game-panel {
  z-index: 500 !important;   /* au-dessus des stat-cards (#controls-panel z=200) et toasts */
  position: relative !important;
}
.reveal-overlay-bg { background: var(--paper) !important; }
.game-panel:has(.reveal-screen.visible) .reveal-overlay-bg {
  opacity: 1 !important;
  border: var(--stroke) !important;
  box-shadow: var(--sh) !important;
  z-index: 2 !important;
}
/* L'hémicycle (slot + svg) reste SOUS l'encart pendant le reveal. */
.game-panel:has(.reveal-screen.visible) #hemi-slot,
.game-panel:has(.reveal-screen.visible) #hemicycle-svg { z-index: 0 !important; }
/* Identité + verdict au-dessus de l'encart et de tout le reste. */
.reveal-screen { z-index: calc(var(--z-overlay) + 1) !important; }
.reveal-verdict { z-index: 520 !important; }   /* > stat-cards (200) et toasts, garanti */
.reveal-progress, .reveal-next { z-index: calc(var(--z-overlay) + 3) !important; }

/* #11 · Carte d'identité enrichie : rôle / mandat / âge sous l'identité. */
.reveal-meta {
  grid-column: 1 / -1;
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 9px;
}
.reveal-screen:not(.visible) .reveal-meta { display: none; }
.reveal-meta-row { display: flex; align-items: baseline; gap: 10px; }
.reveal-meta-row[hidden] { display: none !important; }
.reveal-meta-k {
  font-family: var(--font-heading); text-transform: uppercase;
  font-size: 10px; letter-spacing: 0.08em; opacity: 0.55;
  min-width: 62px; flex: 0 0 auto;
}
.reveal-meta-v {
  font-family: var(--font-body); font-size: 15px; font-weight: 700;
  color: var(--ink); line-height: 1.2;
}

/* ─── #11 · Post-it indice : déploiement vers la DROITE (au lieu de la gauche,
   où il était tronqué par la carte). On ancre le wrap à gauche et on inverse
   l'ordre flex : bouton à gauche, message qui pousse vers la droite. ────────── */
.hint-postit-wrap {
  right: auto !important;
  left: 6px !important;
  flex-direction: row-reverse !important;
}

/* ─── #7 · Navbar V3 — blocs colorés tiltés (header desktop + footer mobile) ──
   Langage gm-navbar : 4 blocs néo-brut, couleurs alternées, légères rotations,
   ombre dure 4×4, press qui écrase l'ombre. */
.header-actions .btn-collection,
.header-actions .btn-nav {
  box-shadow: var(--sh) !important;
  border: var(--stroke) !important;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out) !important;
}
.header-actions > *:nth-child(1) { transform: rotate(var(--rot-1)); background: var(--purple) !important; }
.header-actions > *:nth-child(2) { transform: rotate(var(--rot-6)); background: var(--yellow) !important; }
.header-actions > *:nth-child(3) { transform: rotate(var(--rot-3)); background: var(--blue) !important; }
.header-actions > *:nth-child(4) { transform: rotate(var(--rot-4)); background: var(--green) !important; }
.header-actions > *:nth-child(5) { transform: rotate(var(--rot-5)); background: var(--coral) !important; }  /* 5e bloc = bouton Menu ajouté en desktop (retour user 2026-06-22) */
html.dlp-can-hover .header-actions .btn-collection:hover,
html.dlp-can-hover .header-actions .btn-nav:hover {
  transform: translate(-2px, -2px) rotate(0deg) !important;
  box-shadow: var(--sh-hover) !important;
}
.header-actions .btn-collection:active,
.header-actions .btn-nav:active {
  transform: translate(4px, 4px) !important;
  box-shadow: var(--sh-press) !important;
}

/* ─── #8 · CTA « Nouvelle partie » + « Options » ─────────────────────────────── */
.gm-cta-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;   /* CHRONO ancré à GAUCHE (immuable) ; les CHOIX poussés à droite via
                                    #stage-postits{margin-left:auto} → débord éventuel à DROITE, jamais
                                    sur le chrono (retour user 2026-06-17 : le chrono ne bouge plus) */
  gap: 8px;
  padding: 4px 4px 2px;
  flex-wrap: nowrap;             /* (item 12) chrono + choix sur UNE ligne ; les choix rétrécissent au besoin */
  -webkit-flex-wrap: nowrap;     /* (item 12) préfixe pour vieux Safari */
  /* Accueille le CHRONO (à gauche) + les post-its de CHOIX (à droite), sur la même ligne,
     dans l'espace libéré sous l'hémicycle. HAUTEUR FIXE (retour user 2026-06-17) : la bande
     ne grandit JAMAIS, même quand une pastille de choix devient grande / wrappe sur 2 lignes
     → le chrono, l'hémicycle et le bouton Ratio restent STABLES (plus de jump à chaque
     sélection). overflow visible : les ombres/rotations des post-its dépassent sans être
     coupées, sans repousser les éléments voisins. */
  height: clamp(48px, 9vw, 58px);
  overflow: visible;
}
.btn-new-game, .btn-options {
  font-family: var(--font-heading);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink);
  border: var(--stroke);
  box-shadow: var(--sh);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.btn-new-game {
  background: var(--yellow);
  font-size: 17px;
  padding: 13px 22px;
  transform: rotate(var(--rot-1));
}
.btn-options {
  /* Orange (≠ vert+gear du bouton Paramètres) : plus de doublon visuel avec
     « Paramètres » de la navbar. Icône « swap » (changer de mode) côté HTML. */
  background: var(--orange);
  font-size: 14px;
  padding: 10px 16px;
  transform: rotate(var(--rot-4));
}
.btn-new-game .ico { width: 18px; height: 18px; }
.btn-options .ico { width: 16px; height: 16px; }
html.dlp-can-hover .btn-new-game:hover,
html.dlp-can-hover .btn-options:hover { transform: translate(-2px,-2px) rotate(0deg); box-shadow: var(--sh-hover); }
.btn-new-game:active, .btn-options:active { transform: translate(4px,4px); box-shadow: var(--sh-press); }

/* « Nouvelle partie » DANS la modale Options : lance directement la partie avec
   le mode sélectionné (sans devoir ressortir cliquer le CTA externe). Pleine
   largeur, pas de tilt (plus net dans la modale). */
.options-new-game {
  width: 100%; justify-content: center; margin-top: 16px; transform: none; font-size: 16px;
}
html.dlp-can-hover .options-new-game:hover { transform: translate(-2px, -2px); box-shadow: var(--sh-hover); }
.options-new-game:active { transform: translate(4px, 4px); box-shadow: var(--sh-press); }

/* ─── #8 · Modale Options ────────────────────────────────────────────────────── */
.options-backdrop {
  position: fixed; inset: 0;
  z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.options-backdrop[hidden] { display: none; }
.options-backdrop.show { opacity: 1; }
.options-modal {
  position: relative;
  width: min(420px, 100%);
  max-height: 88vh;
  overflow-x: hidden;        /* D1 : pas de scrollbar horizontale parasite */
  overflow-y: auto;
  box-sizing: border-box;
  background: var(--paper);
  border: var(--stroke);
  box-shadow: var(--sh-hover);
  padding: 22px 20px 20px;
  transform: rotate(-0.6deg) scale(0.96);
  transition: transform var(--dur-base) var(--ease-out);
}
/* D1 : la grille de modes ne doit pas déborder la modale. */
.options-modal .modes { gap: 8px !important; }
.options-modal .mode-btn { min-width: 0 !important; }
.options-backdrop.show .options-modal { transform: rotate(-0.6deg) scale(1); }
.options-close {
  position: absolute; top: 10px; right: 10px;   /* à l'intérieur : pas de débord → pas de scroll (D1) */
  width: 34px; height: 34px;
  background: var(--red); color: var(--ink);
  border: var(--stroke); box-shadow: 3px 3px 0 var(--ink);
  font-size: 17px; line-height: 1; cursor: pointer;
  font-family: var(--font-heading);
  transform: rotate(6deg);
  z-index: 2;
}
html.dlp-can-hover .options-close:hover { transform: rotate(0deg) translate(-1px,-1px); box-shadow: var(--sh-hover); }
.options-modal .section-mode { margin-top: 4px; }
/* Les .mode-btn / pickers conservent leur style legacy (style.css). On garde
   leur visibilité dans la modale (game-v3 mobile les masquait dans le panel). */
.options-modal .specialiste-family-picker:not(.hidden),
.options-modal .specialiste-role-picker:not(.hidden),
.options-modal .mode-option-picker:not(.hidden) { display: flex; flex-wrap: wrap; }
/* Grille 2 colonnes déterministe (D1 : flex-wrap laissait 11px de débord). */
.options-modal .modes {
  display: grid !important;
  grid-template-columns: 1fr 1fr !important;
  gap: 8px !important;
  width: 100% !important;
}
.options-modal .mode-btn { min-width: 0 !important; width: auto !important; }
/* La description est un paragraphe avec des termes de glossaire inline :
   surtout PAS de flex (ça casserait le flux du texte → « Choisiscampparmi »). */
.options-modal .mode-desc { display: block; margin-top: 12px; }

/* ─── #13 · UI modale Options retravaillée pour coller au langage V3 ──────────── */
.options-modal { padding: 26px 18px 20px !important; }
/* #9 · Header d'info dans la modale (la sélection ne relance pas la partie). */
.options-modal .mode-select-hint {
  margin: 14px 0 2px !important;
  font-family: var(--font-body); font-size: 12px; line-height: 1.4;
  background: var(--yellow); color: var(--ink);
  border: var(--stroke); box-shadow: 3px 3px 0 var(--ink);
  padding: 8px 12px; transform: rotate(-0.7deg);
}
/* Titre « MODE DE JEU » : sticker affirmé, plus gros, tilté. */
.options-modal .section-mode {
  font-family: var(--font-heading) !important;
  font-size: 17px !important;
  letter-spacing: 0.02em !important;
  margin: 0 0 14px !important;
  display: inline-flex !important; align-items: center !important; gap: 8px !important;
}
.options-modal .section-mode .section-tag {
  background: var(--ink) !important; color: var(--paper) !important;
  width: 26px; height: 26px; display: inline-grid; place-items: center;
  transform: rotate(-4deg);
}
/* Boutons de mode : léger rythme sticker (tilts alternés), comme la navbar. */
.options-modal .modes { gap: 10px !important; }
.options-modal .mode-btn { padding: 12px 8px !important; font-size: 13px !important; }
.options-modal .mode-btn:nth-child(odd)  { transform: rotate(-1.2deg); }
.options-modal .mode-btn:nth-child(even) { transform: rotate(1.2deg); }
.options-modal .mode-btn.active { transform: rotate(0deg) !important; }
/* Description : note crème encadrée (sticker), pas un simple paragraphe nu. */
.options-modal .mode-desc {
  margin-top: 16px !important;
  background: var(--paper-2) !important;
  border: var(--stroke) !important;
  box-shadow: 4px 4px 0 var(--ink) !important;
  padding: 12px 14px !important;
  font-family: var(--font-body) !important;
  font-size: 13px !important; line-height: 1.5 !important;
  transform: rotate(-0.8deg);
}

/* ════════════ MOBILE ROUND 2 — proportions, hauteurs, titre, navbar ════════════ */
@media (min-width: 0px) {
  /* #9 · Titre pleine largeur + centré */
  .header { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; }
  .site-title { width: 100% !important; justify-content: center !important; text-align: center !important; display: flex !important; align-items: center; gap: 8px; }
  .header-actions { display: none !important; }  /* nav du bas suffit sur mobile */

  /* #2 · Proportions carte 2/3 — stats 1/3 ; #3 · hauteurs égales.
     Grille déterministe : col1=carte (2fr), col2=stats (1fr). Les deux
     cellules de la rangée 1 s'étirent à la même hauteur (align-items stretch
     + rangées auto pilotées par la hauteur intrinsèque de la carte). */
  .main#game {
    grid-template-columns: 2fr 1fr !important;
    grid-auto-rows: auto !important;
    align-items: stretch !important;
    gap: 10px 10px !important;
    padding: 8px 12px 92px !important;
  }
  .card-stack { grid-column: 1 !important; grid-row: 1 !important; align-self: stretch !important; align-items: stretch !important; }
  .card-stack .deputy-card, .card-stack .deputy-card-shadow,
  .card-stack .dlp-card-host { max-width: none !important; width: 100% !important; margin: 0 !important; }

  .controls-panel { grid-column: 2 !important; grid-row: 1 !important; align-self: stretch !important; }
  /* #3 · le stack de 3 stat-cards remplit toute la hauteur de la carte. */
  .controls-panel .stats-compact {
    height: 100% !important;
    display: flex !important; flex-direction: column !important;
    gap: 8px !important; margin: 0 !important;
  }
  .controls-panel .stats-compact .stat-card {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    width: 100% !important; box-sizing: border-box !important;
    display: flex !important; flex-direction: column !important; justify-content: center !important;
    padding: 8px 10px !important;
  }
  .controls-panel .section-title { display: none !important; }  /* « Score » : superflu sur mobile */

  /* Hémicycle pleine largeur sous le hero */
  .game-panel { grid-column: 1 / -1 !important; grid-row: 2 !important; }
  /* CTA pleine largeur sous l'hémicycle */
  .gm-cta-row { grid-column: 1 / -1 !important; grid-row: 3 !important; }

  /* #7 · Footer nav V3 : 5 blocs colorés tiltés (Modes + 4). Grille à 5 colonnes
     STRICTEMENT égales + gap resserré → tout tient sur UNE ligne (le bouton Modes
     ajouté en navbar a forcé un 5e segment, cf. retour user). */
  .mobile-footer-nav.is-fixed {
    display: grid !important;
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;  /* minmax(0,…) : sinon le min-content « Classements » (nowrap) empêche les colonnes de se partager le viewport → débord */
    gap: 6px !important;
    background: var(--paper) !important;
    border-top: var(--stroke) !important;
  }
  .mobile-nav-btn {
    flex: none !important;
    flex-direction: column !important;
    gap: 3px !important;
    border: var(--stroke) !important;
    box-shadow: 4px 4px 0 var(--ink) !important;
    padding: 7px 1px 6px !important;
    /* Police FLUIDE : 8.5px sur grand téléphone, rétrécit jusqu'à 6.6px pour faire
       tenir « Classements » (Archivo Black caps, le libellé le plus large) sur 5
       colonnes même à 320px (Z Flip). minmax(0,1fr) côté grille fait le reste. */
    font-size: clamp(6.6px, 2.0vw, 8.5px) !important;
    letter-spacing: -0.02em !important;
    white-space: nowrap !important;
    overflow: visible !important;       /* D6 : « Classements » entier, pas d'ellipsis */
    text-overflow: clip !important;
  }
  .mobile-nav-btn:nth-child(1) { transform: rotate(-1.4deg); background: var(--purple) !important; }
  .mobile-nav-btn:nth-child(2) { transform: rotate(1.2deg);  background: var(--yellow) !important; }
  .mobile-nav-btn:nth-child(3) { transform: rotate(-1deg);   background: var(--blue) !important; }
  .mobile-nav-btn:nth-child(4) { transform: rotate(1.5deg);  background: var(--green) !important; }
  .mobile-nav-btn:nth-child(5) { transform: rotate(-1.2deg); background: var(--coral) !important; }
  .mobile-nav-btn .ico { width: 20px !important; height: 20px !important; }
  .mobile-nav-btn:active { transform: translate(3px,3px) !important; box-shadow: var(--sh-press) !important; }
  /* (#5 mobile est désormais géré par le bloc reveal GLOBAL unifié plus haut.) */

  /* Post-it Ratios : le legacy le poussait à top:-50px (dans la carte). En V3
     l'hémicycle est une rangée distincte sous le hero → on le ramène dans la
     zone hémicycle (gap au-dessus, à gauche de l'arc centré), sans chevaucher
     la carte. */
  .pct-postit { top: -6px !important; left: 4px !important; }
}


/* ─── ROUND 2 · correctifs mobile post-vérif navigateur ─────────────────────── */
@media (min-width: 0px) {
  /* (A) Les stat-cards masquées (VIES hors Survie) restent masquées malgré le
     display:flex appliqué aux stat-cards visibles. */
  .controls-panel .stats-compact .stat-card.hidden,
  .controls-panel .stats-compact .stat-card[hidden] { display: none !important; }

  /* (C) Hauteurs égales carte/stats : le legacy ne définissait que 2 rangées
     (row1 clampée, row2 1fr) → la carte débordait d'une row1 trop courte et la
     CTA passait en rangée implicite (chevauchement). On redéfinit 3 rangées
     auto (hero / hémicycle / CTA), dimensionnées par leur contenu. La rangée
     hero prend alors la hauteur de la carte ; la colonne stats s'y étire. */
  .main#game {
    grid-template-rows: auto auto auto !important;
    height: auto !important;
    min-height: 0 !important;
    align-items: stretch !important;
  }
  .controls-panel { align-self: stretch !important; height: auto !important; display: flex !important; flex-direction: column !important; }
  .controls-panel .stats-compact { flex: 1 1 auto !important; }

  /* (B) Hémicycle compact : laisse une vraie place à la CTA, sans chevauchement.
     290px de large → ~174px de haut (ratio 400/240). */
  #hemi-slot { max-width: 290px !important; margin: 0 auto !important; }
  .game-panel { align-self: start !important; overflow: visible !important; min-height: 0 !important; }
  .gm-cta-row {
    position: relative !important; z-index: 6 !important;
    margin-top: 2px !important; gap: 8px !important;
    align-self: center !important;
  }
  .btn-new-game { font-size: 15px !important; padding: 11px 16px !important; }
  .btn-options  { font-size: 13px !important; padding: 9px 13px !important; }

  /* Titre : emoji dans le bandeau (pas en débord à gauche) */
  .site-title .site-emoji { font-size: 22px !important; }

  /* (D) CAUSE RACINE des hauteurs inégales : les items grid ont min-width:auto
     (= min-content) par défaut → l'hémicycle (span 2 col) et la carte forçaient
     les pistes à s'élargir (grid à 468px > viewport), donc col1 trop large →
     carte trop haute qui débordait de sa rangée. min-width:0 contraint les
     pistes au viewport : col1 (2fr) ≈ 2/3, la carte y définit la hauteur de la
     rangée, et la colonne stats s'y étire (hauteurs égales). */
  .app { overflow-x: clip; }
  /* overflow-x: clip contient l'hémicycle large horizontalement ; overflow-y
     DOIT rester visible sinon le haut des stat-cards (coins tiltés + ombres) et
     les bumpers de score (qui montent en translateY négatif au-dessus de la
     stat-card, pile au bord supérieur de .main) sont rognés = « mur invisible ». */
  .main#game { width: 100% !important; max-width: 100vw !important; box-sizing: border-box !important; overflow-x: clip !important; overflow-y: visible !important; }
  .card-stack, .controls-panel, .game-panel, .gm-cta-row { min-width: 0 !important; }

  /* (E) Hauteurs STRICTEMENT égales (#3) + largeurs 2/3–1/3 (#2) — déterministe.
     Le track-sizing auto du grid n'attrape NI la hauteur d'un <svg height:auto>
     NI celle dérivée d'un aspect-ratio (quirk Chromium) → la rangée se calait
     sur les stats et la carte débordait. On garde donc les colonnes 2fr/1fr
     (largeurs 2/3–1/3) ET on impose une hauteur explicite IDENTIQUE aux deux
     colonnes : `min(86vw, 50vh)` (plafond anti-scroll sur écran court). La carte
     DLPCard remplit son conteneur (léger meet ≈ pas de letterbox visible). */
  .main#game { grid-template-columns: 2fr 1fr !important; }
  .card-stack {
    height: min(86vw, 50vh) !important;
    align-self: start !important;
  }
  .card-stack .deputy-card,
  .card-stack .deputy-card-shadow,
  .card-stack .dlp-card-host { height: 100% !important; width: 100% !important; }
  .card-stack .dlp-card-host .card,
  .card-stack .dlp-card-host .card-svg { height: 100% !important; width: 100% !important; }
  .controls-panel { height: min(86vw, 50vh) !important; align-self: start !important; }
}


/* ─── ROUND 2 · finitions navbar + CTA mobile (post-vérif) ──────────────────── */
@media (min-width: 0px) {
  /* (A) Navbar : 4 colonnes STRICTEMENT égales. On neutralise les règles legacy
     (icon-only à largeur fixe, « Succès » réduit à font-size:0 sous 430px) qui
     détachaient le 4e bloc et tronquaient les libellés. */
  .mobile-footer-nav.is-fixed {
    padding: 8px 6px calc(10px + env(safe-area-inset-bottom, 0px)) 6px !important;
    align-items: stretch !important;
  }
  .mobile-nav-btn,
  .mobile-nav-btn-icon-only,
  .mobile-nav-btn[href*="achievements.html"] {
    flex: none !important;
    width: auto !important;
    min-width: 0 !important;
    font-size: clamp(6.6px, 2.0vw, 8.5px) !important;  /* fluide : tient « Classements » de 320px à 412px+ */
    gap: 3px !important;
    overflow: visible !important;       /* libellés entiers (« Classements ») sur 5 colonnes */
    text-overflow: clip !important;
  }
  .mobile-nav-btn[href*="achievements.html"] .ico,
  .mobile-nav-btn .ico { width: 20px !important; height: 20px !important; font-size: initial !important; }

  /* (B) CTA : une seule ligne, taille compacte, et vraie clairance sous
     l'hémicycle (le bas du demi-cercle ne doit pas toucher les boutons). */
  .gm-cta-row {
    flex-wrap: nowrap !important;
    margin-top: 14px !important;
    gap: 8px !important;
  }
  .btn-new-game { font-size: 13px !important; padding: 10px 14px !important; }
  .btn-options  { font-size: 12px !important; padding: 9px 12px !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   ROUND 3 — ajustements mobile (2026-05-31, retours user). Dernier bloc =
   priorité cascade. Desktop INTACT (scoped max-width:760px) — il aura ses
   propres passes.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 0px) {

  /* #1 · TITRE : typo agrandie + justifiée bord à bord du cadre (text-align-last
     justify étale les 3 mots), cadre plus haut, emoji plus gros + superposé. */
  .header { padding: 6px 8px 4px !important; }
  .site-title { width: 100% !important; display: flex !important; align-items: center !important; gap: 0 !important; }
  .site-title .site-emoji {
    font-size: 40px !important;
    margin-right: -16px !important;
    z-index: 3 !important;
    transform: rotate(-8deg) translateY(2px) !important;
  }
  .site-title .accent {
    flex: 1 1 auto !important;
    display: block !important;
    margin-left: 0 !important;
    /* « DEVINE LE PARTI » : grand sur 2 lignes, remplit le cadre, mais borné
       pour laisser la place à un grand hémicycle (budget vertical à 844px). */
    font-size: clamp(20px, 7vw, 28px) !important;
    line-height: 1.0 !important;
    letter-spacing: -0.02em !important;
    text-align: center !important;
    white-space: normal !important;
    padding: 8px 12px 9px 20px !important;
  }

  /* #7 · HÉMICYCLE bord à bord + interlignes resserrés. La rangée hémicycle
     prend tout l'espace restant (1fr) → l'hémicycle se centre dans la zone
     libre entre le hero et la CTA, qui se cale juste au-dessus de la navbar
     (plus de grand vide). Le slot déborde légèrement les bords latéraux. */
  .main#game {
    /* La grille occupe la hauteur dispo et CENTRE son contenu (align-content) →
       le vide est réparti haut/bas au lieu d'être massé entre l'hémicycle et la
       navbar (le 1fr ne suffisait pas : la résolution fr se cale sur la hauteur
       de contenu, pas sur min-height). */
    grid-template-rows: auto auto auto !important;
    row-gap: 8px !important;
    padding: 6px 10px 84px !important;
    min-height: calc(100dvh - 150px) !important;
    align-content: space-between !important;   /* hero en haut, CTA près de la navbar, vide réparti */
  }
  #hemi-slot { max-width: none !important; width: 116% !important; margin: 0 -8% !important; }
  .game-panel {
    grid-row: 2 !important;
    align-self: center !important;
    margin: 0 !important;
    display: flex !important; align-items: center !important; justify-content: center !important;
  }
  .hemicycle-wrap, #hemicycle-container { width: 100% !important; }

  /* #2 · Stat-stack PLUS COURT que la carte + centré verticalement.
     Carte dimensionnée à ~sa hauteur naturelle (largeur colonne × 1.5) pour
     remplir sans letterbox ET réduire le vide hero↔hémicycle. */
  .card-stack { height: min(88vw, 48vh) !important; align-self: start !important; }
  .controls-panel {
    height: min(78vw, 44vh) !important;   /* plus proche de la carte → moins de vide sous les stats */
    align-self: center !important;        /* centré sur la hauteur de la carte */
    display: flex !important; flex-direction: column !important;
  }
  .controls-panel .stats-compact {
    height: 100% !important; flex: 1 1 auto !important;
    display: flex !important; flex-direction: column !important; gap: 7px !important;
  }
  .controls-panel .stats-compact .stat-card {
    flex: 1 1 0 !important; min-height: 0 !important;
    display: flex !important; flex-direction: column !important; justify-content: space-between !important;
    gap: 2px !important; padding: 7px 10px !important; overflow: hidden !important;
  }

  /* #3 · CHIFFRE beaucoup plus gros (remplit le vide), borné pour ne pas déborder. */
  .controls-panel .stats-compact .stat-num {
    font-size: clamp(28px, 10vw, 40px) !important;
    line-height: 0.95 !important;
    white-space: nowrap !important;
    flex: 1 1 auto !important;
    display: flex !important; align-items: center !important;
  }
  .controls-panel .stats-compact .stat-sub { font-size: 9px !important; opacity: 0.8 !important; }
  .controls-panel .stats-compact .stat-sub-acc .acc-good,
  .controls-panel .stats-compact .stat-sub-acc .acc-bad,
  .controls-panel .stats-compact .stat-sub-acc .acc-sep { font-size: 13px !important; }

  /* #4 · ICÔNE stat-card SANS cercle, à DROITE juste avant le nom. */
  .controls-panel .stat-head {
    flex-direction: row-reverse !important;
    justify-content: flex-start !important;
    gap: 6px !important;
    font-size: 9px !important;
  }
  .controls-panel .stat-head .ico,
  .controls-panel .stat-card[data-tone="points"] .stat-head .ico,
  .controls-panel .stat-card[data-tone="lives"]  .stat-head .ico {
    background: none !important;
    border-radius: 0 !important;
    width: 18px !important; height: 18px !important;
    color: currentColor !important;
    place-items: center;
  }
  .controls-panel .stat-head .ico svg { width: 18px !important; height: 18px !important; }

  /* #5 · POST-IT INDICE plus petit + coin BAS-GAUCHE de la carte (message → droite).
     (retour user 2026-06-18) Ancrage FIXE, indépendant du rôle/forme de carte : le recalage
     JS par-carte (syncHintToPhoto) qui faisait « sauter » le bouton a été supprimé. `bottom`
     reste proportionnel à la hauteur de carte (responsive) mais CONSTANT d'une carte à l'autre,
     placé SOUS la carte avec un léger chevauchement (offset -40px ; abaissé de +22px vs -18px
     sur retour user 2026-06-18 « baisser encore d'au moins 20px »). */
  .hint-postit-wrap {
    top: auto !important;
    bottom: calc(var(--frame-bot-frac) * var(--card-h) - 40px) !important;
    left: -4px !important; right: auto !important;
    flex-direction: row-reverse !important;
    min-height: 0 !important; max-height: none !important;
    padding: 5px 8px !important;
    font-size: 10px !important;
  }
  .hint-postit { gap: 3px !important; }
  .hint-postit > .ico { width: 16px !important; height: 16px !important; }
  /* Pastille de coût à largeur STABLE (centrée) → le bouton ne change pas de
     largeur entre « -2 PTS » et « -10 PTS ». */
  .hint-postit .cost { font-size: 9px !important; padding: 2px 5px !important; min-width: 44px !important; text-align: center !important; box-sizing: border-box !important; }

  /* #6 · POST-IT RATIOS plus petit + à DROITE de l'hémicycle. En version
     compacte, le camembert legacy (34px, poussé par margin-top:auto) chevauchait
     « RATIOS » → on masque l'icône décorative : « RATIOS / −1 PTS » reste clair. */
  /* #3 (user) · Bouton « Ratios » en forme de CAMEMBERT — le différencie des
     post-its rectangulaires (Indice). Cercle néo-brut : pie conic-gradient
     (proportions de partis, couleurs de l'hémicycle = thématique « ratios ») +
     trou central « donut » paper portant le label + coût. */
  /* Bouton « Ratios » = camembert néo-brut « éclaté » (croquis user), rendu+animé
     par js/ratios-icon.js. Conteneur TRANSPARENT : tout le visuel est dans le SVG
     (#pct-postit > .pct-svg). Position pilotée par sizeHemicycle (#1) : centré dans
     le creux du donut par défaut, glissé dans la zone vide à droite quand l'hémicycle
     rétrécit. */
  .pct-postit {
    right: auto !important;
    /* Position + taille pilotées par sizeHemicycle (#2/#3) : centre de l'icône
       aligné (remonté) sur le centre du cercle de l'hémicycle (top), centré +
       décalé droite (left), TAILLE proportionnelle à l'hémicycle (--ratios-size).
       Fallbacks avant le 1er passage JS. */
    top: var(--ratios-top, auto) !important;
    bottom: var(--ratios-bottom, 2px) !important;
    left: var(--ratios-left, 50%) !important;
    margin-left: var(--ratios-ml, -54px) !important;
    width: var(--ratios-size, 108px) !important; height: var(--ratios-size, 108px) !important;
    min-height: 0 !important; padding: 0 !important;
    background: none !important; border: none !important;
    box-shadow: none !important; border-radius: 0 !important;
    display: block !important; overflow: visible !important;
    /* Sway léger (comme Passer/Indice), désynchronisé (4.3s vs 3.6/4.1s). Le
       `rotate` n'entre pas en conflit avec le positionnement (left/top, pas transform). */
    animation: ratiosSway 4.3s ease-in-out infinite !important;
    transition: top .3s ease, left .3s ease, margin-left .3s ease,
                width .3s ease, height .3s ease,
                opacity .2s ease, scale .22s cubic-bezier(.34,1.56,.64,1) !important;  /* (item 4) scale-in/out pop */
  }
  @keyframes ratiosSway { 0%, 100% { rotate: -3deg; } 50% { rotate: 3deg; } }
  html.reduce-motion .pct-postit { animation: none !important; rotate: 0deg !important; }
  .pct-postit .pct-svg { width: 100% !important; height: 100% !important; display: block !important; overflow: visible !important; }
  /* Ombre portée DURE (= box-shadow néo-brut des autres éléments) sur le donut. (#3) */
  .pct-postit .pct-seg { filter: drop-shadow(3px 3px 0 var(--ink)); }
  /* Contour 3px CONSTANT (non-scaling) = même épaisseur que carte/hémicycle/stat-cards
     (--stroke-w) quelle que soit la taille du donut → cohérence des contours. */
  .pct-postit .pct-seg path { vector-effect: non-scaling-stroke !important; }
  .pct-postit .pct-svg-label {
    font-family: var(--font-heading), sans-serif !important;  /* Archivo Black ; font-size piloté par JS (fit RATIOS/ÉGALISER) */
    letter-spacing: -0.02em !important;
    fill: var(--ink) !important;
    stroke: var(--paper) !important; stroke-width: 2px !important; /* halo BEIGE fin DERRIÈRE le noir (réduit, retour user) */
    paint-order: stroke !important;
  }
  .pct-postit .pct-ico { display: none !important; }
  /* libellé texte HTML caché (accessibilité via aria-label du bouton) */
  .pct-postit .pct-lbl { position: absolute !important; width: 1px !important; height: 1px !important; overflow: hidden !important; clip: rect(0 0 0 0) !important; white-space: nowrap !important; }

  /* CTA resserrée (l'hémicycle prend plus de place au-dessus). */
  .gm-cta-row { margin-top: 6px !important; }

  /* #11 (mobile) · verdict aligné à GAUCHE de l'encart, responsive : court =
     gros, long = rétréci par fitRevealVerdict() (nowrap requis ; on NE met PAS
     !important sur font-size pour que le fit JS inline puisse réduire). Base
     plus grosse que le legacy (« Oui » bien gros). max-width = largeur écran
     pour que le fit borne sans troncature. */
  .reveal-verdict.show {
    left: 14px !important; right: auto !important; margin: 0 !important;
    width: fit-content !important;        /* la boîte hugge le texte → vrai alignement gauche */
    max-width: calc(100vw - 56px) !important;   /* marge pour que le mot le plus long ne soit pas rogné par la rotation */
    /* Verdicts COURTS (« Oui ») = grosse police (clamp) sur 1 ligne ; LONGS =
       wrap multi-lignes. Le fit JS (fitRevealVerdict, SANS !important ici) réduit
       la police jusqu'à ce que le mot le plus large tienne dans la boîte → ni
       troncature ni débordement, tout en gardant les courts bien gros. */
    white-space: normal !important;
    text-align: left !important;
    font-size: clamp(34px, 13vw, 64px);   /* agrandi (retour user 2026-06-14) ; le fit JS réduit les longs */
    line-height: 1.05 !important;
    overflow: visible !important;            /* la rotation -2° ne doit pas couper le dernier caractère */
    padding: 10px 16px 12px !important;
  }
  .main#game:has(.reveal-screen.visible) .gm-cta-row { visibility: hidden !important; }

  /* #8 (fix overlap reveal) · Sur petit panel, le bloc enrichi rôle/mandat/âge
     sur-remplissait l'encart à hauteur fixe → les lignes grid se compriment et,
     comme `.reveal-name` a `overflow:hidden` (→ taille mini auto = 0 en grid),
     sa ligne tombait à 0px et le NOM recouvrait le pill parti. Double parade :
     1) min-height sur le nom = sa ligne ne peut plus s'écraser sous 1 ligne ;
     2) on compacte le bloc meta (marge/gap/police) → c'est LUI qui cède
        gracieusement si l'espace manque, jamais l'identité. */
  .reveal-name { min-height: 1.05em !important; }
  /* B1 (critique #1) : gouttière en bas → le bloc meta (rôle/mandat) ne peut
     plus passer SOUS le bouton SUIVANT (absolu bottom-right) ni se faire
     tronquer au ras du cadre. Si l'espace manque, c'est la meta qui cède
     AU-DESSUS du bouton, jamais de collision. */
  .reveal-screen.visible { row-gap: 5px !important; padding-bottom: 26px !important; }
  .reveal-meta { margin-top: 8px !important; gap: 4px !important; }
  /* SUIVANT compact dans le coin bas-droit. */
  .reveal-next {
    bottom: -18px !important;
    right: 10px !important;
    padding: 6px 13px 7px !important;
    font-size: 12px !important;
  }
  /* B2.2 (2026-06-10) : le clamp 1-ligne + gouttière droite 100px qui vivait ici
     coupait la valeur MANDAT « alors qu'il y a la place » — la fiche Dossier est
     à hauteur de contenu et les boutons Pause/Suivant sont abaissés sous elle,
     donc le wrap multi-lignes est redevenu sûr. */
  .reveal-meta-row { gap: 8px !important; }
  .reveal-meta-k { min-width: 52px !important; font-size: 9px !important; }
  .reveal-meta-v { font-size: 13px !important; line-height: 1.15 !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   ROUND 4 — retours user (2026-05-31). MOBILE uniquement. Dernier bloc.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 0px) {

  /* #1 · TITRE : le bloc (flex:1) remplit la largeur ; le TEXTE est JUSTIFIÉ
     (text-align-last:justify) pour atteindre la marge droite à toute largeur
     (sans ça, à police plafonnée, le texte laissait du vide à droite). Police
     bornée pour rester sur une seule ligne. */
  .site-title .accent {
    flex: 1 1 auto !important;
    font-size: clamp(13px, 4.6vw, 22px) !important;
    white-space: normal !important;
    text-align: justify !important;
    text-align-last: justify !important;
    overflow: hidden !important;
    line-height: 1.1 !important;
    padding: 10px 14px 10px 18px !important;
  }

  /* #5 · HÉMICYCLE au-dessus de la carte/stats (la légère superposition doit
     passer PAR-DESSUS). #6 · post-its indice + ratios au-dessus de TOUT.
     Clé : card-stack/controls en z auto (pas de stacking context) pour que les
     enfants (hint) s'évaluent au niveau racine et dépassent l'hémicycle. */
  .card-stack { z-index: auto !important; }
  .controls-panel { z-index: auto !important; }
  .game-panel { z-index: 10 !important; }            /* #5 */
  .hint-postit-wrap { z-index: 60 !important; }      /* #6 */
  .pct-postit { z-index: 60 !important; }            /* #6 (dans game-panel z:10 → au-dessus de l'hémicycle) */

  /* #8 · Les bumpers de score doivent DÉBORDER de la stat-card (rendus
     au-dessus). On retire le overflow:hidden posé en R3. Le chiffre est borné
     par sa police responsive (#4), pas par un clip. */
  .controls-panel .stats-compact .stat-card { overflow: visible !important; }
  .score-bump { z-index: 80 !important; }            /* au-dessus des cartes voisines */

  /* #4 · Le sous-texte des stat-cards reste TOUJOURS visible ; le gros chiffre
     rétrécit si la carte est trop courte (clamp borné aussi par vh). */
  .controls-panel .stats-compact .stat-card {
    display: flex !important; flex-direction: column !important; justify-content: space-between !important;
  }
  .controls-panel .stats-compact .stat-num {
    font-size: clamp(22px, min(10vw, 6.4vh), 40px) !important;
    flex: 0 1 auto !important;
    min-height: 0 !important;
  }
  .controls-panel .stats-compact .stat-sub,
  .controls-panel .stats-compact .stat-sub-acc { flex: 0 0 auto !important; }  /* jamais écrasé */

  /* #12 · Post-it indice plus ÉTROIT (marges G/D trop importantes). */
  .hint-postit { padding: 0 !important; }
  .hint-postit .hint-line { letter-spacing: -0.01em !important; }
  .hint-postit-wrap { padding: 5px 6px !important; }

  /* #7 · CTA « Nouvelle partie » + « Options » plus GRANDES (largeur), collées
     juste sous l'hémicycle (léger chevauchement constant) et proches de la
     navbar (espace minimal). On groupe hémicycle + CTA vers le bas : le vide
     se loge entre le hero et l'hémicycle (rangée hémicycle en 1fr, hémicycle
     calé en bas de cette rangée). */
  .main#game {
    grid-template-rows: auto 1fr auto !important;
    align-content: stretch !important;
    row-gap: 0 !important;
    column-gap: 16px !important;   /* l'ombre 7px de la carte mangeait le gap → 16px pour respirer */
    /* padding-bottom : petit espace constant CTA↔navbar (le .app réserve déjà
       la hauteur de la navbar fixe). */
    padding: 6px 10px 14px !important;
  }
  .game-panel { align-self: end !important; }        /* hémicycle en bas de sa rangée 1fr → vide au-dessus */
  .gm-cta-row {
    margin-top: -6px !important;                      /* léger chevauchement constant avec le bas de l'hémicycle */
    gap: 10px !important;
    display: flex !important; align-items: stretch !important;
  }
  .gm-cta-row .btn-new-game {
    flex: 1 1 auto !important;
    font-size: 15px !important; padding: 12px 14px !important;
    white-space: nowrap !important; justify-content: center !important;
  }
  .gm-cta-row .btn-options {
    flex: 0 0 auto !important;
    font-size: 14px !important; padding: 12px 16px !important;
    white-space: nowrap !important; justify-content: center !important;
  }
}


/* ════════════════════════════════════════════════════════════════════════════
   ROUND 5 — retours user (2026-05-31, captures). MOBILE. Dernier bloc = priorité.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 0px) {

  /* #2 · Moins d'interligne titre → contenu. */
  .header { padding: 6px 8px 2px !important; }
  .main#game { padding-top: 2px !important; }

  /* #3 · Carte pilotée par sa HAUTEUR (largeur dérivée via aspect-ratio),
     justifiée à GAUCHE ; stats en 1fr qui remplissent la largeur restante avec
     un gap CONSTANT. Quand la fenêtre rétrécit, la carte (height min(96vw,48vh))
     rapetisse → sa largeur diminue → les stats s'allongent pour combler.
     Hauteurs ÉGALES (même H, align-self:start → top+bottom alignés). */
  .main#game { grid-template-columns: auto 1fr !important; column-gap: 14px !important; }
  .card-stack {
    height: min(84vw, 46vh) !important;
    aspect-ratio: 2 / 3 !important;
    width: auto !important;
    align-self: start !important;
    justify-self: start !important;
  }
  .controls-panel {
    height: min(84vw, 46vh) !important;
    align-self: start !important;       /* même haut/bas que la carte */
    width: auto !important;
  }
  .card-stack .deputy-card,
  .card-stack .deputy-card-shadow,
  .card-stack .dlp-card-host,
  .card-stack .dlp-card-host .card,
  .card-stack .dlp-card-host .card-svg { height: 100% !important; width: 100% !important; }

  /* #6 · Post-it indice plus ÉTROIT : le bloc hugge ses lignes (pas de marge
     latérale superflue). Les 2 lignes « DEMANDER / UN INDICE » donnent la
     largeur ; on retire le min-width et on serre le padding. */
  .hint-postit-wrap { padding: 5px 7px !important; min-width: 0 !important; }
  .hint-postit { gap: 2px !important; }
  .hint-postit .hint-line { font-size: 10px !important; letter-spacing: -0.02em !important; white-space: nowrap !important; }

  /* #10 · Bouton « Passer » : (B9 2026-06-18) BAS-DROITE de la carte (la fiche
     dossier prend le haut-gauche), au-dessus de l'hémicycle (z:60), compact. */
  .skip-rp {
    bottom: 0px !important;
    right: 2px !important;
    top: auto !important;
    left: auto !important;
    z-index: 60 !important;
    font-size: 10px !important;
    padding: 4px 7px 4px 6px !important;
    gap: 4px !important;
  }
  .skip-rp .skip-ico { width: 12px !important; height: 12px !important; }

  /* B2 (critique #2) · La carte Précision porte « nombre + % » (2 spans), donc
     plus large que les cartes à 1 token (Points/Série). À 39px le « 100% »
     débordait du bloc (overflow:visible, posé pour les score-bumps en #8, ne le
     retenait pas). On réduit le nombre de CETTE carte + le « % » pour que même
     « 100% » tienne dans la largeur. */
  .stat-card[data-tone="acc"] .stat-num {
    font-size: clamp(18px, 7.2vw, 30px) !important;
    white-space: nowrap !important;
    max-width: 100% !important;
  }
  .stat-card[data-tone="acc"] .stat-num > span:last-child { font-size: 0.5em !important; }

  /* B3 (critique #3) · Le nombre POINTS grimpe à 3-4 chiffres (« 146 ») et
     débordait/clippait sur la carte (overflow:visible #8). On le borne en nowrap
     + clamp qui tient confortablement 3 chiffres. Le badge combo ×N MORD le coin
     (au lieu de flotter à moitié dehors → lecture « glitch »). */
  .stats-compact .stat-num { white-space: nowrap !important; }
  .stat-card[data-tone="points"] .stat-num { font-size: clamp(20px, 8vw, 34px) !important; }
  .combo-pin { top: -10px !important; right: -9px !important; }

  /* #4 + #5 · Hémicycle : on TRIME le vide réservé sous l'arc (viewBox 240 mais
     contenu jusqu'à y≈186 → aspect 400/192) et on le pilote par la HAUTEUR avec
     un plafond vh → il RÉTRÉCIT sur écran court avant de chevaucher (au lieu de
     tout cacher). La CTA se cale alors juste sous l'arc visible. */
  #hemi-slot {
    /* Largeur pilotée + plafond vh (#5 : la largeur — et donc la hauteur via
       l'aspect — rétrécit quand la hauteur dispo manque, avant de chevaucher).
       aspect 400/195 + overflow:hidden ROGNE le vide réservé sous l'arc (le SVG
       en height:auto déborde par le bas, zone vide → coupée) → la CTA lèche
       l'arc visible (#4). */
    width: min(126%, calc(36vh * 400 / 195)) !important;  /* + grand sur écran haut (comble le vide), bridé en vh (shrink #5) */
    height: auto !important;
    aspect-ratio: 400 / 195 !important;
    margin: 0 auto !important;
    overflow: hidden !important;
  }
  #hemi-slot .hemicycle { height: auto !important; width: 100% !important; max-width: none !important; }
  #hemi-slot .hemi-svg, #hemi-slot > .hemicycle > svg, #hemi-slot svg {
    width: 100% !important; height: auto !important;
  }
  .gm-cta-row { margin-top: 6px !important; }   /* lèche le bas (rogné) de l'hémicycle */
  .main#game { padding-bottom: 14px !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   ROUND 6 — retours user (2026-05-31). MOBILE uniquement (desktop différé).
   DERNIER bloc = priorité cascade. Corrige : #1 titre modulaire (grossit au lieu
   d'étaler les mots), #2 stack borné à la carte + bouton Passer en overlay coin
   haut-gauche, #3 anti-troncature par le titre, #4 hémicycle RECENTRÉ (était
   décalé+tronqué à droite), #6 CTA/vides resserrés, #7 chiffres stat fit (base
   CSS + fit JS), #8 mentions alignées gauche + police heading.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 0px) {

  /* ── #1 · TITRE modulaire ────────────────────────────────────────────────
     GROSSIR avec le conteneur via une taille en vw (plus de text-align:justify
     qui étalait les espaces entre les mots). Une ligne, centré, remplit le cadre
     par la taille, proportions conservées. */
  /* ROUND 6 #1 — titre 100% FLEX : police en cqw (% de la largeur du conteneur
     .site-title, cf. container-type plus bas) → GROSSIT/rétrécit avec la fenêtre,
     SANS plafond. L'emoji scale aussi (cqw) → la part du .accent reste constante
     → le texte remplit le cadre au même taux à TOUTE largeur. Padding en `em` →
     le cadre grossit avec la police. Plus de justify (jamais d'espaces entre mots). */
  .site-title .accent {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    font-size: 6.05cqw !important;           /* tuné navigateur : remplit ~96% du cadre à 320→760px, jamais de débord */
    text-align: center !important;
    text-align-last: auto !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    letter-spacing: -0.015em !important;
    line-height: 1.0 !important;
    padding: 0.2em 0.34em 0.26em 0.42em !important;   /* cadre resserré (marges réduites, surtout en vertical) */
  }
  /* .site-title = conteneur de requête : la largeur sert de base aux cqw. */
  .site-title { container-type: inline-size !important; }
  .site-title .site-emoji {
    font-size: 9cqw !important;              /* scale avec le titre → ratio cadre constant */
    margin-right: -0.22em !important;
    z-index: 3 !important;
    transform: rotate(-8deg) translateY(0.04em) !important;
    flex: 0 0 auto !important;
  }

  /* ── #3 · Anti-troncature + le titre au Z MINIMUM ────────────────────────
     Le header ne clippe rien, ET il est posé au z le plus bas (0) → TOUT le
     hero (carte, stats, bumpers de score, bouton Passer…) se rend PAR-DESSUS
     le titre en cas de recouvrement. Le header reste un stacking context (z:0,
     pas négatif → ne passe pas sous le fond) pour contenir l'emoji (z:3) sans
     qu'il s'échappe. .right-col (z:1) et .card-stack (z:5) sont déjà > 0. */
  .header { z-index: 0 !important; }
  .header, .site-title { overflow: visible !important; }
  .card-stack, .controls-panel { z-index: 5 !important; }
  /* (retour user 2026-06-18) BUG « bouton d'indice quasi incliquable » : .card-stack à z:5
     crée un stacking-context qui PIÈGE le bouton d'indice (#hint-postit-wrap z:60, son enfant) ;
     comme l'hémicycle vit dans .right-col et se peint au-dessus du sous-arbre card-stack, il
     intercepte les taps sur tout le bouton qui le chevauche → seule une fine frange au-dessus de
     l'hémicycle répondait. On REMET .card-stack en z:auto (intention d'origine ligne 945, écrasée
     ici) → le bouton d'indice (z:60) s'évalue au niveau racine et passe AU-DESSUS de l'hémicycle
     (cliquable à 100 %, même abaissé). La carte passe toujours par-dessus le titre via #game
     (z:1) > .header (z:0), donc card-stack n'a pas besoin de z:5 pour ça. */
  .card-stack { z-index: auto !important; }

  /* Marge HAUTE titre → contenu (le `gap` du flex `.app`) : RESPONSIVE — rétrécit
     sur écran court (vh) entre 9 et 18px. C'est la « marge supérieure » du play-area. */
  .app { gap: clamp(9px, 2.2vh, 18px) !important; }

  /* ── #2 · Carte et stack stats = MÊME boîte visible (alignées par CSS calc) ──────
     LAYOUT DÉTERMINISTE (plus de mesure JS = plus de jumps). Le SVG carte contient
     du vide transparent en haut/bas, variable par rôle → exposé en fractions par
     v3-adapter (--frame-top-frac / -h / -bot, sur .main#game au rendu). On aligne le
     HAUT VISIBLE de la carte (= card-stack + topFrac×H) avec le HAUT des stats, tous
     deux à --play-gap sous le haut de rangée. Tout en calc(), zéro mesure par frame. */
  .main#game {
    grid-template-columns: auto 1fr !important; column-gap: 12px !important;
    /* hauteur de la boîte carte. Le 80vw borne en portrait normal (inchangé) ; le
       40vh (abaissé de 44 → le héros rétrécit PLUS sur écran court) ne borne que sur
       écran court → l'hémicycle récupère cette place et le rapport héros/hémicycle se
       rapproche du moitié-moitié quand tout rétrécit. (#1) */
    --card-h: min(80vw, 40vh);
    --play-gap: 6px;                    /* air entre le haut de rangée et le contenu visible */
    /* défauts si la carte n'est pas encore rendue. Fractions CANONIQUES (cadres
       centrés verticalement par card-frames.js → ces valeurs sont constantes
       pour TOUS les rôles → plus de jump hémicycle/stats au changement de carte). */
    --frame-top-frac: 0.083; --frame-h-frac: 0.834; --frame-bot-frac: 0.083;
  }
  .card-stack {
    position: relative !important;          /* ancre le bouton Passer en overlay */
    height: var(--card-h) !important;
    aspect-ratio: 2 / 3 !important;
    width: auto !important;
    align-self: start !important;
    justify-self: start !important;
    /* remonte la carte du vide transparent → le HAUT VISIBLE du cadre arrive à
       --play-gap sous le haut de rangée (déterministe, pas d'anim → pas de jump). */
    margin-top: calc(var(--play-gap) - var(--frame-top-frac) * var(--card-h)) !important;
    transition-property: transform, box-shadow, filter !important;   /* la MARGE ne transitionne pas */
  }
  .controls-panel {
    /* Haut des stats à --play-gap (= haut visible de la carte, toujours, car la
       carte est remontée de topFrac×H → son cadre arrive à --play-gap quel que soit
       le rôle). Hauteur CONSTANTE (fraction fixe, pas var(--frame-h-frac)) → les
       stats NE se redimensionnent PAS d'une carte à l'autre (plus de « grossit /
       rétrécit »). Les chiffres, fittés à cette hauteur stable, ne sautent plus. */
    margin-top: var(--play-gap) !important;
    height: calc(0.84 * var(--card-h)) !important;
    align-self: start !important;
    width: auto !important;
    display: flex !important; flex-direction: column !important;
  }

  /* ── #2 · Bouton « Passer » : sticker perché dans le coin HAUT-GAUCHE, débordant
     un peu du cadre (plus haut/plus dans le coin). Léger sway néo-brut comme le
     post-it Indice (rotate animé), désynchronisé (durée + phase différentes). ── */
  .skip-rp {
    position: absolute !important;
    /* (B9 2026-06-18) DÉPLACÉ en BAS-DROITE (la fiche dossier prend le haut-gauche).
       Chevauche le BAS du cadre visible (botFrac×H), symétrique de l'ancien top. */
    bottom: calc(var(--frame-bot-frac) * var(--card-h) - 8px) !important;
    right: 0px !important; left: auto !important; top: auto !important;
    z-index: 62 !important;
    /* (retour user 2026-06-19) Le bouton « Passer » paraissait TROP GROS vs les boutons
       Indices voisins : police 11,5→9,5px pour le rapprocher de leur taille (indices à
       10px). NB : padding/gap NE se règlent PAS ici — le bloc de BASE (placé après les
       @media) les écrase ; la boîte est resserrée là-bas. */
    font-size: 9.5px !important;
    padding: 5px 10px 5px 8px !important;
    gap: 5px !important;
    /* tilt sticker au repos. PAS de !important : sinon il l'emporte sur l'animation
       (les déclarations !important auteur battent les animations dans la cascade) →
       le sway resterait figé. Sans !important, skipSway anime bien le rotate ;
       reduce-motion (animation:none) retombe sur ce tilt statique. */
    rotate: -5deg;
    animation: skipSway 4.1s ease-in-out infinite !important;
  }
  .skip-rp .skip-ico { width: 14px !important; height: 14px !important; }
  /* Contour du drapeau aminci (4→3) + ombre allégée (5→3 au repos) → moins « lourd ». */
  .skip-rp .skip-frame path { stroke-width: 3 !important; }
  .skip-rp .skip-frame { filter: drop-shadow(3px 3px 0 var(--ink)) !important; }
  /* Compteur d'utilisations resserré (carré noir plus discret). */
  .skip-rp .skip-count { font-size: .78em !important; padding: 1px 4px !important; }

  /* ── #8 · Mentions (Points/Série/Précision) + icône : alignées à GAUCHE,
     police HEADING (Archivo Black), un peu plus grosses, interlignes resserrés. ── */
  /* #b · légère SUPERPOSITION des cartes : gap nul + chevauchement négatif. La
     carte du HAUT passe au-dessus de la MILIEU, la MILIEU au-dessus de la BAS
     (z décroissant). nth-child : 1=Points, 2=Série, 3=Précision (la carte Vies
     est cachée, nth-child 4). */
  .controls-panel .stats-compact { gap: 0 !important; }
  .controls-panel .stats-compact .stat-card:nth-child(2),
  .controls-panel .stats-compact .stat-card:nth-child(3),
  .controls-panel .stats-compact .stat-card:nth-child(4) { margin-top: -5px !important; padding-top: 13px !important; }
  .controls-panel .stats-compact .stat-card:nth-child(1) { z-index: 3 !important; }
  .controls-panel .stats-compact .stat-card:nth-child(2) { z-index: 2 !important; }
  .controls-panel .stats-compact .stat-card:nth-child(3) { z-index: 1 !important; }
  .controls-panel .stats-compact .stat-card:nth-child(4) { z-index: 0 !important; }
  .controls-panel .stats-compact .stat-card {
    flex: 1 1 0 !important; min-height: 0 !important;
    display: flex !important; flex-direction: column !important;
    justify-content: flex-start !important;  /* head haut · chiffre flex:1 remplit · sub bas */
    align-items: stretch !important;
    gap: 0 !important;
    padding: 7px !important;                  /* marges haut/bas HARMONISÉES avec gauche/droite */
    overflow: visible !important;
    position: relative !important;            /* pour que z-index s'applique */
    container-type: size !important;          /* #3 : base cqh pour head + sub flex */
  }
  /* Le padding-top de 9px (≥ overlap 6) suffit à dégager le label des cartes
     recouvertes → plus besoin de padding-top spécifique. */
  .controls-panel .stat-head {
    flex: 0 0 auto !important;                /* taille fixe en haut ; le chiffre prend le reste */
    display: flex !important;
    flex-direction: row !important;          /* icône + label, alignés à GAUCHE */
    justify-content: flex-start !important;
    align-items: center !important;
    gap: 4px !important;
    font-family: var(--font-heading, 'Archivo Black'), sans-serif !important;
    /* #3 : label FLEX (cqh), plus gros qu'à l'origine mais borné pour tenir sur
       1 ligne sans déborder « PRÉCISION » ni passer trop sous le badge ×2. */
    font-size: clamp(11px, 18cqh, 14px) !important;
    letter-spacing: -0.02em !important;
    line-height: 1.0 !important;
    text-transform: uppercase !important;
    white-space: nowrap !important;
    overflow: hidden !important;             /* garde-fou : ne déborde jamais la carte */
  }
  /* La carte Points porte le badge combo ×N (coin haut-droit) → on réserve sa
     place pour que « POINTS » + icône ne passent pas dessous. */
  .controls-panel .stat-card[data-tone="points"] .stat-head { padding-right: 18px !important; }
  /* #4 : icône en `em` → elle GROSSIT avec la police du label (et compte dans la
     mesure du fit JS). 1.1em ≈ hauteur d'une majuscule du label. */
  .controls-panel .stat-head .ico,
  .controls-panel .stat-card[data-tone="points"] .stat-head .ico {
    background: none !important; border-radius: 0 !important;
    width: 1.1em !important; height: 1.1em !important; color: currentColor !important; flex: 0 0 auto !important;
  }
  .controls-panel .stat-head .ico svg { width: 100% !important; height: 100% !important; }

  /* ── #7 · CHIFFRE modulaire : remplit la carte quel que soit le nombre de
     chiffres. Base grosse + neutralisation des bornes par-tone des rounds
     précédents → le fit JS (fitStatNums(), inline !important) affine pour ne
     jamais déborder ni paraître ridicule à 1 chiffre. ───────────────────────── */
  .controls-panel .stats-compact .stat-num,
  .stat-card[data-tone="acc"] .stat-num,
  .stat-card[data-tone="points"] .stat-num {
    /* #d : composant FLEX qui REMPLIT la hauteur dispo entre head et sub. La
       taille réelle est posée inline !important par fitStatNums() (mesure le
       texte → la + grande police qui tient en HAUTEUR ET en LARGEUR selon le
       nombre de chiffres). Base ci-dessous = fallback avant le JS. */
    flex: 1 1 0 !important; min-height: 0 !important;
    display: flex !important; align-items: center !important;
    font-size: 40px !important;             /* fallback ; fitStatNums pose un inline !important */
    line-height: 0.85 !important;
    white-space: nowrap !important;
    margin: 0 !important;
    text-align: left !important;
    overflow: hidden !important;            /* garde-fou : le chiffre ne masque jamais head/sub */
  }
  .stat-card[data-tone="acc"] .stat-num > span:last-child { font-size: 0.5em !important; }
  .controls-panel .stats-compact .stat-sub,
  .controls-panel .stats-compact .stat-sub-acc {
    flex: 0 0 auto !important;
    /* #3 : sous-texte FLEX aussi (cqh), un peu plus gros qu'à l'origine (9px),
       mais sur 1 SEULE ligne (nowrap + clip) → « MEILLEURE : 9 » ne wrappe plus. */
    font-size: clamp(9px, 14cqh, 11px) !important;
    line-height: 1.05 !important; margin: 0 !important;
    text-align: left !important;
    white-space: nowrap !important;
    overflow: hidden !important;
  }
  /* La valeur inline des sous-textes (Record/Meilleure) et les chiffres
     bonnes/mauvaises SCALENT avec le sous-texte (em) → ils grossissent avec lui
     au lieu de rester à une taille fixe. 1.15em = légèrement emphasé. */
  .controls-panel .stats-compact .stat-sub:not(.stat-sub-acc) span { font-size: 1.08em !important; }
  .controls-panel .stats-compact .stat-sub-acc .acc-good,
  .controls-panel .stats-compact .stat-sub-acc .acc-bad,
  .controls-panel .stats-compact .stat-sub-acc .acc-sep { font-size: 1.08em !important; }
  /* Icônes check/croix ENCADRÉES (data-icon check-box/cross-box) + léger tilt,
     en em → scalent avec le sous-texte. */
  .controls-panel .stats-compact .stat-sub-acc .ico { width: 1.25em !important; height: 1.25em !important; }
  .controls-panel .stats-compact .stat-sub-acc .ico svg { width: 100% !important; height: 100% !important; }
  .controls-panel .stats-compact .stat-sub-acc .acc-good .ico { transform: rotate(-7deg) !important; }
  .controls-panel .stats-compact .stat-sub-acc .acc-bad  .ico { transform: rotate(6deg) !important; }

  /* ── #4 · HÉMICYCLE RECENTRÉ ──────────────────────────────────────────────
     Cause du décalage R5 : #hemi-slot (≈416px) plus large que son conteneur
     (≈330px) avec margin:0 auto → les marges auto se résolvent à 0 (CSS ne
     distribue pas d'espace négatif) → le slot se cale à GAUCHE et déborde de
     ~86px à DROITE (tronqué). Fix : conteneur FLEX justify-content:center →
     l'item trop large déborde SYMÉTRIQUEMENT ; l'arc (plus étroit que le slot)
     reste alors entièrement visible et centré sur le viewport. */
  .game-panel {
    grid-column: 1 / -1 !important;
    align-self: end !important;             /* hémicycle calé en bas de sa rangée → la CTA le lèche (#6) */
    display: flex !important; flex-direction: column !important;
    align-items: stretch !important; justify-content: flex-end !important;
  }
  #hemicycle-container {
    display: flex !important;
    align-items: flex-start !important;
    justify-content: center !important;     /* CENTRE l'hémicycle sur le viewport */
    width: 100% !important;
  }
  #hemi-slot {
    margin: 0 !important;                    /* plus de margin:auto (inopérant en débord) */
    flex: 0 0 auto !important;
    /* + grand pour combler le vide (cap % large mais arc non rogné : ~12px de
       marge latérale) ; le terme vh fait RÉTRÉCIR l'hémicycle sur écran court
       (#5) avant tout chevauchement. */
    width: min(132%, calc(44vh * 400 / 195)) !important;
    height: auto !important;
    aspect-ratio: 400 / 195 !important;
    overflow: hidden !important;
  }

  /* ── #6 · CTA sous l'hémicycle + plus d'air sous la CTA (ne se fait plus manger
     par la navbar). Le padding-bottom remonte la grille → gap CTA↔navbar plus
     grand ; MARGINS (app.js) est augmenté du même montant pour garder l'overlap. */
  .gm-cta-row { margin-top: 6px !important; margin-bottom: 6px !important; }
  /* Marge BASSE contenu → navbar : RESPONSIVE (vh) — la « marge inférieure » du play-area. */
  .main#game { padding-bottom: clamp(10px, 2.4vh, 18px) !important; }
}

/* Sway du bouton « Passer » (sticker coin haut-gauche). Oscille le `rotate`
   autour de son tilt de repos (-5deg), comme le post-it Indice mais désynchronisé. */
@keyframes skipSway {
  0%, 100% { rotate: -6.5deg; }
  50%      { rotate: -3.5deg; }
}
/* Respecte les préférences de mouvement réduit (cohérent avec les post-its). */
html.reduce-motion .skip-rp,
html.anim-reduced .skip-rp { animation: none !important; }


/* ════════════════════════════════════════════════════════════════════════════
   ROUND 7 — retours user (2026-06-02). MOBILE. Dernier bloc max-width:760px =
   priorité cascade (le bloc ≤310px qui suit reste plus spécifique pour ce range).
   #10 · le hero atteint son ratio privilégié (≈ 2/3 photo) quand l'hémicycle est
   à sa taille max. #11 · plus de gap qui gonfle entre hero et hémicycle : gap
   CONSTANT plafonné, et l'espace EXCÉDENTAIRE va EN HAUT (au-dessus du titre,
   zone notch) au lieu de s'accumuler au milieu.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width: 0px) {
  /* #11 · La rangée centrale n'est plus 1fr (elle absorbait tout le slack →
     gap géant au-dessus de l'hémicycle). Les 3 rangées sont dimensionnées au
     CONTENU (auto), séparées par un row-gap CONSTANT plafonné (≈ le spacing
     d'ailleurs). min-height retiré : le main ne fait JAMAIS plus haut que son
     contenu → sur écran haut il est plus court que le viewport et le slack
     remonte (cf. .app flex-end ci-dessous) ; jamais plus haut qu'avant donc
     aucun nouveau débord sur écran court. */
  .main#game {
    grid-template-rows: auto auto auto !important;
    row-gap: clamp(8px, 1.8vh, 16px) !important;
    min-height: 0 !important;
    /* .main legacy = flex:1 → il remplissait .app et absorbait tout le slack
       (vide massé sous la CTA). flex-grow:0 → le main fait la hauteur de son
       CONTENU ; le slack restant dans .app est alors repoussé EN HAUT par
       justify-content:flex-end (au-dessus du titre, #11). */
    flex: 0 0 auto !important;
    align-content: start !important;
    /* #10 · plafond vertical du hero relevé (40 → 43vh) : sur écran haut la carte
       grandit (sa largeur = card-h × 2/3 suit) → la photo s'approche des 2/3 de la
       largeur et les stats du 1/3, au lieu de rester petites avec un vide qui gonfle. */
    --card-h: min(86vw, 43vh) !important;
  }
  /* L'hémicycle suit le hero avec le row-gap constant (plus de calage en bas
     d'une rangée 1fr). */
  .game-panel {
    align-self: start !important;
    justify-content: flex-start !important;
  }
  /* #11 · Espace excédentaire (écran haut) repoussé AU-DESSUS DU TITRE (zone
     notch) : le bloc header+main s'aligne en bas de .app, le vide apparaît en
     haut. `safe` → si le contenu DÉPASSE la hauteur (écran court, ou desktop bas
     en mode « téléphone partout »), l'alignement retombe sur start : le TITRE
     reste visible en haut (jamais rogné). Scopé au jeu (#game). */
  .app:has(.main#game) { justify-content: safe flex-end !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   #4 (user) · 2e MISE EN PAGE — écran TRÈS étroit (≤ 310px). Le 2-colonnes
   (photo | stats) rend les stat-cards « allongées » et illisibles. On bascule en
   MONO-COLONNE : photo en haut (réduite, centrée) puis les 3 stats EN BANDES
   pleine largeur (label · gros chiffre · sous-texte EN LIGNE) → bien plus lisible.
   La synchro de hauteur JS est désactivée à cette largeur (cf. syncStatsToCardFrame).
   ════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 310px) {
  /* Le jeu est verrouillé au viewport (pas de scroll) ; en mono-colonne le
     contenu empilé dépasse → on libère la hauteur et on autorise le défilement
     vertical (la navbar reste fixe en bas). */
  html, body { overflow-y: auto !important; height: auto !important; min-height: 100% !important; }
  .app { height: auto !important; min-height: 100dvh !important; overflow: visible !important; }
  .main#game {
    grid-template-columns: 1fr !important;
    grid-template-rows: auto !important;          /* rangées dimensionnées au CONTENU (plus de distribution fixe) */
    column-gap: 0 !important; row-gap: 10px !important;
    height: auto !important; min-height: 0 !important;
    overflow: visible !important;
    padding-bottom: 92px !important;               /* dégage la navbar fixe */
    --card-h: min(84vw, 315px);                    /* photo 56vw (max 210) × aspect 3/2 → cale Passer/Indice */
  }

  /* Empilement explicite (card-stack & controls-panel étaient TOUS DEUX en row 1,
     côte à côte ; en mono-colonne ils se superposeraient). On force l'ordre. */
  .card-stack    { grid-column: 1 !important; grid-row: 1 !important; }
  .controls-panel{ grid-column: 1 !important; grid-row: 2 !important; }
  .game-panel    { grid-column: 1 !important; grid-row: 3 !important;
                   align-self: start !important; height: auto !important; min-height: 0 !important;
                   justify-content: flex-start !important; }  /* plus de débord vers le haut (overlap du mode hero) */
  .gm-cta-row    { grid-column: 1 !important; grid-row: 4 !important; margin-top: 4px !important; }

  .card-stack {
    margin-top: 0 !important;
    height: auto !important;
    width: 56vw !important; max-width: 210px !important;
    aspect-ratio: 2 / 3 !important;
    justify-self: center !important;
  }
  .controls-panel {
    margin-top: 0 !important; height: auto !important;
    width: 100% !important;
    display: flex !important; flex-direction: column !important;
  }
  /* Stats empilées, chacune en BANDE horizontale pleine largeur. */
  .controls-panel .stats-compact { display: flex !important; flex-direction: column !important; gap: 9px !important; }
  .controls-panel .stats-compact .stat-card {
    width: 100% !important;
    flex-direction: row !important; align-items: center !important;
    justify-content: flex-start !important;
    gap: 12px !important;
    margin-top: 0 !important; padding: 8px 14px !important;
    height: auto !important; min-height: 54px !important;
    container-type: normal !important;       /* annule le container-query vertical du mode carte */
  }
  /* recouvrement vertical du stack carte → neutralisé en bandes */
  .controls-panel .stats-compact .stat-card:nth-child(2),
  .controls-panel .stats-compact .stat-card:nth-child(3),
  .controls-panel .stats-compact .stat-card:nth-child(4) { margin-top: 0 !important; padding-top: 8px !important; }
  .controls-panel .stats-compact .stat-card .stat-head {
    flex: 0 0 auto !important; width: 92px !important;
    justify-content: flex-start !important; white-space: nowrap !important;
  }
  .controls-panel .stats-compact .stat-card .stat-num {
    flex: 0 0 auto !important; width: auto !important;
    line-height: 1 !important; justify-content: flex-start !important;
  }
  .controls-panel .stats-compact .stat-card .stat-sub,
  .controls-panel .stats-compact .stat-card .stat-sub-acc {
    flex: 1 1 auto !important; justify-content: flex-end !important; text-align: right !important;
  }
}


/* ════════════════════════════════════════════════════════════════════════════
   #6 (retour user) · ÉLIMINATION ANIMÉE des secteurs d'hémicycle (≠ jump).
   hemicycle.js (animateElim) ajoute .hemi-elim-anim au <g.hemi-lift> du secteur
   visé et pose --elim-dx/--elim-dy (vecteur radial sortant, en unités viewBox).
   Le secteur SORT le long de son rayon puis REVIENT ; en parallèle sa couleur
   cross-fade vers le gris (transition inline posée par le JS). GLOBAL (hors media
   query) : vaut pour mobile ET desktop reconstruit. */
@keyframes hemiElimPop {
  0%   { transform: translate(0px, 0px) scale(1); }
  45%  { transform: translate(calc(var(--elim-dx, 0) * 1px), calc(var(--elim-dy, 0) * 1px)) scale(1.1); }
  100% { transform: translate(0px, 0px) scale(1); }
}
.hemi-lift.hemi-elim-anim {
  transform-box: fill-box;          /* scale centré sur le secteur (pop en place) */
  transform-origin: center;
  animation: hemiElimPop 500ms var(--ease-out, cubic-bezier(.2, .9, .3, 1.1));
}
html.reduce-motion .hemi-lift.hemi-elim-anim,
html.anim-reduced .hemi-lift.hemi-elim-anim { animation: none; }


/* ════════════════════════════════════════════════════════════════════════════
   #12 + ROUND 8 · LAYOUT VERTICAL SYSTÉMATISÉ — RÈGLES STRICTES (user 2026-06-02).
   ───────────────────────────────────────────────────────────────────────────
   UN SEUL jeu de règles, continu à TOUTE largeur (tous les blocs V3 sont en
   @media (min-width:0px) → pas de switch mobile↔desktop). On NE borne PAS en
   colonne « téléphone » (les éléments suivent les règles quand la fenêtre
   grandit ; le cas « rectangle horizontal » sera traité plus tard, en smooth).

   ESPACEMENTS : UNE seule constante --gap-const (px FIXE, jamais vh/vw/clamp) :
     • titre ↔ hero      = --gap-const   (gap de .app)                              [R3]
     • hero ↔ hémicycle   ≤ --gap-const   (row-gap = PLAFOND ; le recouvrement R6a   [R4]
                                          est géré par sizeHemicycle/HEMI_OVERLAP_MAX en JS)
     • hémicycle ↔ CTA    = --gap-const   (row-gap)                                  [R3]
     • CTA ↔ navbar       = --gap-const   (= .app padding-bottom − hauteur navbar)   [R3]
   SEUL l'espace HAUT-DE-L'ÉCRAN ↔ titre grandit (slack), via justify-content:
   safe flex-end ([R5] ; `safe` → titre jamais rogné sur écran court, [R1]).
   Navbar position:fixed bottom:0, JAMAIS bougée [R2].

   Le DIMENSIONNEMENT + placement vertical de l'hémicycle et les hauteurs de
   .card-stack/.controls-panel restent pilotés par le JS (sizeHemicycle,
   syncStatsToCardFrame, alignCardToStats — inline !important) → on NE les touche
   PAS ici (sinon oscillation/écrasement). [R6] (overlap→shrink) vit dans le JS.
   COHÉRENCE : app.js MARGINS = 2×--gap-const (hémi↔CTA + CTA↔navbar) pour que
   l'arc se pose pile au-dessus de la CTA → réglé à 24 (cf. sizeHemicycle).
   ════════════════════════════════════════════════════════════════════════════ */
:root { --gap-const: 12px; --navbar-h: 84px; }

@media (min-width: 0px) {
  /* [R3] titre↔hero = gap CONSTANT · [R5] surplus vertical EN HAUT · [R2] réserve navbar
     (gap CTA↔navbar = padding-bottom − hauteur navbar = --gap-const). */
  .app:has(#game) {
    gap: var(--gap-const) !important;
    justify-content: safe flex-end !important;
    padding-bottom: calc(var(--navbar-h) + var(--gap-const) + env(safe-area-inset-bottom, 0px)) !important;
  }
  /* main = hauteur du CONTENU (flex:0 0 auto) → le slack remonte en haut [R5]. Pas de
     padding-bottom (le gap CTA↔navbar vient de .app). 3 rangées auto (jamais 1fr).
     row-gap:0 → les gaps verticaux sont portés par des MARGINS explicites (ci-dessous)
     pour pouvoir traiter le gap hero↔hémi différemment (dynamique) des autres (fixes). */
  .main#game {
    grid-template-rows: auto auto auto !important;
    row-gap: 0 !important;
    padding-bottom: 0 !important;
    min-height: 0 !important;
    flex: 0 0 auto !important;
    align-content: start !important;
  }
  /* [R3] hémicycle↔CTA = gap CONSTANT. */
  .gm-cta-row { margin-top: var(--gap-const) !important; margin-bottom: 0 !important; }
  /* [R4]/[R6a] hero↔hémicycle = gap DYNAMIQUE piloté par sizeHemicycle (JS) :
     plafonné à --gap-const ([R4]) ; descend en NÉGATIF = recouvrement ([R6a]) sur
     écran court (margin-top négatif d'un item grid → recouvre row1 ET récupère
     l'espace, donc la CTA remonte). Fallback = --gap-const avant le 1er passage JS.
     (Le JS pose un margin-top inline !important qui prime.) */
  .game-panel { margin-top: var(--gap-const) !important; }
  /* [R1] Le conteneur hémicycle NE doit PAS imposer d'aspect-ratio : le legacy
     pose `.hemicycle-wrap{aspect-ratio:2/1}` (style.css) → sur fenêtre large il
     devenait géant (1104px → 552px de haut) et poussait la CTA hors écran. On
     l'annule à TOUTE largeur : le conteneur épouse la hauteur du #hemi-slot
     (dont la largeur est posée par le JS, hauteur via aspect 400/195). */
  #hemicycle-container {
    aspect-ratio: auto !important;
    height: auto !important;
  }
  /* Titre de panneau legacy (« Quel est son groupe ? ») masqué à TOUTE largeur
     (le V3 ne l'utilise pas ; il ne réapparaissait que >760 = ancien switch). */
  .panel-title { display: none !important; }
  /* [R2] navbar épinglée en bas, JAMAIS bougée (scope #game → autres pages intactes). */
  body:has(#game) .mobile-footer-nav.is-fixed {
    position: fixed !important;
    bottom: 0 !important; left: 0 !important; right: 0 !important;
    width: auto !important; margin: 0 !important;
  }
}


/* ════════════════════════════════════════════════════════════════════════════
   STAT-CARDS · LAYOUT ALTERNATIF « ALLONGÉ » (≥ 2.5:1) — demande user.
   ───────────────────────────────────────────────────────────────────────────
   Le layout par défaut (label / gros chiffre / sous-texte EMPILÉS) est parfait
   quand la carte est carrée/légèrement rectangulaire, mais laisse un grand vide
   à droite quand elle s'allonge (écran large). app.js (tagElongatedStats) pose
   .stat-elongated quand largeur/hauteur ≥ 2.5 → on bascule en GRILLE 2 colonnes :
   le label + le sous-texte à GAUCHE, le GROS CHIFFRE dans sa PROPRE colonne à
   DROITE (il remplit alors l'espace). Le chiffre est dimensionné par fitStatNums
   (qui mesure sa nouvelle boîte) → pas de taille en dur ici. Class-based (pas de
   media query) → s'applique à toute largeur dès que la carte est trop allongée. */
/* Garde-fou : une carte CACHÉE le reste, même si elle porte .stat-elongated. */
.controls-panel .stats-compact .stat-card.stat-elongated.hidden,
.controls-panel .stats-compact .stat-card.stat-elongated[hidden] { display: none !important; }
.controls-panel .stats-compact .stat-card.stat-elongated {
  display: grid !important;
  /* La statcard est DIVISÉE EN DEUX (demande user) : moitié gauche = label+sub,
     moitié droite = chiffre. minmax(0,1fr) → 50/50 STRICT, jamais écrasé par le
     min-content du label → la colonne chiffre fait toujours exactement sa moitié
     et le chiffre (auto-fité par fitStatNums sur cette boîte) ne déborde jamais. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) !important;
  grid-template-rows: 1fr 1fr !important;
  grid-template-areas: "head num" "sub num" !important;
  align-items: center !important;
  column-gap: 14px !important;
}
.stat-card.stat-elongated .stat-head { grid-area: head !important; align-self: end !important; min-width: 0 !important; }
.stat-card.stat-elongated .stat-sub,
.stat-card.stat-elongated .stat-sub-acc { grid-area: sub !important; align-self: start !important; min-width: 0 !important; }
.stat-card.stat-elongated .stat-num {
  grid-area: num !important;
  align-self: stretch !important;       /* boîte = PLEINE hauteur de la carte → fitStatNums remplit le chiffre GROS */
  justify-self: stretch !important;
  display: flex !important;
  align-items: center !important;
  justify-content: flex-end !important; /* chiffre calé à droite (scoreboard) */
  padding-right: 6px !important;        /* dégagement bord / badge combo */
}


/* ════════════════════════════════════════════════════════════════════════════
   #5 (retour user) · HOVER UNIFIÉ des post-its (Indice / Passer / Retour).
   ───────────────────────────────────────────────────────────────────────────
   Ils doivent réagir EXACTEMENT comme les CTA « Nouvelle partie »/« Modes » :
   se SOULÈVENT de 2px, se REDRESSENT (rotate 0), ombre --sh-hover. On fige le
   sway (rotate:0/scale:1 en !important priment sur l'animation) et on neutralise
   tout transform de hover hérité (skip-rp avait transform translate+rotate). */
html.dlp-can-hover .hint-postit-wrap:has(.hint-postit:hover),
html.dlp-can-hover .skip-rp:hover,
html.dlp-can-hover .hemicycle-back:hover {
  transform: none !important;
  rotate: 0deg !important;
  scale: 1 !important;
  translate: -2px -2px !important;
  box-shadow: var(--sh-hover) !important;
  transition: transform 160ms var(--ease-out), rotate 160ms var(--ease-out),
              scale 160ms var(--ease-out), translate 160ms var(--ease-out),
              box-shadow 160ms ease !important;
}

/* ════════════════════════════════════════════════════════════════════════════
   BOUTON « PASSER » — drapeau néo-brut à POINTE GAUCHE (retour user 2026-06-18)
   ───────────────────────────────────────────────────────────────────────────
   Le CONTOUR doit épouser EXACTEMENT la flèche (y compris la pointe) → on dessine
   le drapeau en SVG avec un `stroke` non-scaling 4px (un border CSS / box-shadow
   inset ne suit pas la diagonale de la pointe). Libellé « PASSER » + compteur dans
   un CARRÉ NOIR (coins DROITS). Ombre dure décalée via `filter:drop-shadow` sur le
   SVG (suit le drapeau). Plus d'icône ≫. Placé APRÈS les @media skip → gagne. */
.skip-rp {
  position: relative;
  display: inline-flex !important;
  align-items: center;
  gap: 5px !important;                             /* (retour user 2026-06-19) resserré (était 7px) */
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  filter: none !important;
  padding: 8px 11px 8px 18px !important;          /* (retour user 2026-06-19) resserré vs indices, hauteur remontée ; gauche = pointe du drapeau */
  color: var(--ink) !important;
  overflow: visible !important;
}
/* Drapeau SVG : remplit le bouton, stroke 4px constant qui trace la flèche. */
.skip-rp .skip-frame {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0; overflow: visible; pointer-events: none;
  filter: drop-shadow(5px 5px 0 var(--ink));      /* ombre dure décalée, suit le drapeau */
}
.skip-rp .skip-frame path {
  fill: var(--paper);
  stroke: var(--ink);
  stroke-width: 4;
  vector-effect: non-scaling-stroke;              /* 4px constant = épaisseur des contours */
  stroke-linejoin: miter;
}
.skip-rp .skip-lbl,
.skip-rp .skip-count { position: relative; z-index: 1; }   /* au-dessus du SVG */
.skip-rp .skip-lbl {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1;
}
.skip-rp .skip-count {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--paper);
  font-family: var(--font-display);
  font-size: .82em; line-height: 1;
  padding: 3px 5px 2px;
  border-radius: 0;                               /* CARRÉ — coins droits (retour user) */
  letter-spacing: .01em;
}
.skip-rp.skip-out { opacity: .5; }                /* 0 passe : grisé */
/* Hover : pas d'ombre rectangulaire (le hover unifié posait box-shadow sur la
   boîte) ; on grossit l'ombre du DRAPEAU. Le lift (translate −2px) reste hérité. */
html.dlp-can-hover .skip-rp:hover { box-shadow: none !important; }
/* !important : l'ombre au repos est désormais posée en !important (ROUND 6) → le hover
   doit l'être aussi pour la grossir (3→5px). Spécificité supérieure → gagne au survol. */
html.dlp-can-hover .skip-rp:hover .skip-frame { filter: drop-shadow(5px 5px 0 var(--ink)) !important; }

/* #5b (retour user) · Hover COHÉRENT pour la NAVBAR (footer) et le bouton RATIOS :
   l'ombre s'écarte comme sur tous les autres boutons néo-brut (lift −2px + ombre
   agrandie). Avant : la navbar n'avait qu'un :active, et Ratios aucun hover. */
html.dlp-can-hover .mobile-nav-btn {
  transition: transform 140ms var(--ease-out), box-shadow 140ms var(--ease-out) !important;
}
html.dlp-can-hover .mobile-nav-btn:hover {
  transform: translate(-2px, -2px) rotate(0deg) !important;   /* se redresse + se soulève */
  box-shadow: var(--sh-hover) !important;
}
/* Ratios : conteneur transparent → l'ombre est un drop-shadow filtre sur .pct-seg.
   On l'écarte (3→6px) + petit lift via `translate` (compose avec le sway en `rotate`). */
html.dlp-can-hover .pct-postit { transition: translate 140ms var(--ease-out) !important; }
html.dlp-can-hover .pct-postit:hover { translate: -2px -2px !important; }
html.dlp-can-hover .pct-postit .pct-seg { transition: filter 140ms var(--ease-out) !important; }
html.dlp-can-hover .pct-postit:hover .pct-seg { filter: drop-shadow(6px 6px 0 var(--ink)) !important; }

/* #4 · Bouton Retour affiché (post-it inline-flex) quand un camp est armé, à TOUTE
   largeur (le show legacy n'était qu'en @media ≤760 → invisible au-delà avec le
   layout continu). Superposé au bas-droite de l'arc. */
.hemicycle-wrap.is-armed .hemicycle-back {
  display: inline-flex !important;
  opacity: 1 !important;
  pointer-events: auto !important;
  bottom: 22px !important;
  right: 10px !important;
}

/* #3 · Secteurs de l'hémicycle : repère de transform LOCAL → le `scale` de proximité
   (posé inline par proximity.js) part du centre du secteur (sinon il partirait de
   l'origine SVG 0,0 et déplacerait le secteur). */
#hemi-slot .hemi-macro,
#hemi-slot .hemi-sub {
  transform-box: fill-box;
  transform-origin: center;
  /* Le scale de proximité est appliqué par proximity.js APRÈS un court délai de
     re-collecte ; sans transition les NOUVEAUX secteurs (à l'ouverture d'un camp)
     sautaient de scale 1 → scale proximité (« rattrapage »). La transition lisse
     ce rattrapage (et les micro-variations au déplacement du curseur). */
  transition: scale 140ms ease;
}
/* Pendant l'animation d'arming (sectors qui churent chaque frame), pas de transition
   de scale (sinon flicker) : la transition ne sert qu'au repos. */
#hemi-slot svg.is-animating .hemi-macro,
#hemi-slot svg.is-animating .hemi-sub { transition: none; }


/* ════════════════════════════════════════════════════════════════════════════
   INDICE V3 — refonte (retour user). Avant : le bandeau grandissait EN HAUTEUR
   et couvrait la photo, et le bouton était trop large (grosses marges G/D).
   Désormais : bouton compact ; bandeau message LARGE (≈ largeur carte, pouvant
   DÉBORDER au-dessus des stat-cards) mais COURT (hauteur plafonnée → photo
   dégagée) ; une CROIX pour replier ; un CHEVRON pour ré-étendre sans repayer.
   ═══════════════════════════════════════════════════════════════════════════ */

/* — Bouton « Demander un indice » : texte PLUS GROS, marges resserrées. — */
/* Le bouton DOIT épouser son contenu (sinon il restait ~19px plus large que
   « DEMANDER » → grosses marges jaunes autour du texte). fit-content le colle au
   plus large enfant. */
/* Le legacy impose min-width:84px au bouton (style.css) → trop large pour
   « DEMANDER UN INDICE » (~71px). On le ramène à 72px (snug autour du texte).
   NB : pas de min-width:0 ni width:max-content ici — le bouton a overflow:hidden,
   ces valeurs le feraient s'effondrer à 0.
   IMPORTANT : seulement si le bouton n'est PAS `hint-out` — sinon ce min-width
   empêchait le bouton de se rétracter à 0 quand les indices sont épuisés → un
   carré jaune vide restait visible à côté de la languette chevron. */
.hint-postit-wrap .hint-postit { gap: 3px !important; }
.hint-postit-wrap .hint-postit:not(.hint-out) { min-width: 72px !important; }
/* Le message/séparateur vides (repliés sans indice) ne doivent pas réserver de
   largeur à droite du bouton → masqués tant qu'aucun indice n'est affiché. */
.hint-postit-wrap:not(.has-message) .hint-postit-message,
.hint-postit-wrap:not(.has-message) .hint-postit-sep { display: none !important; }
.hint-postit-wrap .hint-postit > .ico { width: 17px !important; height: 17px !important; }
.hint-postit-wrap .hint-postit .hint-line { font-size: 11px !important; letter-spacing: -0.01em !important; }
/* La pastille de coût ne doit PLUS imposer la largeur (align-self:stretch +
   min-content ~84px = grosses marges autour du texte). On la passe en largeur de
   CONTENU, centrée → le bouton se cale sur « DEMANDER / UN INDICE ». */
.hint-postit-wrap .hint-postit .cost {
  align-self: center !important;
  width: auto !important; min-width: 0 !important; max-width: none !important;
  white-space: nowrap !important;
  font-size: 9.5px !important; padding: 2px 6px !important;
}
.hint-postit-wrap:not(.has-message) { padding: 3px 4px !important; }

/* — Indice affiché : bandeau LARGE + COURT, au-dessus des stat-cards. — */
.hint-postit-wrap.has-message {
  padding: 5px 5px !important;
  min-height: 0 !important;
  height: 80px !important;             /* HAUTEUR FIXE : le legacy min-height:110 + align-self:stretch rendaient max-height inopérant */
  max-height: 80px !important;
  z-index: 250 !important;             /* au-dessus des stat-cards (z 200) */
}
.hint-postit-wrap.has-message .hint-postit-message {
  /* LARGEUR calculée : s'étend jusqu'au bord de l'écran (déborde sur les stats,
     bien au-delà du milieu de la carte Précision) sans pousser la croix hors champ.
     En flex un max-width ne suffit pas (le texte multi-ligne réduit à min-content). */
  /* PAS de !important sur max-width : sinon il prime sur l'animation (WAAPI/keyframes)
     et l'ouverture est instantanée. Notre sélecteur (chargé après style.css) gagne
     quand même la cascade. Le repli (.hint-collapsed) garde son !important → la
     transition interpole correctement 222→0. */
  max-width: min(calc(100vw - 168px), 262px);
  width: auto !important;
  justify-content: flex-start !important;  /* le span (largeur fixe) se révèle de gauche à droite */
  align-self: center !important;           /* centré vertical (pas stretch → hauteur fixe tient) */
  height: 68px !important; max-height: 68px !important; min-height: 0 !important;
  overflow: hidden !important;
  padding: 2px 14px 2px 8px !important;     /* marges resserrées (place croix à droite) */
  transition: max-width 300ms cubic-bezier(.22, .61, .36, 1),
              opacity 200ms ease !important;
}
/* Span interne : largeur FIXE → texte figé (pas de reflow pendant l'extension). */
.hint-postit-wrap .hint-msg-inner {
  display: inline-block; flex: 0 0 auto;
  text-align: center; white-space: normal; line-height: 1.2;
}
/* EXTENSION du bandeau (ouverture / ré-ouverture) : pilotée en JS via la Web
   Animations API (app.js → animateHintBandOpen) — une CSS @keyframes ne se
   re-déclenchait pas fiablement à la ré-ouverture (et sa présence supprimait la
   transition → ouverture instantanée). Le REPLI reste géré par la transition
   max-width ci-dessus (que le user apprécie). Le span interne figé = zéro reflow. */
/* Pour que le débord passe AU-DESSUS de la colonne stats (z 200), on remonte la
   card-stack pendant que l'indice est ouvert (et SEULEMENT à ce moment-là). */
.main#game:has(.hint-postit-wrap.has-message:not(.hint-collapsed)) .card-stack {
  z-index: 250 !important;
}

/* (B9 2026-06-18) ÉVITEMENT « Passer » ↔ bandeau d'indice. Le bandeau (ancré en
   bas, 80px de haut, z:250) recouvrirait le bouton « Passer » désormais en
   bas-droite. Quand il est déployé, « Passer » REMONTE au-dessus du bandeau et
   passe en z:251 (reste cliquable). translate sur `transform` = INDÉPENDANT du
   `rotate` (sway) → les deux composent sans conflit. Transition douce = il « se
   déplace » visiblement. Repli (.hint-collapsed) → il revient en place. */
.main#game:has(.hint-postit-wrap.has-message:not(.hint-collapsed)) .skip-rp {
  /* (retour user) NE PAS remonter beaucoup : -92px laissait un vide et masquait
     la photo. On garde « Passer » quasi en place et on le fait simplement passer
     AU-DESSUS du bandeau (z:251), avec un PETIT lift pour qu'il ne soit pas noyé.
     On lift via `margin-bottom` (le bouton est ancré `bottom` en absolu → la
     marge le remonte) plutôt que `transform` : ce dernier entrait en conflit avec
     l'animation `skipSway` (rotate) et n'était pas appliqué. Bandeau z:250 →
     « Passer » dessus, cliquable. */
  margin-bottom: 60px !important;       /* dégage le bandeau (≈84px, son haut ~82px au-dessus du bas carte) → « Passer » se cale JUSTE au-dessus, sans le recouvrir */
  z-index: 251 !important;
  transition: margin-bottom 240ms var(--ease-out, ease-out) !important;
}

/* — Croix (replier) + Chevron (rouvrir) : pastilles néo-brut, ancrées au wrap. — */
.hint-x, .hint-reopen {
  position: absolute; z-index: 3;
  display: none; align-items: center; justify-content: center;
  margin: 0; padding: 0; cursor: pointer; pointer-events: auto;
  border: 2px solid var(--ink);
  transition: transform 120ms var(--ease-out, ease-out), box-shadow 120ms var(--ease-out, ease-out);
}
.hint-x svg, .hint-reopen svg { fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
/* Croix : coin haut-droit du bandeau, visible UNIQUEMENT déployé. */
.hint-postit-wrap.has-message:not(.hint-collapsed) .hint-x {
  display: inline-flex; top: 3px; right: 5px;
  width: 19px; height: 19px; border-radius: 50%;
  background: var(--ink);
}
.hint-x svg { width: 11px; height: 11px; stroke: var(--paper); }
html.dlp-can-hover .hint-x:hover { transform: translate(-1px, -1px); box-shadow: 2px 2px 0 var(--ink); }

/* Repli : message + séparateur masqués ; le BOUTON reste VISIBLE et de taille
   INCHANGÉE (pas de redimensionnement au repli) ; un petit chevron apparaît à sa
   droite pour rouvrir le dernier indice. */
.hint-postit-wrap.hint-collapsed .hint-postit-message { max-width: 0 !important; opacity: 0 !important; padding: 0 !important; }
.hint-postit-wrap.hint-collapsed .hint-postit-sep { width: 0 !important; margin: 0 !important; opacity: 0 !important; }
.hint-postit-wrap.has-message.hint-collapsed { max-height: none !important; padding: 5px 5px !important; }
/* Indices ÉPUISÉS (bouton hint-out) + replié : plus de bouton à montrer → on
   neutralise la boîte jaune du wrap (sinon carré vide) ; seule la languette reste. */
.hint-postit-wrap.has-message.hint-collapsed:has(.hint-postit.hint-out) {
  background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important;
}
.hint-postit-wrap.has-message.hint-collapsed:has(.hint-postit.hint-out) .hint-reopen { left: 16px; right: auto; margin-left: 0; }
.hint-postit-wrap.has-message.hint-collapsed .hint-reopen {
  display: inline-flex;
  top: 50%; left: 100%; margin-left: 5px; transform: translateY(-50%);
  width: 22px; height: 30px; border-radius: 4px;
  background: var(--yellow); box-shadow: 2px 2px 0 var(--ink);
}
.hint-reopen svg { width: 13px; height: 16px; stroke: var(--ink); }
html.dlp-can-hover .hint-reopen:hover { transform: translateY(-50%) translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); }


/* ════════════════════════════════════════════════════════════════════════════
   DESKTOP / PAYSAGE — bascule 2 colonnes (user 2026-06-03).
   ───────────────────────────────────────────────────────────────────────────
   DÉCLENCHEUR : la fenêtre devient CARRÉE ou plus large que haute
   (min-aspect-ratio: 1/1) → on quitte l'empilement mobile et on passe à 2
   colonnes qui « continuent en flex » sur tout rectangle horizontal :
     • COLONNE GAUCHE : grande carte RP (le TITRE reste dans le .header, au-dessus
       de la colonne — rangée « ZONE TITRE | ZONE NAVBAR » = le header existant).
     • COLONNE DROITE : stat-cards À L'HORIZONTALE, puis hémicycle (remplit), puis
       CTA « Nouvelle partie / Modes ». La navbar = le .header (en haut à droite).
   Ce bloc est le DERNIER du fichier → en paysage il PRIME (à !important égal,
   source plus tardive) sur tous les blocs @media(min-width:0) « ROUND N ». On NE
   redéclare QUE ce qui change ; tout le reste (typo, post-its, indice, hover…)
   est hérité du mobile. sizeHemicycle()/positionRatiosButton() ont une branche
   desktop (app.js) qui dimensionne/centre l'arc depuis la COLONNE DROITE.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-aspect-ratio: 1/1) {

  /* ── .app : contenu aligné EN HAUT (titre/navbar puis colonnes), plus de
     réserve navbar (masquée en desktop). Sélecteur calqué sur ROUND7
     (.app:has(.main#game), spéc. (1,2,0)) pour battre son `safe flex-end`. ── */
  .app:has(.main#game) {
    justify-content: flex-start !important;
    gap: clamp(8px, 1.6vh, 16px) !important;
    padding-bottom: clamp(10px, 2vh, 22px) !important;
  }

  /* ── #game : grille 2 colonnes / 1 rangée, remplit la hauteur restante de .app ── */
  .main#game {
    display: grid !important;
    /* 2 colonnes de MÊME largeur (= largeur carte), CENTRÉES → colonne droite plus
       étroite (demande user), marges latérales équilibrées. */
    grid-template-columns: auto auto !important;
    grid-template-rows: auto !important;                     /* rangée = hauteur carte (pas tout le viewport) */
    column-gap: clamp(20px, 3vw, 56px) !important;
    row-gap: 0 !important;
    justify-content: center !important;                      /* centre les 2 colonnes */
    align-items: start !important;                           /* carte & colonne calées EN HAUT (sous le titre) */
    align-content: start !important;
    flex: 1 1 auto !important;            /* enfant flex de .app → prend la hauteur restante */
    min-height: 0 !important;
    overflow: visible !important;         /* sinon overflow-x:clip rogne Passer/Indice à gauche */
    padding: 0 0 clamp(8px, 1.6vh, 18px) !important;   /* .app porte déjà la marge latérale */
    /* La plus GRANDE carte 2:3 qui tient en hauteur (≤84vh) ET en largeur. La
       largeur est bornée par la LARGEUR DE CONTENU réelle (≈ .app, max 1124px)
       pondérée à 0.66 → la carte vise ~44% de la largeur, la colonne droite garde
       sa moitié même sur écran haut/large (sinon, passé max-width:1180, les vw
       débordent et la carte mange tout). Pas de mesure JS, pas de flash. */
    --card-h: min(84vh, min(1124px, 90vw) * 0.66) !important;
  }

  /* ── COLONNE GAUCHE : la carte, calée EN HAUT (sous le titre) ── */
  .card-stack {
    grid-column: 1 !important; grid-row: 1 !important;
    align-self: start !important; justify-self: center !important;
    height: var(--card-h) !important;
    aspect-ratio: 2 / 3 !important;
    width: auto !important; max-width: 100% !important;
    margin: 0 !important;                /* la carte remplit la rangée (centrée vis-à-vis du stack droit) */
  }
  /* Le wrapper du deck (js/card-deck.css) plafonne la carte à 340px → en desktop on
     le libère pour que la carte REMPLISSE le stack (hauteur = colonne droite, et
     Passer/Indice retombent alors pile sur les coins haut/bas de la carte). */
  #card-deck { max-width: none !important; width: 100% !important; }

  /* ── COLONNE DROITE : .right-col redevient un vrai conteneur flex vertical ── */
  .right-col {
    display: flex !important; flex-direction: column !important;
    grid-column: 2 !important; grid-row: 1 !important;
    width: calc(var(--card-h) * 2 / 3) !important;   /* MÊME largeur que la carte (2:3) → colonnes égales */
    height: var(--card-h) !important;            /* MÊME hauteur que la carte → le stack se centre dedans */
    min-height: 0 !important; min-width: 0 !important;
    gap: 6px !important;                          /* gaps SERRÉS (retour user 2026-06-22 : 10→6, espace hémicycle↔chrono réduit) */
    justify-content: center !important;          /* stack CENTRÉ verticalement (en face de la carte) */
  }
  /* ORDRE (retour user 2026-06-21) : hémicycle → chrono+pastilles de choix → stats.
     Le chrono et les pastilles de choix (gm-cta-row) se logent JUSTE SOUS l'hémicycle,
     les stat-cards passent EN DESSOUS (avant : hémicycle → stats → boutons). */
  .right-col > .game-panel     { order: 1 !important; flex: 0 0 auto !important; min-height: 0 !important; margin: 0 !important; padding-inline: 0 !important; align-self: stretch !important; }
  .right-col > .gm-cta-row      { order: 2 !important; flex: 0 0 auto !important; margin: 0 !important; align-self: stretch !important; }
  .right-col > .controls-panel { order: 3 !important; flex: 0 0 auto !important; margin: 0 !important; align-self: stretch !important; }
  /* Boutons « Nouvelle partie » / « Modes » ÉQUILIBRÉS (50/50) — avant seul le
     premier grandissait (déséquilibre, retour user). */
  .right-col .gm-cta-row .btn-new-game,
  .right-col .gm-cta-row .btn-options { flex: 1 1 0 !important; min-width: 0 !important; }
  /* éléments mobile-only masqués en desktop. `.is-fixed` est nécessaire : la règle
     `.mobile-footer-nav.is-fixed{display:grid!important}` (spéc. 0,2,0) bat un simple
     `.mobile-footer-nav` (0,1,0). */
  .stats-trigger, .mobile-footer-nav, .mobile-footer-nav.is-fixed { display: none !important; }
  /* La navbar du jeu en desktop = .header-actions (haut-droite du header). Le mobile
     la masque (`display:none`, ligne 477) au profit de la footer-nav qu'on vient de
     cacher → on la ré-affiche ici. */
  .header-actions { display: flex !important; }

  /* ── Stat-cards À L'HORIZONTALE (3 côte à côte) ── */
  .right-col .controls-panel {
    height: auto !important; margin: 0 !important;
    display: flex !important; flex-direction: column !important;
  }
  .right-col .controls-panel .stats-compact {
    flex-direction: row !important;
    gap: 0 !important;                              /* fusion : l'overlap est porté par les marges négatives */
    align-items: stretch !important;
    height: clamp(84px, 14vh, 130px) !important;   /* hauteur DÉFINIE → container-type:size (cqh) opérant */
    margin: 0 !important;
  }
  .right-col .controls-panel .stats-compact .stat-card {
    flex: 1 1 0 !important; min-width: 0 !important;
    margin-top: 0 !important;             /* annule l'overlap VERTICAL mobile (-5px) */
    padding-top: 7px !important;          /* annule le padding-top:13px de compensation */
  }
  /* Superposition HORIZONTALE (la fusion verticale du mobile, tournée 90°) : chaque
     carte mord sur la voisine de DROITE ; la carte de GAUCHE passe au-dessus. */
  .right-col .controls-panel .stats-compact .stat-card:nth-child(2),
  .right-col .controls-panel .stats-compact .stat-card:nth-child(3),
  .right-col .controls-panel .stats-compact .stat-card:nth-child(4) {
    margin-left: -12px !important; padding-left: 18px !important;   /* recouvrement + dégagement du contenu */
  }
  .right-col .controls-panel .stats-compact .stat-card:nth-child(1) { z-index: 3 !important; }
  .right-col .controls-panel .stats-compact .stat-card:nth-child(2) { z-index: 2 !important; }
  .right-col .controls-panel .stats-compact .stat-card:nth-child(3) { z-index: 1 !important; }
  .right-col .controls-panel .stats-compact .stat-card:nth-child(4) { z-index: 0 !important; }   /* 4e carte Bulletins (Campagne) */

  /* ── HÉMICYCLE : remplit l'espace flex:1 de la colonne, centré V+H ── */
  .right-col .game-panel {
    display: flex !important; flex-direction: column !important;
    align-self: stretch !important;
    align-items: stretch !important;
    justify-content: center !important;   /* centre l'hémicycle dans l'espace dispo */
  }
  #hemicycle-container {
    justify-content: center !important;   /* centre l'arc dans la colonne droite */
    width: 100% !important;
    overflow: hidden !important;          /* rogne le surplus du slot élargi (arc = pleine largeur colonne) */
    /* …mais le donut Ratios + le bouton Retour dépassent SOUS l'arc → on étend la
       border-box vers le bas (le padding est dans la zone de clip) pour qu'ils tiennent.
       (retour user 2026-06-22 : 46→30, espace hémicycle↔chrono réduit ; 30 suffit juste
       à loger le donut Ratios + son ombre sans clip.) */
    padding-bottom: 30px !important;
  }
  /* Largeur du slot posée en JS (sizeHemicycleDesktop, inline !important) ;
     fallback raisonnable avant le 1er passage. */
  #hemi-slot { width: min(100%, 60vh * 400 / 195) !important; margin: 0 auto !important; }

  /* ── Header : taille du titre bornée (le 6.05cqw mobile l'emballerait sur une
     barre large) ; padding latéral nul → titre/navbar alignés sur les bords des
     colonnes (.app porte déjà 28px de marge). ── */
  /* Header en RANGÉE (titre gauche / navbar droite) : une media query mobile le
     passe en `column` (titre empilé sur navbar) → on rétablit `row`. */
  .header {
    padding: 6px 0 !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    justify-content: space-between !important;
  }
  /* Titre à sa LARGEUR DE CONTENU. CRUCIAL : on DÉSACTIVE `container-type:inline-size`
     (posé en mobile pour les cqw) — la containment inline rend la largeur indépendante
     du contenu → `width:auto` se résolvait à 0 et l'accent débordait hors écran. En
     desktop la police est fixe (clamp), plus besoin de cqw. */
  .site-title { container-type: normal !important; flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; }
  .site-title .accent {
    flex: 0 0 auto !important;            /* taille de CONTENU (le flex:1 mobile l'étirait) */
    white-space: nowrap !important;
    font-size: clamp(20px, 2.3vw, 30px) !important;
    padding: 0.16em 0.34em 0.2em 0.4em !important;
  }
  .site-title .site-emoji { font-size: clamp(22px, 2.6vw, 34px) !important; }
  /* Navbar COMPACTE en desktop → titre + 4 boutons tiennent sur une rangée même
     près du carré (sinon ~885px ne rentrent pas sous ~800px de large). */
  .header-actions { flex: 0 0 auto !important; gap: 6px !important; }
  .header-actions .btn-collection,
  .header-actions .btn-nav {
    display: inline-flex !important;     /* le mobile les masque < ~900px (style.css:4793) → on les garde */
    font-size: 11px !important;
    padding: 6px 10px !important;
    letter-spacing: 0.02em !important;
    gap: 5px !important;
  }
  .header-actions .btn-collection .ico,
  .header-actions .btn-nav .ico { width: 15px !important; height: 15px !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   REVEAL « DOSSIER » (retours user 2026-06-03) — POUR TOUT LE MONDE (mobile + desktop).
   Fiche SANS photo, prénom+nom MÊME taille fit-to-width (1 ligne). PILE FLEX :
   VERDICT (gros, gauche, 1 ligne — l'anim part de lui, le nom s'écoule DESSOUS) → nom
   → pastille → parti → groupe → ──── → méta. Contrôles Pause+Suivant en POST-ITS sur le
   coin bas-droit. Progress ANCRÉE au bas de la fiche. PAS de bandeau (retiré, il était
   caché par le verdict). Animations conservées (typewriter, flip, slide-up, balistique).
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Fiche (flex column), mobile + desktop ───────────────────────────────── */
.reveal-screen.visible {
  display: flex !important; flex-direction: column !important;
  align-items: stretch !important; justify-content: flex-start !important;
  gap: 0 !important;
  top: 22px !important; left: 0 !important; right: 0 !important; bottom: auto !important;
  padding: 0 0 13px !important;            /* réserve basse pour la progress */
  background: var(--paper) !important; border: var(--border-thick) !important;
  box-shadow: var(--sh-md) !important;
  overflow: visible !important; perspective: 800px;
}
/* VERDICT : 1er élément FLUX (gros, gauche, 1 ligne). Marges symétriques g/d. Léger
   overhang HAUT (slap-on). max-width → fitRevealVerdict réduit les verdicts longs (zéro
   débord). Le nom s'écoule EN-DESSOUS (jamais recouvert). position:static + order:-1
   annulent l'absolu legacy ; sélecteur (0,3,0) bat game-v3:843. */
.reveal-screen.visible .reveal-verdict.show {
  order: -1 !important; position: static !important; align-self: flex-start !important;
  inset: auto !important; top: auto !important; left: auto !important; right: auto !important;
  margin: -16px 16px 4px 16px !important;
  max-width: calc(100% - 32px) !important;
  white-space: nowrap !important;
  font-size: clamp(34px, 8vw, 56px);   /* agrandi (retour user 2026-06-14 : plus d'impact) */
  padding: 8px 16px 10px !important;
  box-shadow: var(--sh-md) !important;
}
/* Nom : flex pleine largeur, 1 ligne, fit-to-width (fitRevealName réduit ; `nowrap`
   obligatoire sinon ça wrappe au lieu de réduire → coupe « RUNAC / HER »). */
.reveal-screen.visible .reveal-name {
  order: 1; grid-area: auto !important;
  align-self: stretch !important; width: auto !important; max-width: 100% !important;
  white-space: nowrap !important; overflow: hidden !important; text-align: left !important;
  padding: 10px 16px 0 !important; margin: 0 !important;
}
.reveal-screen.visible .reveal-party {
  order: 2; grid-area: auto !important;
  align-self: flex-start !important; margin: 11px 16px 11px !important;
}
/* Rubriques C+D — ligne-mention sous la pilule mouvement : mouvement précis
   (quand la pilule montre le super-mouvement de l'hémicycle) et/ou raison
   d'acceptation (« Ex-Républicain », « Soutenue par les Socialistes »).
   Rendu = PILULES colorées, même langage que .reveal-party (style.css) en
   plus petit : font-display, bord épais, ombre franche, tilt -1°. */
.reveal-mvt-mention {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
}
.reveal-mvt-mention .reveal-mvt-pill {
  display: inline-block;
  width: fit-content;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(11px, 1.5vw, 15px);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  padding: 5px 10px 6px;
  border: var(--border-thick);
  box-shadow: var(--sh-sm);
  transform: rotate(-1deg);
  /* Même entrée flip que la pilule principale (revealPartyFlip, style.css —
     délai 220ms), juste différée : 1ʳᵉ pilule +100ms, 2ᵉ +160ms (stagger). */
  animation: revealPartyFlip 480ms cubic-bezier(.34, 1.4, .64, 1) both 320ms;
  transform-origin: center center;
  backface-visibility: hidden;
}
.reveal-mvt-mention .reveal-mvt-pill:nth-child(2) { animation-delay: 380ms; }
@media (prefers-reduced-motion: reduce) {
  .reveal-mvt-mention .reveal-mvt-pill { animation: none; }
}
html.reduce-motion .reveal-mvt-mention .reveal-mvt-pill { animation: none !important; }
.reveal-mvt-mention[hidden] { display: none !important; }
.reveal-screen:not(.visible) .reveal-mvt-mention { display: none; }
.reveal-screen.visible .reveal-mvt-mention {
  order: 2; grid-area: auto !important;
  margin: -4px 16px 11px !important;
}
.reveal-screen.visible .reveal-party-sub {
  order: 3; grid-area: auto !important; margin: 0 !important; padding: 0 16px !important;
}
.reveal-screen.visible .reveal-groupe-sigle {
  /* Problème 1 (retour user 2026-06-03) : le padding-bas (13px) ici était la SEULE
     source d'espace avant le trait pointillé → quand il n'y a PAS de groupe (élément
     display:none), l'espace disparaissait et le trait se collait sous la ligne parti.
     On retire ce padding et on porte l'espace sur la marge-HAUT du bloc méta (constant). */
  order: 4; grid-area: auto !important; margin: 3px 0 0 !important; padding: 0 16px 0 !important;
}
.reveal-screen.visible .reveal-meta {
  order: 5; margin: 13px 16px 6px !important;   /* 13px top = espace CONSTANT avant le pointillé (groupe ou non) */
  border-top: 3px dashed var(--ink) !important; padding-top: 11px !important;
}
/* ── Contrôles Pause + Suivant : post-its ancrés au coin bas-DROIT (débordent). ── */
.reveal-screen.visible .reveal-controls {
  position: absolute !important; bottom: -18px !important; right: -6px !important;
  display: flex !important; gap: 8px !important; align-items: flex-end !important; z-index: 6 !important;
}
.reveal-screen.visible .reveal-next {
  position: static !important; align-self: auto !important;
  margin: 0 !important; inset: auto !important; transform: rotate(-2deg);
}
.reveal-screen.visible .reveal-pause {
  position: static !important; flex: 0 0 auto;
  width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink);
  border: var(--border-thick); box-shadow: var(--sh-sm);
  cursor: pointer; transform: rotate(2deg);
  transition: transform 140ms var(--ease-out), box-shadow 140ms var(--ease-out);
}
.reveal-pause svg { width: 20px; height: 20px; display: block; }
html.dlp-can-hover .reveal-pause:hover { transform: rotate(2deg) translate(-1px,-1px); box-shadow: var(--sh-md); }
/* Toggle icône : pause (2 barres) par défaut → play (triangle) quand en pause. */
.reveal-pause.is-paused .rp-ico-pause { display: none; }
.reveal-pause.is-paused .rp-ico-play { display: block !important; }
/* ── Progress : ANCRÉE au bas de la fiche (full-width strip, cohérent partout). ── */
.reveal-screen.visible .reveal-progress {
  position: absolute !important; left: 0 !important; right: 0 !important;
  bottom: 0 !important; top: auto !important; width: auto !important;
  height: 7px !important; margin: 0 !important; z-index: 3 !important; overflow: hidden;
}
/* Problème 2 (desktop, retour user 2026-06-03) — la barre de progression avait un
   TRACK noir plein (var(--ink)) ; une fois le temps écoulé, ce track fusionnait avec
   la bordure basse noire + l'ombre portée → une grosse masse noire au ras du bord qui
   semblait « déborder sous le cadre » par-dessus le fond du jeu. On allège le track en
   gris très discret : seul le fill (vert/orange/rouge) reste franc, la portion écoulée
   se fond dans le papier → plus de bande noire. Cohérent mobile + desktop. */
.reveal-screen.visible .reveal-progress { background: rgba(10, 10, 10, 0.10) !important; }

/* ════════════════════════════════════════════════════════════════════════════
   Problème 3 (retour user 2026-06-03) — TIMING du verdict. Phase « verdict-only ».
   Le verdict est un enfant de #reveal-screen ; or la fiche est display:none au repos
   → son anim balistique ne démarrait qu'à showReveal (T+450), désynchronisée du shake
   (programmé à T+468) et donnant une impression de « retard au clic ».
   PHASE A (T+0, classe .verdict-only posée par showRevealVerdictNow) : la fiche est
   rendue (display:flex) → le verdict s'élance AU CLIC, mais le CADRE (fond/bordure/
   ombre) est transparent et tout le contenu est display:none → seul le verdict tampon
   flotte sur l'hémicycle (overlay beige neutralisé).
   PHASE B (T+450, .verdict-only retiré par showReveal, au moment où le verdict
   retombe) : le cadre se matérialise (transition), le contenu réapparaît (ses anims
   d'entrée flip/slide/typewriter (re)démarrent car display:none → display) et le shake
   joue → tout se déclenche ENSEMBLE à la retombée, comme voulu.
   ════════════════════════════════════════════════════════════════════════════ */
/* Le cadre se matérialise en douceur quand on quitte la phase A (opacity ABSENTE de la
   liste → le verdict ne fond pas, il POP via sa balistique). */
.reveal-screen.visible {
  transition: background-color 200ms var(--ease-out),
              border-color 200ms var(--ease-out),
              box-shadow 200ms var(--ease-out);
}
/* PHASE A : cadre invisible (border-color, pas border:none → 0 reflow), non cliquable
   (les clics traversent vers l'hémicycle, bloqué par isAnswering → pas d'advance). */
.reveal-screen.visible.verdict-only {
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
  pointer-events: none !important;
}
/* Tout SAUF le verdict est display:none en phase A → leurs anims d'entrée ne partent
   qu'en phase B (au passage display:none → display). */
.reveal-screen.visible.verdict-only .reveal-name,
.reveal-screen.visible.verdict-only .reveal-party,
.reveal-screen.visible.verdict-only .reveal-mvt-mention,
.reveal-screen.visible.verdict-only .reveal-party-sub,
.reveal-screen.visible.verdict-only .reveal-groupe-sigle,
.reveal-screen.visible.verdict-only .reveal-meta,
.reveal-screen.visible.verdict-only .reveal-controls,
.reveal-screen.visible.verdict-only .reveal-progress { display: none !important; }

/* Problème 1 (mobile) — on abaisse les contrôles Pause+Suivant SOUS la dernière
   ligne de la fiche pour qu'ils ne la recouvrent plus (placé après le bloc Dossier
   pour battre le `bottom:-18px` global ; portrait uniquement → le desktop, qui n'a
   pas le souci et a les stats juste dessous, garde son léger overhang). */
@media (max-aspect-ratio: 1/1) {
  .reveal-screen.visible .reveal-controls { bottom: -30px !important; }
}

/* ════════════════════════════════════════════════════════════════════════════
   Problèmes 3 + 4 (retours user 2026-06-03 soir) — fond beige qui déborde + boutons
   qui « sautent ». MÊME cause : l'ancien voile beige (.reveal-overlay-bg) qui couvrait
   l'hémicycle débordait la fiche (bas en desktop, haut en mobile), et les boutons
   étaient masqués/rétrécis (jump). La fiche étant OPAQUE et rendue PAR-DESSUS, le voile
   est redondant : on le neutralise (→ plus de beige qui dépasse) et on FOND simplement
   l'hémicycle en phase B (sinon, sur mobile, l'arc — plus large que la fiche — dépasse
   sur les côtés). Les boutons ne sont plus masqués : la fiche se pose par-dessus.
   ════════════════════════════════════════════════════════════════════════════ */
/* #3 — voile beige neutralisé pendant TOUT le reveal (la fiche opaque suffit). */
.game-panel:has(.reveal-screen.visible) .reveal-overlay-bg { opacity: 0 !important; }
/* Hémicycle : VISIBLE en phase A (le verdict flotte dessus), FONDU en phase B (la
   fiche se pose par-dessus → aucun arc ne dépasse, mobile inclus). */
#hemi-slot, #hemicycle-svg { transition: opacity 240ms var(--ease-out); }
.game-panel:has(.reveal-screen.visible:not(.verdict-only)) #hemi-slot,
.game-panel:has(.reveal-screen.visible:not(.verdict-only)) #hemicycle-svg {
  opacity: 0 !important; pointer-events: none !important;
}
/* (retour user 2026-06-15) Ratios NE DISPARAÎT PLUS pendant le reveal : le cadre de
   dépouillement (plus haut) le RECOUVRE entièrement → le scale-out + réapparition n'apportait
   rien et causait un jump au retour. On garde juste pointer-events:none (clic intercepté
   par le cadre). pct-hidden-by-reveal n'est plus posée côté JS. */
.game-panel:has(.reveal-screen.visible) .pct-postit {
  pointer-events: none !important;
}
/* La bande .gm-cta-row reste visible pendant le reveal (au lieu de clignoter)… */
.main#game:has(.reveal-screen.visible) .gm-cta-row { visibility: visible !important; }
/* …ET ses post-its de choix ET le chrono de JEU sont MASQUÉS pendant le reveal : la fiche
   est le focus. Le chrono de jeu est désormais TOUJOURS caché au reveal (refonte 2026-06-15 :
   le mult chrono est une pastille spawnée dans la scène de dépouillement, plus la vraie
   pastille déplacée — voir depouillement.js ; et la laisser affichée spoilait une bonne partie). */
.main#game:has(.reveal-screen.visible) .gm-cta-row > #stage-postits,
.main#game:has(.reveal-screen.visible) .gm-cta-row > .speed-timer { visibility: hidden !important; }


/* ─── Réductions ciblées (retour user 2026-06-15) ──────────────────────────────
   On scale via la propriété INDIVIDUELLE `scale:` (≠ transform) → elle COMPOSE avec
   le `rotate:` du sway au lieu de l'écraser. La règle hover partagée remettant
   `scale:1 !important`, on la ré-override pour ces éléments (sinon saut au survol). */

/* (1) Pastille d'indice À 80% — et comme le BANDEAU d'indice est le MÊME élément
   (.hint-postit-wrap passant en .has-message à l'achat), la réduction s'y propage.
   On passe par `transform: scale()` (≠ propriété `scale:`) car la pastille a une
   animation `hintBreathe` qui anime déjà `scale:` (1↔1.04) → notre transform se
   COMPOSE par-dessus au lieu d'être écrasé. (Le bandeau anime maxWidth d'un enfant,
   pas le transform du wrap → pas de conflit.) */
.hint-postit-wrap { transform: scale(0.8); }
html.dlp-can-hover .hint-postit-wrap:has(.hint-postit:hover) { transform: scale(0.8) !important; }

/* (2) Bouton « Retour » de l'hémicycle à 85%, DESCENDU dans le coin bas-droit libre sous l'arc
   (retour user : à 16px il était trop HAUT et recouvrait le texte des secteurs bas). */
.hemicycle-back { scale: 0.85; }
html.dlp-can-hover .hemicycle-back:hover { scale: 0.85 !important; }
.hemicycle-wrap.is-armed .hemicycle-back { bottom: -34px !important; right: 4px !important; }


/* ════════════════════════════════════════════════════════════════════════════
   POST-ITS PROPORTIONNELS À LA PHOTO (user 2026-06-21)
   ───────────────────────────────────────────────────────────────────────────
   Les post-its de jeu (VIES / PASSER / INDICE) gardaient une taille FIXE en px
   (vies : 104×96, repassant à 84×78 sous 760px ; Passer : 9,5px ; Indice : 10px),
   indépendante de la taille de la photo. On les indexe désormais sur --card-h
   (= hauteur de la photo, posée sur #game par sizeHemicycle/CSS) via un scalaire
   --postit-k BORNÉ : clamp(min, proportionnel, max) → taille mini garantie sur
   petit écran, maxi sur grand écran, ÉCHELLE proportionnelle entre les deux.
   Remplace les tailles fixes ET le breakpoint 760px du post-it vies. Vaut à
   TOUTE largeur (portrait + desktop), source tardive + spécificité (.card-stack …)
   → prime sur les blocs @media précédents. */
.card-stack {
  /* --postit-u = LONGUEUR pilote (= largeur du post-it vies) qui suit --card-h,
     bornée min/max. TOUT en longueurs (length × number = length, clamp de
     longueurs) → valide partout, y compris vieux WebKit/iOS (≠ length/number qui
     casse le clamp). card-h ~456 → 82px (min) · ~773 (desktop 1440) → ~139px ·
     ≥833 (grand desktop) → 150px (max). Plafond + facteur relevés (retour user
     2026-06-22 : « max pas assez grand »). Bande proportionnelle ≈ card-h 456→833. */
  /* Facteur + plafond relevés 2× (retour user 2026-06-22 : « encore trop petit ») :
     à 1440px (card-h 773) → ~201px ; plafond 220px sur grand écran ; min 82px inchangé. */
  --postit-u: clamp(82px, calc(var(--card-h, 520px) * 0.26), 220px);
}
/* VIES — cœur (SVG : chiffre/label en unités viewBox → suivent la taille).
   Coefficient PROPRE (0.8 ; retour user 2026-06-22 : le cœur ressortait trop face au
   skip/indice) → le cœur est ~20 % plus petit que le « u » plein des autres post-its. */
.card-stack .lives-postit {
  width: calc(var(--postit-u) * 0.8) !important;
  height: calc(var(--postit-u) * 0.72) !important;   /* 0.8 × 0.9 (ratio h/l d'origine) */
}
/* Contour + ombre du cœur ALIGNÉS sur les autres post-its (retour user 2026-06-22 :
   « épaisseur stroke/shadow différente »). CAUSE : le stroke du cœur était en unités
   viewBox (stroke-width:1) SANS non-scaling-stroke → il GROSSISSAIT avec le cœur
   (~6.7px à 161px) ; et l'ombre 6px était plus lourde que skip/indice (~3px). FIX :
   non-scaling-stroke → contour CONSTANT (~3.5px, comme le drapeau « Passer » à 3px et
   l'indice ~3.2px) ; drop-shadow ramené à 3px (= --sh-sm des autres post-its). */
.card-stack .lives-heart-shape {
  vector-effect: non-scaling-stroke !important;
  stroke-width: 3.5 !important;
}
.card-stack .lives-postit { filter: drop-shadow(3px 3px 0 var(--ink)) !important; }
/* PASSER — drapeau (police + padding ; le SVG frame en inset:0/100% suit la boîte).
   Fractions normalisées sur u≈104 → ≈ tailles actuelles (font 9,5 / pad 8·11·8·18). */
.card-stack .skip-rp {
  font-size: calc(var(--postit-u) * 0.092) !important;
  padding: calc(var(--postit-u) * 0.077) calc(var(--postit-u) * 0.106)
           calc(var(--postit-u) * 0.077) calc(var(--postit-u) * 0.173) !important;
}
/* INDICE — pastille (police + padding + icône + pastille de coût). Le scale(0.8)
   global (« indice à 80% ») reste appliqué PAR-DESSUS → garde l'intention.
   Fractions normalisées sur u≈104 → ≈ tailles actuelles (pad 5·8 / font 10 / ico 16 / cost 9). */
.card-stack .hint-postit-wrap {
  padding: calc(var(--postit-u) * 0.048) calc(var(--postit-u) * 0.077) !important;
  font-size: calc(var(--postit-u) * 0.096) !important;
}
.card-stack .hint-postit .hint-line { font-size: calc(var(--postit-u) * 0.096) !important; }
.card-stack .hint-postit > .ico {
  width: calc(var(--postit-u) * 0.154) !important;
  height: calc(var(--postit-u) * 0.154) !important;
}
.card-stack .hint-postit .cost { font-size: calc(var(--postit-u) * 0.087) !important; }


/* ════════════════════════════════════════════════════════════════════════════
   STAT-CARDS — REFLOW 2×2 EN PORTRAIT LARGE (user 2026-06-21)
   ───────────────────────────────────────────────────────────────────────────
   En portrait, la colonne stats (col2 = 1fr) s'élargit avec l'écran → les 4
   cartes empilées en 1 colonne deviennent « larges et fines ». On ajoute un état
   intermédiaire : dès que la boîte stats n'est plus nettement plus haute que
   large, on REFLOWE en 2 colonnes (4 cartes → 2×2). La rangée unique (« une seule
   ligne ») arrive ENSUITE, à la bascule portrait→paysage (aspect 1/1), déjà gérée
   par le bloc DESKTOP : la hauteur des stats étant verrouillée à 0.84×--card-h,
   une rangée unique en portrait donnerait des cartes étroites/hautes → on ne la
   déclenche qu'en paysage (où la hauteur stats devient compacte).
   Piloté par CONTAINER-QUERY sur .controls-panel (largeur = col2, hauteur =
   0.84×--card-h → aspect-ratio fiable). Exclu sous 311px (mono-colonne en bandes,
   où .controls-panel passe en height:auto → incompatible container-type:size). */
@media (max-aspect-ratio: 1/1) and (min-width: 311px) {
  .controls-panel { container-type: size; container-name: statsbox; }

  /* Boîte stats ~aussi large que haute (aspect ≥ 0.62) → 2 colonnes. */
  @container statsbox (min-aspect-ratio: 62/100) {
    .controls-panel .stats-compact {
      display: grid !important;
      grid-template-columns: 1fr 1fr !important;
      grid-auto-rows: 1fr !important;
      grid-auto-flow: row !important;
      gap: 8px !important;
      height: 100% !important;
    }
    /* Annule l'OVERLAP vertical du mode 1-colonne (margin-top -5px / padding-top 13px). */
    .controls-panel .stats-compact .stat-card {
      margin: 0 !important;
      padding-top: 7px !important;
    }
    /* Une carte masquée (VIES hors Survie, BULLETINS hors Campagne) le reste. */
    .controls-panel .stats-compact .stat-card.hidden,
    .controls-panel .stats-compact .stat-card[hidden] { display: none !important; }
  }
}
