/* ─────────────────────────────────────────────────────────────────────
   Disable iOS double-tap-to-zoom on interactive content.
   `touch-action: manipulation` preserves single tap, pan (scroll), and
   pinch-to-zoom (accessibility), but turns off the legacy double-tap
   zoom gesture. As a side benefit, this also removes the 300 ms tap
   latency that older iOS versions added to detect double-taps.
   Applies globally because every clickable surface in the app should
   feel snappy and stable (avatar picker, reaction buttons, action
   buttons during a hand, etc.).
   ───────────────────────────────────────────────────────────────────── */
/* ── Police officielle Inter (parité QML, point 7 du chantier clone) ──
   Fichier EXACT du client officiel (Inter-VariableFont de l'APK, axes
   opsz 14-32 + wght 100-900), converti en woff2 (877 Ko → 350 Ko),
   self-hosted (public/fonts/, licence OFL jointe). Les tokens --ff-* des
   thèmes PokerTH référencent déjà 'Inter' : ce @font-face les résout enfin
   (ils retombaient silencieusement sur system-ui). */
@font-face {
  font-family: 'Inter';
  src: url('fonts/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
/* Texte courant en Inter dans les thèmes PokerTH uniquement (le QML utilise
   Inter partout) ; les autres thèmes gardent leur pile système. Les contrôles
   de formulaire n'héritent pas par défaut -> inherit explicite. */
:root[data-theme^="pokerth"] body { font-family: 'Inter', system-ui, sans-serif; }
:root[data-theme^="pokerth"] :is(button, input, select, textarea) { font-family: inherit; }

html { touch-action: manipulation; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

:root {
  /* ═══════════════════════════════════════════════════════════════════════
     COUCHE DE TOKENS GÉNÉRIQUE — échelles unifiées (typo · espacement · rayon ·
     hauteurs de contrôle). Barème DISCRET, surchargeable par breakpoint en un
     seul endroit (voir docs/DESIGN_TOKENS.md → §Responsive). ADDITIF : tant
     qu'un élément ne référence pas ces variables, le rendu est INCHANGÉ.
     Les valeurs QML (barre d'action 54/40 px, All-In 52 px, radius 9/10) sont
     encodées ici → la fidélité est préservée par construction.
     Réf. complète : docs/DESIGN_TOKENS.md */
  /* Typographie (rem) — dérivée des 77 valeurs existantes ramenées à 10 pas */
  --fs-3xs: .55rem;  --fs-2xs: .62rem;  --fs-xs: .70rem;   --fs-sm: .78rem;
  --fs-base: .85rem; --fs-md: .95rem;   --fs-lg: 1.05rem;  --fs-xl: 1.35rem;
  --fs-2xl: 1.6rem;  --fs-hero: 2.6rem;
  --lh-tight: 1.1;   --lh-base: 1.35;
  /* Espacement (px, base 2 — 6/8 = chevaux de trait) */
  --sp-0: 2px;  --sp-1: 4px;  --sp-2: 6px;  --sp-3: 8px;
  --sp-4: 10px; --sp-5: 12px; --sp-6: 16px; --sp-7: 20px;
  /* Rayons (QML : bouton 9, barre 10) */
  --r-xs: 3px; --r-sm: 6px; --r-md: 9px; --r-lg: 12px; --r-bar: 10px; --r-pill: 999px;
  /* Accent des pastilles du bandeau de jeu. #pot-strip est un bandeau NOIR
     rgba(0,0,0,0.78) dans TOUS les modes (parite QML §7), donc son accent doit
     rester lisible sur du sombre : il suit le theme par defaut, mais la palette
     claire le ramene a l'or QML (Theme.colorAccent #E3C800 n'a qu'UNE valeur
     dans la bible §13.2, pas de variante claire). */
  --sel-bar: var(--sel, #E3C800);
  --sel-bar-rgb: var(--sel-rgb, 227,200,0);
  /* Hauteurs de contrôle (QML : barre 54, landscapeCompact 40, All-In 52) */
  --ctrl-sm: 26px; --ctrl-md: 34px; --ctrl-lg: 40px; --ctrl-xl: 54px; --ctrl-allin: 52px;

  --ff-display: 'Cinzel', serif;
  --ff-mono:    'Inconsolata', monospace;
  --timer-glow: 0 0 3px rgba(var(--gold-rgb), 0.5), 0 1px 2px rgba(0,0,0,0.9);
  --felt:       #182e1a;
  --felt-mid:   #1e3820;
  --felt-hi:    #254526;
  /* Surface de la table (axe "Tapis") — feutre de l'oval + lisere. Voir theme.mjs. */
  --felt-base-hi:  #1e6b1e;
  --felt-base-mid: #0f3d0f;
  --felt-base-lo:  #091f09;
  --modal-bg:   linear-gradient(160deg, #0a1f0a 0%, #142a18 50%, #08160a 100%);
  --body-glow:  rgba(50,100,50,0.18);
  --rail:          #6b3e18;
  --rail-dark:     #3a2208;
  --rail-glow:     rgba(107,62,24,0.3);
  --panel:      rgba(8,18,10,0.88);
  --panel-hi:   rgba(14,28,16,0.9);
  --gold:       #E3C800;
  --gold-rgb:   227,200,0;
  --chrome-tint: rgba(0,0,0,0.35);
  --pos:        #4cff88;
  --neg:        #ff6b6b;
  --info:       #7ec8e3;
  --green-rgb:  39,174,96;
  --red-rgb:    192,57,43;
  --blue-rgb:   52,152,219;
  --green2-rgb: 88,201,122;
  --orange-rgb: 230,126,34;
  --on-green:   #d7ffe0;
  --ld-quit-fg: #fad6d0;
  --ld-create-fg: #d6f5dc;
  /* Confirm-dialog buttons — couleurs QML constantes sur tous les themes.
     Dialogues quit/disconnect : les deux boutons sont neutres (contour),
     fideles au dialogue officiel. Seul Create (quick-create) = Raise vert. */
  --qml-pos-grad:       linear-gradient(180deg, #50b840, #1e6614);
  --qml-pos-grad-hi:    linear-gradient(180deg, #5ec84c, #248019);
  --qml-pos-edge:       #7ad06a;
  --qml-pos-fg:         #eafbe6;
  --wp-need-fg: #e0a040;
  --gold-hi:    #f2dc4d;
  --gold-dim:   #b09a00;
  --cream:      #ede8dc;
  --field-bg:   #0c1e0e;
  --inset: rgba(255,255,255,0.05);
  --inset-hi: rgba(255,255,255,0.08);
  --on-gold:    #110900;
  --text:       #9aaa92;
  --text-hi:    #c8d8c0;
  --red:        #c0392b;
  --green:      #27ae60;
  --orange:     #e67e22;
  --border:     rgba(var(--gold-rgb), 0.25);
  --border-hi:  rgba(var(--gold-rgb), 0.65);
  --card-back:  url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20100%20140%27%20preserveAspectRatio%3D%27none%27%3E%3Cdefs%3E%3CradialGradient%20id%3D%27h%27%20cx%3D%2750%25%27%20cy%3D%2744%25%27%20r%3D%2780%25%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%23234023%27%2F%3E%3Cstop%20offset%3D%27100%25%27%20stop-color%3D%27%230c1c0e%27%2F%3E%3C%2FradialGradient%3E%3Cpattern%20id%3D%27l%27%20width%3D%2714%27%20height%3D%2714%27%20patternUnits%3D%27userSpaceOnUse%27%3E%3Cpath%20d%3D%27M7%200L14%207L7%2014L0%207Z%27%20fill%3D%27none%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%270.6%27%20opacity%3D%270.4%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%270.8%27%20fill%3D%27%23c8a84a%27%20opacity%3D%270.45%27%2F%3E%3C%2Fpattern%3E%3C%2Fdefs%3E%3Crect%20width%3D%27100%27%20height%3D%27140%27%20fill%3D%27url%28%23h%29%27%2F%3E%3Crect%20x%3D%276%27%20y%3D%276%27%20width%3D%2788%27%20height%3D%27128%27%20rx%3D%275%27%20fill%3D%27url%28%23l%29%27%2F%3E%3Crect%20x%3D%275%27%20y%3D%275%27%20width%3D%2790%27%20height%3D%27130%27%20rx%3D%277%27%20fill%3D%27none%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%271.4%27%2F%3E%3Crect%20x%3D%278.5%27%20y%3D%278.5%27%20width%3D%2783%27%20height%3D%27123%27%20rx%3D%275%27%20fill%3D%27none%27%20stroke%3D%27%237a6428%27%20stroke-width%3D%270.6%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2725%27%20ry%3D%2737%27%20fill%3D%27%2313280f%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%270.9%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2721%27%20ry%3D%2732.5%27%20fill%3D%27none%27%20stroke%3D%27%237a6428%27%20stroke-width%3D%270.5%27%2F%3E%3Ctext%20x%3D%2750%27%20y%3D%2784%27%20font-size%3D%2738%27%20text-anchor%3D%27middle%27%20fill%3D%27%23e0c070%27%20font-family%3D%27Georgia%2Cserif%27%3E%E2%99%A0%3C%2Ftext%3E%3C%2Fsvg%3E");
}

/* ── Palette : Sombre neutre (axe "Palette", choisie via le menu 🎨) ──
   "Casino vert" reste le défaut dans :root ci-dessus ; ce bloc ne fait
   qu'écraser les variables de couleur quand <html data-theme="dark">.
   Voir public/modules/theme.mjs. */
:root[data-theme="dark"] {
  --felt:       #1b1e24;
  --felt-mid:   #232730;
  --felt-hi:    #2c313c;
  --modal-bg:   linear-gradient(160deg, #0e1014 0%, #161a20 50%, #0c0e12 100%);
  --panel:      rgba(12,14,18,0.90);
  --panel-hi:   rgba(20,23,29,0.92);
  --gold:       #E3C800;
  --gold-hi:    #f2dc4d;
  --gold-dim:   #b09a00;
  --cream:      #ece9e2;
  --field-bg:   #12151b;
  --inset: rgba(255,255,255,0.05);
  --inset-hi: rgba(255,255,255,0.08);
  --on-gold:    #110900;
  --text:       #97a0ad;
  --text-hi:    #d4dae3;
  --red:        #c0392b;
  --green:      #27ae60;
  --orange:     #e67e22;
  --border:     rgba(var(--gold-rgb), 0.22);
  --border-hi:  rgba(var(--gold-rgb), 0.60);
  --card-back:  url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20100%20140%27%20preserveAspectRatio%3D%27none%27%3E%3Cdefs%3E%3CradialGradient%20id%3D%27h%27%20cx%3D%2750%25%27%20cy%3D%2744%25%27%20r%3D%2780%25%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%232c313c%27%2F%3E%3Cstop%20offset%3D%27100%25%27%20stop-color%3D%27%230c0e12%27%2F%3E%3C%2FradialGradient%3E%3Cpattern%20id%3D%27l%27%20width%3D%2714%27%20height%3D%2714%27%20patternUnits%3D%27userSpaceOnUse%27%3E%3Cpath%20d%3D%27M7%200L14%207L7%2014L0%207Z%27%20fill%3D%27none%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%270.6%27%20opacity%3D%270.4%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%270.8%27%20fill%3D%27%23c8a84a%27%20opacity%3D%270.45%27%2F%3E%3C%2Fpattern%3E%3C%2Fdefs%3E%3Crect%20width%3D%27100%27%20height%3D%27140%27%20fill%3D%27url%28%23h%29%27%2F%3E%3Crect%20x%3D%276%27%20y%3D%276%27%20width%3D%2788%27%20height%3D%27128%27%20rx%3D%275%27%20fill%3D%27url%28%23l%29%27%2F%3E%3Crect%20x%3D%275%27%20y%3D%275%27%20width%3D%2790%27%20height%3D%27130%27%20rx%3D%277%27%20fill%3D%27none%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%271.4%27%2F%3E%3Crect%20x%3D%278.5%27%20y%3D%278.5%27%20width%3D%2783%27%20height%3D%27123%27%20rx%3D%275%27%20fill%3D%27none%27%20stroke%3D%27%237a6428%27%20stroke-width%3D%270.6%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2725%27%20ry%3D%2737%27%20fill%3D%27%231b1e24%27%20stroke%3D%27%23c8a84a%27%20stroke-width%3D%270.9%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2721%27%20ry%3D%2732.5%27%20fill%3D%27none%27%20stroke%3D%27%237a6428%27%20stroke-width%3D%270.5%27%2F%3E%3Ctext%20x%3D%2750%27%20y%3D%2784%27%20font-size%3D%2738%27%20text-anchor%3D%27middle%27%20fill%3D%27%23e0c070%27%20font-family%3D%27Georgia%2Cserif%27%3E%E2%99%A0%3C%2Ftext%3E%3C%2Fsvg%3E");
}

/* ── Palette : PokerTH officiel (axe "Palette") ── slate neutre + accent ambré,
   couleurs reprises du client QML 2.x. Comme :root/dark, ne fait qu'ecraser les
   variables. Voir theme.mjs. */
:root[data-theme="pokerth"] {
  --ff-display: 'Inter', system-ui, sans-serif;
  --ff-mono:    'Inter', system-ui, sans-serif;
  --felt:       #161b23;
  --felt-mid:   #1d222b;
  --felt-hi:    #252c38;
  --modal-bg:   linear-gradient(160deg, #12161d 0%, #1d222b 50%, #0e1218 100%);
  --panel:      rgba(20,25,33,0.92);
  --panel-hi:   rgba(29,34,43,0.94);
  --gold:       #eff1f5;
  --gold-rgb:   239,241,245;
  --gold-hi:    #ffffff;
  --gold-dim:   #a0acc4;
  --sel:        #E3C800;
  --sel-rgb:    227,200,0;
  --sel-hi:     #ffd700;
  --timer-normal: #cdd3e0;
  --cream:      #eff1f5;
  --field-bg:   #161c25;
  --inset: rgba(255,255,255,0.05);
  --inset-hi: rgba(255,255,255,0.08);
  --on-gold:    #110900;
  --text:       #a0acc4;
  --text-hi:    #eff1f5;
  --red:        #c0392b;
  --green:      #27ae60;
  --orange:     #e67e22;
  --border:     rgba(160,172,196,0.16);
  --border-hi:  rgba(var(--gold-rgb), 0.55);
  --card-back:  url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20100%20140%27%20preserveAspectRatio%3D%27none%27%3E%3Cdefs%3E%3CradialGradient%20id%3D%27h%27%20cx%3D%2750%25%27%20cy%3D%2744%25%27%20r%3D%2780%25%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%232c313c%27%2F%3E%3Cstop%20offset%3D%27100%25%27%20stop-color%3D%27%230c0e12%27%2F%3E%3C%2FradialGradient%3E%3Cpattern%20id%3D%27l%27%20width%3D%2714%27%20height%3D%2714%27%20patternUnits%3D%27userSpaceOnUse%27%3E%3Cpath%20d%3D%27M7%200L14%207L7%2014L0%207Z%27%20fill%3D%27none%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%270.6%27%20opacity%3D%270.4%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%270.8%27%20fill%3D%27%236b7689%27%20opacity%3D%270.45%27%2F%3E%3C%2Fpattern%3E%3C%2Fdefs%3E%3Crect%20width%3D%27100%27%20height%3D%27140%27%20fill%3D%27url%28%23h%29%27%2F%3E%3Crect%20x%3D%276%27%20y%3D%276%27%20width%3D%2788%27%20height%3D%27128%27%20rx%3D%275%27%20fill%3D%27url%28%23l%29%27%2F%3E%3Crect%20x%3D%275%27%20y%3D%275%27%20width%3D%2790%27%20height%3D%27130%27%20rx%3D%277%27%20fill%3D%27none%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%271.4%27%2F%3E%3Crect%20x%3D%278.5%27%20y%3D%278.5%27%20width%3D%2783%27%20height%3D%27123%27%20rx%3D%275%27%20fill%3D%27none%27%20stroke%3D%27%233a4254%27%20stroke-width%3D%270.6%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2725%27%20ry%3D%2737%27%20fill%3D%27%231b1e24%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%270.9%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2721%27%20ry%3D%2732.5%27%20fill%3D%27none%27%20stroke%3D%27%233a4254%27%20stroke-width%3D%270.5%27%2F%3E%3Ctext%20x%3D%2750%27%20y%3D%2784%27%20font-size%3D%2738%27%20text-anchor%3D%27middle%27%20fill%3D%27%23a0acc4%27%20font-family%3D%27Georgia%2Cserif%27%3E%E2%99%A0%3C%2Ftext%3E%3C%2Fsvg%3E");
}

/* ── Palette : PokerTH officiel (clair) (axe "Palette") ── variante claire de
   la palette PokerTH officielle (valeurs _light du client QML). Ne fait qu'ecraser
   les variables. Voir theme.mjs. */
:root[data-theme="pokerth-light"] {
  --ff-display: 'Inter', system-ui, sans-serif;
  --ff-mono:    'Inter', system-ui, sans-serif;
  --felt:       #f0f3f8;
  --felt-mid:   #e6ebf3;
  --felt-hi:    #dce2ec;
  --modal-bg:   linear-gradient(160deg, #f0f3f8 0%, #e2e8f1 50%, #eef1f7 100%);
  --panel:      #c8cacf;
  --panel-hi:   #d3d5da;
  --gold:       #1d222b;
  --gold-rgb:   29,34,43;
  --gold-hi:    #000000;
  --gold-dim:   #576378;
  --sel:        #9a7d0a;
  --sel-rgb:    154,125,10;
  /* Bandeau noir meme en clair -> on garde l'or QML (sinon 3,7:1 sur le texte,
     sous le seuil AA, et bordure a 2,1:1 quasi invisible). */
  --sel-bar:     #E3C800;
  --sel-bar-rgb: 227,200,0;
  --sel-hi:     #c2a02e;
  --timer-normal: #394150;
  --timer-glow: 0 1px 1px rgba(0,0,0,0.22);
  --timer-bg:   rgba(255,255,255,0.92);
  --chrome-tint: rgba(0,0,0,0.06);
  --pos:        #1e7e43;
  --neg:        #c0392b;
  --info:       #2a6fb0;
  --green-rgb:  30,126,67;
  --red-rgb:    166,47,34;
  --blue-rgb:   42,111,176;
  --green2-rgb: 30,126,67;
  --orange-rgb: 179,94,16;
  --on-green:   #11532b;
  --ld-quit-fg: #a62f22;
  --ld-create-fg: #1e7e43;
  --wp-need-fg: #b35e10;
  --cream:      #1d222b;
  --field-bg:   #ffffff;
  --inset: rgba(0,0,0,0.06);
  --inset-hi: rgba(0,0,0,0.08);
  --on-gold:    #fdf6e6;
  --text:       #576378;
  --text-hi:    #1d222b;
  --red:        #a62f22;
  --green:      #1e7e43;
  --orange:     #b35e10;
  --border:     rgba(60,72,90,0.16);
  --border-hi:  rgba(var(--gold-rgb), 0.45);
  --card-back:  url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20100%20140%27%20preserveAspectRatio%3D%27none%27%3E%3Cdefs%3E%3CradialGradient%20id%3D%27h%27%20cx%3D%2750%25%27%20cy%3D%2744%25%27%20r%3D%2780%25%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%232c313c%27%2F%3E%3Cstop%20offset%3D%27100%25%27%20stop-color%3D%27%230c0e12%27%2F%3E%3C%2FradialGradient%3E%3Cpattern%20id%3D%27l%27%20width%3D%2714%27%20height%3D%2714%27%20patternUnits%3D%27userSpaceOnUse%27%3E%3Cpath%20d%3D%27M7%200L14%207L7%2014L0%207Z%27%20fill%3D%27none%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%270.6%27%20opacity%3D%270.4%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%270.8%27%20fill%3D%27%236b7689%27%20opacity%3D%270.45%27%2F%3E%3C%2Fpattern%3E%3C%2Fdefs%3E%3Crect%20width%3D%27100%27%20height%3D%27140%27%20fill%3D%27url%28%23h%29%27%2F%3E%3Crect%20x%3D%276%27%20y%3D%276%27%20width%3D%2788%27%20height%3D%27128%27%20rx%3D%275%27%20fill%3D%27url%28%23l%29%27%2F%3E%3Crect%20x%3D%275%27%20y%3D%275%27%20width%3D%2790%27%20height%3D%27130%27%20rx%3D%277%27%20fill%3D%27none%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%271.4%27%2F%3E%3Crect%20x%3D%278.5%27%20y%3D%278.5%27%20width%3D%2783%27%20height%3D%27123%27%20rx%3D%275%27%20fill%3D%27none%27%20stroke%3D%27%233a4254%27%20stroke-width%3D%270.6%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2725%27%20ry%3D%2737%27%20fill%3D%27%231b1e24%27%20stroke%3D%27%236b7689%27%20stroke-width%3D%270.9%27%2F%3E%3Cellipse%20cx%3D%2750%27%20cy%3D%2770%27%20rx%3D%2721%27%20ry%3D%2732.5%27%20fill%3D%27none%27%20stroke%3D%27%233a4254%27%20stroke-width%3D%270.5%27%2F%3E%3Ctext%20x%3D%2750%27%20y%3D%2784%27%20font-size%3D%2738%27%20text-anchor%3D%27middle%27%20fill%3D%27%23a0acc4%27%20font-family%3D%27Georgia%2Cserif%27%3E%E2%99%A0%3C%2Ftext%3E%3C%2Fsvg%3E");
}

/* Inter : chiffres tabulaires pour aligner stacks/mises sur les thèmes officiels. */
:root[data-theme="pokerth"], :root[data-theme="pokerth-light"] { font-variant-numeric: tabular-nums; }

/* ── Palette : Feutre rouge (axe "Palette") ── feutre + UI + popups en rouge.
   Comme :root/dark, ne fait qu'ecraser les variables. Voir theme.mjs. */
:root[data-theme="redfelt"] {
  --felt:       #2c1012;
  --felt-mid:   #3a1418;
  --felt-hi:    #4c1c20;
  --felt-base-hi:  #8e1e1e;
  --felt-base-mid: #4a0e0e;
  --felt-base-lo:  #280606;
  --rail:          #5a2410;
  --rail-dark:     #2e1206;
  --rail-glow:     rgba(150,40,40,0.30);
  --panel:      rgba(26,8,10,0.93);
  --panel-hi:   rgba(38,12,14,0.94);
  --gold:       #c8a84a;
  --gold-hi:    #e0c070;
  --gold-dim:   #7a6428;
  --cream:      #f2e6e2;
  --field-bg:   #1e0a0c;
  --inset: rgba(255,255,255,0.05);
  --inset-hi: rgba(255,255,255,0.08);
  --on-gold:    #110900;
  --text:       #bd9d9a;
  --text-hi:    #ecd6d2;
  --red:        #c0392b;
  --green:      #27ae60;
  --orange:     #e67e22;
  --border:     rgba(var(--gold-rgb), 0.25);
  --border-hi:  rgba(var(--gold-rgb), 0.65);
  --modal-bg:   linear-gradient(160deg, #2c0e10 0%, #3c1519 50%, #1f0709 100%);
  --body-glow:  rgba(140,40,40,0.16);
}

/* ── Tapis (axe "Tapis", choisi via le menu dedie) ─ surcharge la SURFACE
   de la table (feutre + lisere) independamment de la Palette.
   Defaut (vert) = :root ci-dessus. Voir public/modules/theme.mjs. */
:root[data-table="pokerth"] {
  --felt-base-hi:  #008c58;
  --felt-base-mid: #006a44;
  --felt-base-lo:  #073120;
  --rail:          #1d222b;
  --rail-dark:     #12161d;
  --rail-glow:     rgba(0,140,88,0.20);
}
:root[data-table="blue"] {
  --felt-base-hi:  #1f6aa8;
  --felt-base-mid: #124b78;
  --felt-base-lo:  #08233a;
}
:root[data-table="bordeaux"] {
  --felt-base-hi:  #8a1e2e;
  --felt-base-mid: #5e0f1d;
  --felt-base-lo:  #330810;
}
:root[data-table="slate"] {
  --felt-base-hi:  #3a4150;
  --felt-base-mid: #232730;
  --felt-base-lo:  #14171d;
  --rail:          #2b2f38;
  --rail-dark:     #15171c;
  --rail-glow:     rgba(120,130,150,0.18);
}
/* Feutre texture (photo) — garde l'oval + le lisere CSS, remplace seulement
   le remplissage par un vrai feutre extrait de l'image PokerTH (sans lisere,
   donc pas de double lisere ni de distorsion). Asset : /table/felt-green.jpg
   (PokerTH, AGPL-3.0). */
:root[data-table="photo"] .felt-oval {
  background:
    radial-gradient(ellipse 90% 80% at 50% 50%, transparent 55%, rgba(0,0,0,0.40) 100%),
    url("/table/felt-green.jpg") center / cover no-repeat;
}

/* Table « image complète » — une table importée marquée full:true (tables.json /
   themes.json) remplace TOUT le rendu CSS du tapis (bordure, liserés box-shadow,
   liseré ::before, dégradés texture/halo, forme ovale) pour n'afficher QUE l'image,
   centrée et entière (contain). Les feutres-texture (photo, gallery sans full) ne
   sont pas affectés : eux gardent l'ovale + le liseré. L'image vit dans --table-img
   (URL nue, sans cover) ; data-table-full="1" est posé par theme.mjs et l'applier <head>. */
:root[data-table-full="1"] .felt-oval {
  background: var(--table-img, none) center / contain no-repeat;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: drop-shadow(0 12px 18px rgba(0,0,0,0.40));
}
:root[data-table-full="1"] .felt-oval::before { display: none; }
/* Full image (data-table-full): the table PNG carries its own felt + rail with
   transparent corners, so the frame/zone behind it must stay transparent —
   otherwise a light panel shows through the corners. Scoped to full mode only. */
:root[data-table-full="1"] .table-scaler,
:root[data-table-full="1"] .table-zone { background: transparent !important; }

/* Table « Fullscreen » : l'image du pack part en fond plein ecran (--wallpaper,
   active par data-bg-img -> regle body.in-game ci-dessous) et l'ovale devient
   invisible. data-table-fs est pose par theme.mjs (pack table en mode fullscreen). */
:root[data-table-fs="1"] .felt-oval {
  background: transparent;
  border: 0;
  box-shadow: none;
}
:root[data-table-fs="1"] .felt-oval::before { display: none; }

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Taille minimale supportée (déclarative, pas de plancher CSS — html/body sont en
   overflow:hidden, un min-width clipperait) : 390×600 sur desktop (parité fenêtre
   min du client Qt/QML) et largeur ≥ 360 sur mobile. En dessous, rendu dégradé. */
html, body {
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
  font-family: var(--ff-mono);
  background: var(--felt);
  color: var(--text);
}

body {
  background-image:
    radial-gradient(ellipse 140% 70% at 50% 0%, var(--body-glow) 0%, transparent 65%),
    repeating-linear-gradient(45deg, transparent, transparent 3px,
      rgba(0,0,0,0.04) 3px, rgba(0,0,0,0.04) 6px);
}
/* Palette PokerTH claire : fond plat #f0f3f8 (QML col700 light), sans rayures. */
:root[data-theme="pokerth-light"] body { background-image: none; }

/* Fond « Fullscreen » : l'image (--wallpaper) est posee sur la ZONE DE TABLE
   (au-dessus de la barre d'action) et non sur tout le body -> le bas de l'image
   (lisere) reste visible juste au-dessus de la barre. Ancrage bas + cover.
   .table-zone (flex:1) occupe la zone de jeu au-dessus de la barre d'action ;
   l'ovale (.felt-oval) est transparent et laisse voir ce fond. data-table-fs est
   pose par theme.mjs. S'applique a TOUS les tapis en mode fullscreen. */
/* Fullscreen : le feutre couvre TOUT l'ecran de jeu (#s-game, 100dvh) -> il
   descend jusqu'en bas, derriere la barre d'action, et l'entoure. La zone de
   table devient transparente (le fond vient de #s-game), et la barre d'action
   + player-bar sont transparentes ; seul le panneau des boutons (.action-grid)
   flotte sur le feutre. Scoping data-table-fs -> n'affecte que le mode fullscreen. */
:root[data-table-fs="1"] #s-game {
  background-image:
    linear-gradient(rgba(0,0,0,0.14), rgba(0,0,0,0.14)),
    var(--wallpaper, none);
  /* --wallpaper-dyn-* : cadrage QML « center » calculé par renderSeats
     (parité tableBackgroundImage : couvre la bande zone+action bar, centré
     sur communityCenterY, × TableBackgroundZoom). Prioritaire ; repli sur
     le comportement historique (--wallpaper-size / cover, pos / bas). */
  background-size: var(--wallpaper-dyn-size, var(--wallpaper-size, cover));   /* 2.1.3: TableBackgroundZoom (import) surcharge cover */
  background-position: var(--wallpaper-dyn-pos, var(--wallpaper-pos, center bottom));
  background-repeat: no-repeat;
}
/* Portrait (iPhone) : garantir un fond PLEIN ÉCRAN même quand le cadrage
   dynamique (--wallpaper-dyn-*) n'est pas encore posé (image en cours de
   chargement) ou indisponible. Sinon le repli --wallpaper-size (ex. 130%,
   TableBackgroundZoom) = 130% de la LARGEUR, hauteur proportionnelle → une
   bande courte sur écran étroit. Ici le repli devient 'cover' = plein écran.
   Le dynamique, quand présent, reste prioritaire (crop centré × zoom). */
@media (orientation: portrait) {
  :root[data-table-fs="1"] #s-game {
    background-size: var(--wallpaper-dyn-size, cover);
    background-position: var(--wallpaper-dyn-pos, center);
  }
}
:root[data-table-fs="1"] .table-zone { background-image: none; }
:root[data-table-fs="1"] .my-zone,
:root[data-table-fs="1"] .player-bar { background: transparent !important; border-top: 0 !important; }
:root[data-table-fs="1"] .my-zone .action-grid {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 8px 10px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.38);
}
/* Panneau d'attente (« EN ATTENTE / + BOTS ») : hors partie il occupe la barre
   d'action -> lui aussi doit flotter sur le feutre avec le fond de palette,
   sinon il devient transparent en fullscreen. */
:root[data-table-fs="1"] .my-zone .waiting-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: 0 6px 20px rgba(0,0,0,0.38);
}

/* ─── SCREENS ─── */
.screen { display: none; height: 100vh; height: 100dvh; }
:fullscreen            { background: var(--felt); }
:-webkit-full-screen   { background: var(--felt); }
:-moz-full-screen      { background: var(--felt); }
.screen.active { display: flex; }

/* ── Écran dédié « Créer une partie » (page pleine, garde le formulaire existant) ── */
#s-create { flex-direction: column; background: var(--field-bg); }
.cp-header {
  display: flex;
  align-items: center;
  gap: 14px;
  /* Hauteur UNIFORME avec tous les autres headers (--header-h, base QML
     2.1.3 : 38 px / 30 en landscapeCompact) : padding vertical 4 px et
     bouton Retour a 30 px comme les boutons des autres headers. */
  padding: 4px clamp(8px,2vw,20px);
  min-height: var(--header-h, 38px);
  box-sizing: border-box;
  border-bottom: 1px solid var(--border);
  /* Meme fond que les .header globaux (etait --chrome-tint, trop discret). */
  background: var(--panel);
  flex-shrink: 0;
}
/* Pousse le globe + roue crantée à droite (parité header lobby). */
.cp-head-spacer { flex: 1; }
.cp-title {
  font-family: var(--ff-display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-hi);
  letter-spacing: 0.02em;
}
/* Titre centré dans le header (entre la porte à gauche et globe/roue à
   droite) : positionnement absolu au centre du .cp-header — insensible aux
   largeurs inégales des deux groupes d'icônes. max-width borné pour ne
   jamais chevaucher les icônes ; pointer-events off (label non cliquable). */
#s-create .cp-title,
#privacy-page .cp-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: 60%;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
.cp-scroll { flex: 1; overflow-y: auto; padding: 20px 18px 40px; }
.cp-body { max-width: 720px; margin: 0 auto; }
.cp-body #create-form { display: block; }

/* ── Champs « Créer une partie » façon officiel (steppers / toggles / sections) ── */
.cf-block { margin-bottom: 14px; }
.cf-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 9px 0; }
.cf-row-col { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
.cf-lbl { font-size: var(--cf-fs-body); color: var(--text); font-weight: 500; }
.cf-input, .cf-select {
  width: 100%; box-sizing: border-box;
  background: var(--field-bg); border: 1px solid var(--border); border-radius: 8px;
  color: var(--text); padding: 9px 12px; font-size: var(--cf-fs-body); outline: none;
}
.cf-input:focus, .cf-select:focus { border-color: var(--gold-dim); }
.cf-sec {
  margin: 16px 0 2px; padding-top: 14px;
  font-size: var(--cf-fs-body); font-weight: 700; color: var(--text);
  letter-spacing: 0.02em; text-transform: none;
  border-top: 1px solid var(--border);
}
/* Stepper − valeur + */
.cf-step { display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--field-bg); }
.cf-step-btn {
  width: 34px; height: 34px; background: transparent; border: none;
  color: var(--text); font-size: 1.15rem; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.cf-step-btn:hover { background: rgba(127,127,127,0.14); }
.cf-step-num {
  width: 72px; border: none; background: transparent; color: var(--text);
  text-align: center; font-size: var(--cf-fs-value); font-family: var(--ff-display);
  outline: none; -moz-appearance: textfield;
}
.cf-step-num::-webkit-inner-spin-button, .cf-step-num::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.cf-step-sm .cf-step-num { width: 48px; }
/* Toggle switch */
.cf-switch { position: relative; display: inline-block; width: 44px; height: 24px; cursor: pointer; flex: none; }
.cf-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.cf-switch-tr { position: absolute; inset: 0; background: var(--border); border-radius: var(--r-pill); transition: background 0.16s; }
.cf-switch-tr::before {
  content: ''; position: absolute; width: 18px; height: 18px; left: 3px; top: 3px;
  background: #fff; border-radius: 50%; transition: transform 0.16s; box-shadow: 0 1px 3px rgba(0,0,0,0.35);
}
.cf-switch input:checked + .cf-switch-tr { background: #2f81f7; }
.cf-switch input:checked + .cf-switch-tr::before { transform: translateX(20px); }
/* Intervalle blindes : radios + stepper */
.cf-interval { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-6); }
.cf-radio { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--cf-fs-body); color: var(--text); cursor: pointer; }
.cf-radio input { accent-color: #2f81f7; }
.cf-create-btn { flex: 1; padding: var(--sp-5); }

/* ══════════════════════════════════════════
   CONNECT SCREEN
══════════════════════════════════════════ */
#s-connect {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow-y: auto;
  padding: 20px 16px;
  /* PokerTH official login backdrop (flames) — login screen only, theme-agnostic.
     Dark veil keeps the centered .card readable over the bright artwork. */
  background:
    linear-gradient(rgba(8,10,14,0.10), rgba(8,10,14,0.15)),
    url("/img/pokerth-login-bg.webp") center / cover no-repeat;
}

/* Chrome Android : les items flex de la carte login (select de mode, input
   pseudo/host) ont min-width:auto = leur largeur intrinsèque et ne peuvent
   pas rétrécir → la rangée déborde de la carte et le bouton avatar sort de
   l'écran. min-width:0 rend les rangées compressibles ; les boutons 🐼/⚙
   gardent leur taille (flex-shrink:0). Même leçon que la barre d'action. */
.card .sel-wrap { min-width: 0; }
.card .f input { min-width: 0; }

.form-card, .card {
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: 4px;
  padding: 20px 22px;
  width: min(380px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 11px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.8);
}

.card-title {
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  letter-spacing: 0.3em;
  color: var(--gold-dim);
  text-transform: uppercase;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

.card-logo {
  text-align: center;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.card-suits-row { font-size: var(--fs-lg); letter-spacing: 0.2em; opacity: 0.7; margin-bottom: 4px; }
.card-suits-row .r { color: var(--red); }
.card-title-big {
  font-family: var(--ff-display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-hi);
  letter-spacing: 0.12em;
  line-height: 1;
}
.card-subtitle { font-size: var(--fs-2xs); letter-spacing: 0.4em; text-transform: uppercase; color: var(--text); }
.card-chip {
  display: block;
  margin: 0 auto;
  /* Parité client QML (Theme.brandLogoSize) : plafond 126 px desktop /
     100 px phone, plancher 56 px, mise à l'échelle fluide (narmod 19/07).
     Les media-queries max-height ci-dessous prennent le relais sur écrans
     très courts, comme le compact QML. */
  width: clamp(56px, 13vw, 126px);
  height: clamp(56px, 13vw, 126px);
  filter: drop-shadow(0 4px 12px rgba(0,0,0,0.55));
}
@media (max-width: 600px) {
  .card-chip { width: clamp(56px, 22vw, 100px); height: clamp(56px, 22vw, 100px); }  /* compact QML : plafond 100 */
}

/* Small / short screens (e.g. iPhone SE, landscape): compact the login
   card so it fits without scrolling. The header block (chip, title, suits,
   subtitle) is the biggest space user, so it shrinks the most. !important
   overrides the inline sizing set in the markup. */
/* Paliers progressifs de réduction de la carte de connexion (760/640) :
   raffinements fluides pour écrans peu hauts, pas des frontières de classe. */
@media (max-height: 760px) {
  #s-connect { padding: 8px 14px; }
  .card { gap: var(--sp-3); padding: 14px 18px; }
  .card-logo { padding: 8px 0 10px !important; }
  .card-chip { width: 54px; height: 54px; }
  .card-title-big { font-size: 1.5rem !important; margin-top: 6px !important; }
  .card-suits-row { font-size: var(--fs-md) !important; margin-top: 5px !important; }
  .card-subtitle { font-size: var(--fs-3xs) !important; margin-top: 4px !important; }
  .f { gap: var(--sp-1); }
  .f input { padding: 7px 10px; font-size: var(--fs-base); }
  .sel-wrap select { padding: 7px 30px 7px 10px; }
  .login-avatar-top #av-trigger { width: 72px; height: 72px; font-size: 2.1rem; }
  #login-step2 { gap: var(--sp-3); }
  .btn-primary { padding: var(--sp-4); }
  .tls-row { font-size: var(--fs-xs); }
}
@media (max-height: 640px) {
  .card-chip { width: 44px; height: 44px; }
  .card-title-big { font-size: var(--fs-xl) !important; }
  .card-suits-row { display: none !important; }
  .card { gap: var(--sp-2); }
  #login-step2 { gap: var(--sp-2); }
}

.sel-wrap { position: relative; }
.sel-wrap select {
  -webkit-appearance: none; appearance: none;
  width: 100%;
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: 2px;
  color: var(--cream);
  padding: 9px 32px 9px 11px;
  font-family: var(--ff-mono);
  font-size: var(--fs-base);
  outline: none; cursor: pointer;
}
.sel-wrap select:focus { border-color: var(--gold); }
.sel-wrap select option { background: var(--field-bg); color: var(--cream); }
.sel-arr { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); color: var(--gold); pointer-events: none; font-size: var(--fs-sm); }

/* ── Dropdown « Type de partie » (parité QML StyledCombo : icônes champ + liste) ── */
.gt-dd { position: relative; }
.gt-dd-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.gt-dd-btn {
  width: 100%; box-sizing: border-box; display: flex; align-items: center; gap: 9px;
  background: var(--field-bg); border: 1px solid var(--border); border-radius: 8px;
  color: var(--text); padding: 9px 32px 9px 12px; font-size: var(--fs-md); font-family: inherit;
  cursor: pointer; text-align: left; position: relative;
}
.gt-dd-btn:focus { outline: none; border-color: var(--gold-dim); }
.gt-dd-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gt-dd-ico {
  width: 16px; height: 16px; flex: 0 0 16px; background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.gt-ico-1 { -webkit-mask-image: url('img/gametype/user.svg');       mask-image: url('img/gametype/user.svg'); }
.gt-ico-2 { -webkit-mask-image: url('img/gametype/userSquare.svg'); mask-image: url('img/gametype/userSquare.svg'); }
.gt-ico-3 { -webkit-mask-image: url('img/gametype/users.svg');      mask-image: url('img/gametype/users.svg'); }
.gt-ico-4 { -webkit-mask-image: url('img/gametype/chipStack.svg');  mask-image: url('img/gametype/chipStack.svg'); }
.gt-dd-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40;
  background: var(--field-bg); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35); overflow: hidden;
}
.gt-dd-item {
  display: flex; align-items: center; gap: 9px; padding: 9px 12px;
  color: var(--text); font-size: var(--fs-md); cursor: pointer;
}
.gt-dd-item:hover, .gt-dd-item.sel { background: rgba(255,255,255,0.07); }
:root[data-theme="pokerth-light"] .gt-dd-item:hover,
:root[data-theme="pokerth-light"] .gt-dd-item.sel { background: rgba(0,0,0,0.07); }

/* Quick-bets 1/3·1/2·Pot masquables (parité QML ShowPotPercentButtons) */
body.adv-no-potbtns .pct-row { display: none !important; }
/* Contenus communauté masquables (parité QML showCommunityContent) */
body.adv-no-communitycontent #ranking-modal .rk-tab[data-src="bbc"],
body.adv-no-communitycontent #ranking-modal .rk-tab[data-src="wec"] { display: none !important; }
body.adv-no-communitycontent .adv-row:has(#adv-defcommunity) { display: none !important; }

/* Verrous du formulaire de création (parité QML : classé / invité) */
.cf-locked { opacity: 0.55; pointer-events: none; }
.gt-dd-btn:disabled { opacity: 0.55; cursor: default; pointer-events: none; }
#cf-name:disabled { opacity: 0.7; }
.cf-name-err { color: #ef4444; font-size: var(--cf-fs-xs); margin-top: 4px; }

.avatar-picker {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
}
.av-btn {
  background: var(--inset);
  border: 2px solid var(--border);
  border-radius: var(--r-sm);
  font-size: 1.25rem;
  cursor: pointer;
  padding: 4px 2px;
  transition: border-color 0.15s, transform 0.1s, background 0.15s;
  line-height: 1.2;
  text-align: center;
  color: var(--text-hi);
}
.av-btn:hover { border-color: var(--gold-dim); transform: scale(1.1); background: rgba(var(--gold-rgb), 0.08); }
.av-btn.selected { border-color: var(--sel,var(--gold)); background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.18); box-shadow: 0 0 6px rgba(var(--sel-rgb,var(--gold-rgb)), 0.3); }
.av-btn.av-none { font-size: var(--fs-xs); font-family: var(--ff-display); color: var(--text); letter-spacing: 0.05em; }

/* Emoji avatar dans le siège */
.seat-avatar.emoji-av .seat-initial { font-size: 1.5em; line-height: 1; }


/* ── Clickable pseudo pill in the lobby header ──
   The #h-nick pill in the lobby now contains a tiny avatar (emoji or
   PokerTH image) + the name. .pill-clickable adds the cursor + hover
   feedback without disturbing the existing .pill positioning. */
.pill.pill-clickable {
  cursor: pointer;
  user-select: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: background 0.15s, border-color 0.15s;
}
.pill.pill-clickable:hover {
  background: rgba(var(--gold-rgb), 0.22);
  border-color: var(--gold-dim);
}
.pill .h-nick-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  font-size: 0.9em;
  line-height: 1;
}
.pill .h-nick-av img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  pointer-events: none;
  display: block;
}

/* ── Clickable "TABLE" label in the game header ──
   Subtle underline on hover so the user notices it's interactive,
   without changing the visual weight of the header. */
#g-name.g-name-clickable {
  cursor: pointer;
  border-bottom: 1px dashed transparent;
  transition: border-color 0.15s, color 0.15s;
}
#g-name.g-name-clickable:hover {
  border-bottom-color: var(--gold);
  color: var(--gold);
}

/* ── En-tête de jeu : nom de table centré + badges de statut (palette QML) ──
   Le libellé statique « TABLE » devient le nom réel de la partie, centré sur
   la barre (position absolue → indépendant de la largeur des boutons), suivi
   de badges Admin (or #E3C800) et Public/Privé (vert #27ae60). Reste cliquable
   → openGameInfoPopup(). Le nom tronque en « … » ; les badges ne rétrécissent
   pas (le nom cède en premier). */
.header-brand--game {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: min(72vw, 560px);
  justify-content: center;
  pointer-events: none;   /* les zones vides laissent passer les clics aux boutons */
  z-index: 1;
}
.header-brand--game .g-brand-click {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 100%;
  cursor: pointer;
}
/* Annule l'atténuation globale `.header-brand span { opacity:.6 }` (definie
   plus bas → on double la classe pour gagner en specificite). */
.header-brand.header-brand--game span { opacity: 1; font-size: inherit; }
.header-brand--game #g-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-hi);
  transition: color 0.15s;
}
.header-brand--game .g-brand-click:hover #g-name { color: var(--gold); }
.g-brand-sep { color: var(--text); opacity: 0.45; flex-shrink: 0; }
.g-status-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  font-family: var(--ff-mono);
  font-size: 0.42em;
  letter-spacing: 0.04em;
  padding: 1px 5px;
  border-radius: 4px;
  gap: 3px;
  white-space: nowrap;
  line-height: 1;
}
.gsb-label { margin-left: 0; }
.g-status-badge svg { flex: none; width: 1.4em; height: 1.4em; }
/* Spécificité (0,3,0) pour battre `.header-brand.header-brand--game span
   { font-size: inherit }` (0,2,1) qui, sinon, force le texte du badge à la
   taille pleine du nom de table. Ici : texte = 0.45em du nom de table. */
.header-brand--game .g-brand-click .g-status-badge { font-size: 0.45em; }
.g-status-admin {
  color: var(--sel, var(--gold));
  background: rgba(var(--sel-rgb, var(--gold-rgb)), 0.12);
  border: 1px solid rgba(var(--sel-rgb, var(--gold-rgb)), 0.35);
}
.g-status-public {
  color: rgb(var(--blue-rgb));
  background: rgba(var(--blue-rgb), 0.12);
  border: 1px solid rgba(var(--blue-rgb), 0.35);
}
.g-status-private {
  color: var(--text);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
}
/* Petits écrans : on resserre pour ne pas mordre sur les boutons du header. */
@media (max-width: 599.98px) {
  .header-brand--game { max-width: 82vw; }
  /* Emoji seul (le libelle deborde sur petit ecran). */
  .header-brand--game .gsb-label { display: none; }
  .g-status-badge { padding: 1px 5px; }
  .header-brand--game .g-brand-click { gap: var(--sp-1); }
}

/* ── Statut d'attente centre dans le header du lobby ──
   Affiche « En attente de joueurs » + points animes tant que la partie
   creee/rejointe n'a pas demarre. Centre en absolu (independant des
   boutons), non cliquable (laisse passer les clics). Palette QML (or). */
.lobby-wait-status {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: min(70vw, 460px);
  font-family: var(--ff-display);
  font-size: clamp(0.72rem, 1.8vw, 0.95rem);
  letter-spacing: 0.05em;
  color: var(--gold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  z-index: 1;
}
.lws-hourglass {
  font-size: 0.95em;
  display: inline-block;
  animation: lwsHourglass 2.6s ease-in-out infinite;
}
@keyframes lwsHourglass {
  0%, 78%, 100% { transform: rotate(0deg); }
  90%          { transform: rotate(180deg); }
}
.wait-dots { display: inline-flex; }
.wait-dots span {
  opacity: 0.25;
  animation: waitDot 1.4s ease-in-out infinite;
}
.wait-dots span:nth-child(2) { animation-delay: 0.2s; }
.wait-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes waitDot {
  0%, 100% { opacity: 0.25; }
  30%      { opacity: 1; }
}
@media (max-width: 599.98px) {
  .lobby-wait-status { max-width: 62vw; font-size: var(--fs-xs); gap: 5px; }
}
@media (prefers-reduced-motion: reduce) {
  .lws-hourglass { animation: none; }
  .wait-dots span { animation: none; opacity: 0.85; }
}

/* ── Game-info modal (opened by clicking the "TABLE" label) ──
   Centered card with backdrop. The card holds a title (table name)
   + a subtitle (admin/private badges), and a body filled by JS with
   a 2-column grid of label/value rows grouped by section. */
#game-info-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
}
.gim-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.65);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.gim-card {
  position: relative;
  background: var(--modal-bg);
  border: 1px solid var(--gold-dim);
  border-radius: 8px;
  padding: 18px 18px 16px;
  width: min(360px, 100%);
  max-height: min(80vh, 600px);
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  animation: slideDown 0.18s ease;
  -webkit-overflow-scrolling: touch;
}
.gim-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-md);
  padding: 2px 6px;
  line-height: 1;
  z-index: 2;
}
.gim-close:hover { color: var(--gold); }
.gim-header {
  text-align: center;
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px;
  padding-right: 24px; /* keep title from going under the ✕ */
}
.gim-title {
  font-size: 1.15rem;
  color: var(--cream);
  font-family: var(--ff-display);
  font-weight: 600;
  letter-spacing: 0.04em;
  word-break: break-word;
}
.gim-subtitle {
  font-size: var(--fs-xs);
  color: var(--gold-dim);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-top: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.gim-badge {
  background: rgba(var(--gold-rgb), 0.12);
  border: 1px solid var(--gold-dim);
  border-radius: var(--r-xs);
  padding: 1px 6px;
  color: var(--gold);
  letter-spacing: 0.1em;
  font-size: var(--fs-2xs);
}
.gim-section {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
/* Breathing room above each section heading except the first, so
   'CONFIGURATION' / 'GAME STATE' don't sit tight against the row above. */
.gim-section + .gim-section { margin-top: 12px; }
.gim-section-title {
  font-size: var(--fs-2xs);
  color: var(--gold-dim);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.15);
  padding-bottom: 4px;
  margin-bottom: 2px;
}
.gim-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-5);
  padding: 3px 0;
  font-size: var(--fs-sm);
}
.gim-row-label {
  color: var(--text);
  font-family: var(--ff-mono);
}
.gim-row-value {
  color: var(--cream);
  font-family: var(--ff-mono);
  font-weight: 500;
  text-align: right;
}

/* ── Player-info modal (opened by clicking #h-nick) ──
   Centered card with backdrop. The pim-card is sized so it fits
   comfortably on phones; the avatar is big (~96px) so the user
   can clearly see what they have. */
#player-info-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pim-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.65);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.pim-card {
  position: relative;
  background: var(--modal-bg);
  border: 1px solid var(--gold-dim);
  border-radius: 8px;
  padding: 24px 20px 18px;
  min-width: 260px;
  max-width: 320px;
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-5);
  animation: slideDown 0.18s ease;
}
/* Children keep their intrinsic height; the card scrolls instead of squashing
   them (notably the avatar) when the cups make it taller than the viewport. */
.pim-card > * { flex-shrink: 0; }
.pim-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-md);
  padding: 2px 6px;
  line-height: 1;
}
.pim-close:hover { color: var(--gold); }
.pim-avatar {
  width: 96px;
  height: 96px;
  border-radius: var(--r-lg);
  background: rgba(0,0,0,0.5);
  border: 2px solid var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 3rem;
  line-height: 1;
  overflow: hidden;
  box-shadow: 0 0 14px rgba(var(--gold-rgb), 0.35);
}
.pim-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--r-bar);
  pointer-events: none;
  display: block;
}
.pim-avatar.is-letter {
  font-size: 2.4rem;
  font-family: var(--ff-display);
  font-weight: 700;
  color: var(--gold);
}
/* Avatar cliquable : ouvre le sélecteur d'avatar, comme le bouton. */
.pim-avatar-clickable { cursor: pointer; transition: box-shadow 0.2s, transform 0.2s; }
.pim-avatar-clickable:hover,
.pim-avatar-clickable:focus-visible {
  box-shadow: 0 0 20px rgba(var(--gold-rgb), 0.75);
  transform: scale(1.03);
  outline: none;
}
.pim-name {
  font-size: var(--fs-lg);
  color: var(--cream);
  font-weight: 600;
  text-align: center;
  word-break: break-word;
}
/* Drapeau pays sous l'avatar (popup de profil) */
.pim-flag {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  color: var(--gold-dim);
  margin-top: -2px;
}
.pim-flag-code { font-family: var(--ff-mono); }
/* Image drapeau auto-hébergée (rendu identique sur tous les OS). */
.cc-flag {
  display: inline-block;
  vertical-align: middle;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 0 0 0.5px rgba(0,0,0,0.35);
}
.cc-flag-lg { width: 26px; height: 19px; border-radius: var(--r-xs); }
/* ── Bloc stats du popup de profil : onglets SESSION/TOTAL/CLASSEMENT,
   identiques au panneau en jeu (réutilise .stats-tabs/.stats-body/.stats-reset). ── */
.pim-stats {
  width: 100%;
  margin: 4px 0 2px;
}
.pim-stats .stats-tabs { margin-bottom: 4px; }
.pim-stats .stats-body { padding: 8px 2px 2px; }
/* ── Popup d'info joueur : bloc « adversaire » (rôle, infos en jeu, lien
   profil). Entièrement piloté par les variables de thème → suit la palette
   active. Seules les pastilles SB/BB gardent le bleu/rouge des jetons de
   blinds posés sur le tapis (jetons de jeu, identiques sur tous les thèmes). ── */
.pim-info {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
}
.pim-role {
  font-size: var(--fs-base);
  letter-spacing: 0.04em;
  color: var(--gold-dim);
  text-transform: uppercase;
  font-family: var(--ff-mono);
}
.pim-ig {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: 10px 12px;
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.pim-ig-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-5);
  font-size: var(--fs-base);
}
.pim-ig-k { color: var(--gold-dim); }
.pim-ig-v { color: var(--cream); font-family: var(--ff-mono); font-weight: 700; }
.pim-ig-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin-top: 2px;
}
.pim-status {
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gold);
  border: 1px solid var(--gold-dim);
  border-radius: var(--r-pill);
  padding: 2px 9px;
}
.pim-pos-wrap { display: inline-flex; gap: var(--sp-1); }
.pim-pos {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 18px;
  padding: 0 5px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  font-family: var(--ff-mono);
  border-radius: var(--r-pill);
  color: #fff;
}
.pim-pos-d  { background: var(--gold); color: #1a1a1a; }
.pim-pos-sb { background: #1565c0; }
.pim-pos-bb { background: #b71c1c; }
.pim-profile-link {
  font-size: var(--fs-sm);
  color: var(--gold);
  text-decoration: none;
  border-bottom: 1px dotted var(--gold-dim);
  padding-bottom: 1px;
}
.pim-profile-link:hover { color: var(--cream); border-bottom-color: var(--gold); }

/* ── Avatar picker shown as a floating modal (from the lobby) ──
   The existing #avatar-popup lives statically inside the connect
   form and is positioned via the surrounding flow. When opened from
   the lobby we add .avatar-popup-as-modal to make it float centered.
   The JS detaches and re-attaches it to body so this rule applies
   regardless of where it lives in the DOM. */
#avatar-popup.avatar-popup-as-modal {
  /* Fixed full-viewport "backdrop" surface; the popup's own
     header+grid form the visible card, centered via flex. */
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex !important;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.65);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  padding: var(--sp-6);
  border: none;
  border-radius: 0;
  /* Reset the small overflow:hidden / fixed border of the static
     popup -- we re-apply card styling below on the children. */
  overflow: visible;
}
#avatar-popup.avatar-popup-as-modal .avp-header,
#avatar-popup.avatar-popup-as-modal .avp-cats,
#avatar-popup.avatar-popup-as-modal .avp-grid {
  /* These children become the visible "card". All stretched to the
     same fixed width so they look like one panel (header on top, the
     category tabs in the middle, the emoji grid below). */
  background: var(--modal-bg);
  width: min(360px, 100%);
  max-width: 360px;
  border-left: 1px solid var(--gold-dim);
  border-right: 1px solid var(--gold-dim);
}
#avatar-popup.avatar-popup-as-modal .avp-header {
  border-top: 1px solid var(--gold-dim);
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}
#avatar-popup.avatar-popup-as-modal .avp-grid {
  max-height: 60vh;
  overflow-y: auto;
  border-bottom: 1px solid var(--gold-dim);
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
  /* Smooth scroll on iOS */
  -webkit-overflow-scrolling: touch;
}


/* ══ POPUP AVATAR ══ */
#avatar-popup {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 0;
  overflow: hidden;
  animation: slideDown 0.2s ease;
}
.avp-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px;
  font-size: var(--fs-2xs); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--gold-dim);
  border-bottom: 1px solid var(--border);
  background: var(--chrome-tint);
}
.avp-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: var(--sp-1);
  padding: var(--sp-4);
  /* Cap the height + scroll so a big filtered category can't push the
     grid past the SE CONNECTER button / footer on the connect screen.
     The lobby modal overrides this with its own 60vh cap below. */
  max-height: 42vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* ── Category tab row above the emoji grid ── */
.avp-cats {
  display: flex;
  gap: 3px;
  padding: 7px 8px;
  border-bottom: 1px solid var(--border);
  background: rgba(0,0,0,0.25);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* Firefox: hide the scrollbar, swipe instead */
}
.avp-cats::-webkit-scrollbar { display: none; } /* WebKit: hide too */
.avp-cat {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  background: var(--inset);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font-size: 1.15rem;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.1s;
  padding: 0;
}
.avp-cat:hover { background: rgba(var(--gold-rgb), 0.1); transform: scale(1.1); }
.avp-cat.selected {
  border-color: var(--gold);
  background: rgba(var(--gold-rgb), 0.2);
}
.avp-btn {
  aspect-ratio: 1;
  background: var(--inset);
  border: 2px solid transparent;
  border-radius: var(--r-sm);
  font-size: var(--fs-xl);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.12s, transform 0.1s, background 0.12s;
  padding: 0;
}
.avp-btn:hover { border-color: var(--gold-dim); transform: scale(1.15); background: rgba(var(--gold-rgb), 0.1); }
.avp-btn.selected { border-color: var(--sel,var(--gold)); background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.2); }
/* Example-avatar gallery thumbnails: photo fills the grid cell instead
   of an emoji glyph (the gallery is now a category tab, not a modal). */
.avp-gal-item { padding: 0; overflow: hidden; }
.avp-gal-item img { width: 100%; height: 100%; object-fit: cover; border-radius: 4px; display: block; pointer-events: none; }
.avp-none { font-size: var(--fs-xs) !important; font-family: var(--ff-display); color: var(--text); }
/* PokerTH official avatar entry -- accent color to distinguish it
   from the emoji costumes (this is a real identity, not a mask).
   Hosts an <img> of the PokerTH chip logo; tighten padding so the
   image fills the button nicely and centers properly. */
.avp-pth {
  background: rgba(var(--green-rgb), 0.12) !important;
  border-color: rgba(var(--green-rgb), 0.4) !important;
  padding: 0 !important;
  display: flex !important;
  align-items: center;
  justify-content: center;
}
.avp-pth:hover { background: rgba(var(--green-rgb), 0.22) !important; border-color: var(--green) !important; }
.avp-pth.selected { background: rgba(var(--green-rgb), 0.3) !important; border-color: var(--green) !important; }
#av-trigger.has-avatar { border-color: var(--gold-dim); background: rgba(var(--gold-rgb), 0.1); }

/* Emoji avatar dans le siège */
.seat-avatar.emoji-av .seat-initial { font-size: 1.5em; line-height: 1; }

.tls-row { display: flex; align-items: flex-start; gap: var(--sp-3); cursor: pointer; font-size: var(--fs-sm); color: var(--text); line-height: 1.4; }

.row2 { display: flex; gap: var(--sp-5); }
.row2 .f:first-child { flex: 1; }
.row2 .f-sm { width: 110px; }
.row2 .f { min-width: 0; }        /* items flex compressibles (fix debordement Port en portrait iOS) */
.row2 .f input { width: 100%; }   /* borne la largeur de l'input a son conteneur */

/* Roue crantée « Plus d'options » à droite du sélecteur de mode : même langage
   visuel que le bouton avatar et la roue du lobby. Passe en or et l'icône pivote
   quand les options sont ouvertes. Le bloc avancé reprend le rythme vertical
   (gap 11px) de la carte et s'ouvre avec un léger fondu. */
/* Contrôle segmenté du mode de connexion (remplace le <select> visuel) */
.mode-seg {
  display: flex;
  gap: 5px;
  min-width: 0;
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 5px;
}
.mode-seg-btn {
  flex: 1 1 0;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  border-radius: var(--r-sm);
  padding: 8px 3px;
  cursor: pointer;
  font-family: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  transition: background 0.16s, color 0.16s, box-shadow 0.16s;
}
.mode-seg-ic { font-size: var(--fs-xl); line-height: 1; }
.mode-seg-lb {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.mode-seg-btn:hover { color: var(--text-hi); }
.mode-seg-btn[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(var(--gold-rgb), 0.22), rgba(var(--gold-rgb), 0.10));
  color: var(--gold-hi);
  box-shadow: inset 0 0 0 1px rgba(var(--gold-rgb), 0.55), 0 2px 10px rgba(var(--gold-rgb), 0.18);
}
.mode-seg-btn:focus-visible { outline: 2px solid var(--gold-hi); outline-offset: 2px; }

/* ── Wizard login en 2 étapes (palette = tokens du thème) ── */
#login-step1 .login-lead { text-align: center; font-size: var(--fs-lg); font-weight: 800; color: var(--cream); margin: 0 0 3px; }
#login-step1 .login-lead-sub { text-align: center; font-size: var(--fs-base); color: var(--text); margin: 0 0 16px; }
.login-cards { display: flex; flex-direction: column; gap: var(--sp-4); }
.login-card {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left; cursor: pointer;
  font-family: inherit; color: var(--cream); background: var(--inset);
  border: 1px solid var(--border); border-radius: 13px; padding: 14px;
  transition: border-color 0.16s, box-shadow 0.16s, transform 0.12s, background 0.16s;
}
.login-card:hover { border-color: var(--border-hi); background: rgba(var(--gold-rgb), 0.08);
  box-shadow: 0 6px 18px rgba(var(--gold-rgb), 0.15); transform: translateY(-1px); }
.login-card:active { transform: translateY(0); }
.login-card:focus-visible { outline: 2px solid var(--gold-hi); outline-offset: 2px; }
.lc-ic { font-size: 1.8rem; width: 40px; text-align: center; flex: 0 0 auto; }
.lc-tx { flex: 1; min-width: 0; }
.lc-t { display: block; font-size: var(--fs-md); font-weight: 800; color: var(--text-hi); }
.lc-d { display: block; font-size: var(--fs-xs); color: var(--text); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lc-go { font-size: 1.5rem; color: var(--gold-dim); flex: 0 0 auto; line-height: 1; }

.login-back { display: flex; align-items: center; gap: 9px; width: 100%; margin: 0; padding: var(--sp-0);
  background: none; border: 0; font-family: inherit; cursor: pointer; }
.login-back:focus-visible { outline: 2px solid var(--gold-hi); outline-offset: 2px; border-radius: var(--r-sm); }
.lb-chev { font-size: var(--fs-xl); color: var(--gold); line-height: 1; }
.lb-name { display: flex; align-items: center; gap: 7px; font-weight: 800; font-size: var(--fs-md); color: var(--text-hi); }
.lb-ico { font-size: var(--fs-lg); }
.lb-edit { margin-left: auto; font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }

.login-avatar-top { display: flex; flex-direction: column; align-items: center; gap: 7px; margin: 2px 0 6px; }
.login-avatar-top #av-trigger {
  width: 88px; height: 88px; border-radius: 16px; font-size: var(--fs-hero);
  background: var(--inset); border: 1px solid var(--border); cursor: pointer; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.16s, box-shadow 0.16s, transform 0.12s;
}
.login-avatar-top #av-trigger:hover { border-color: var(--border-hi);
  box-shadow: 0 6px 18px rgba(var(--gold-rgb), 0.2); transform: translateY(-1px); }
.login-avatar-top #av-trigger img { width: 100% !important; height: 100% !important; }
.login-avatar-cap { font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }
/* Le wrapping en étapes retirait aux champs le gap du .card parent : on
   redonne à l'étape 2 le même rythme vertical (aéré comme avant). Le <form>
   passe en display:contents pour que ses champs (pseudo, mots de passe,
   options avancées) participent aussi à ce rythme. */
#login-step2 { display: flex; flex-direction: column; gap: 11px; }
#login-form { display: contents; }

.conn-adv-gear {
  flex-shrink: 0;
  width: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--gold-dim);
  cursor: pointer;
  font-size: 1.15rem;
  line-height: 1;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.conn-adv-gear:hover {
  color: var(--gold);
  border-color: var(--gold-dim);
  background: rgba(255,255,255,0.1);
}
.conn-adv-gear.open {
  color: var(--gold);
  border-color: var(--gold);
  background: rgba(var(--gold-rgb), 0.12);
}
.conn-adv-gear-ico {
  display: inline-block;
  transition: transform 0.3s ease;
}
.conn-adv-gear.open .conn-adv-gear-ico { transform: rotate(90deg); }

#conn-advanced { display: flex; flex-direction: column; gap: 11px; }
#conn-advanced.anim { animation: connAdvIn 0.28s ease; }
@keyframes connAdvIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.f {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.f label {
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-dim);
}

.f input {
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 9px 11px;
  color: var(--cream);
  font-family: var(--ff-mono);
  font-size: var(--fs-md);
  outline: none;
  transition: border-color 0.2s, background 0.2s;
}

.f input:focus {
  border-color: var(--gold);
  background: rgba(var(--gold-rgb), 0.05);
}

/* Champ pseudo VERROUILLÉ (mode invité pokerth.net) : fond sombre façon
   client QML (col700 #1d222b, texte atténué col300 #a0acc4) pour signaler
   que le GuestXXXXX n'est pas modifiable. Prime sur :focus. */
.f input[readonly],
.f input[readonly]:focus {
  background: #1d222b;
  color: #a0acc4;
  border-color: rgba(255,255,255,0.10);
  cursor: default;
}

.btn-primary {
  background: #2b3444;
  color: #ffffff;
  border: none;
  padding: var(--sp-5);
  font-family: var(--ff-display);
  font-size: var(--fs-base);
  font-weight: 700;
  letter-spacing: 0.15em;
  cursor: pointer;
  border-radius: 2px;
  transition: background 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 4px 16px rgba(0,0,0,0.28);
}
.btn-primary:hover { background: #384252; box-shadow: 0 6px 24px rgba(0,0,0,0.4); }
.btn-primary:active { transform: scale(0.98); }

.status {
  min-height: 18px;
  font-size: var(--fs-sm);
  text-align: center;
  color: var(--text);
  transition: color 0.2s;
}
.status.ok  { color: var(--green); }
.status.err { color: var(--red); }

/* ══════════════════════════════════════════
   LOBBY SCREEN
══════════════════════════════════════════ */
#s-lobby { flex-direction: column; overflow-y: auto; }
#create-form.open { display: block !important; }

/* Header */
/* ── Hauteur de header UNIFORME (tous ecrans, tous appareils, tous OS) ──
   Base QML officiel 2.1.3 : topBar 38 px, 30 px en landscapeCompact
   (paysage mobile h<600, ou desktop ratio>2.1 && h<1300 — delta §2).
   Une seule variable consommee par TOUTES les regles de header (base,
   desktop, mobile portrait, paysage, connexion) -> plus aucune divergence. */
:root { --header-h: 38px; }
@media (orientation: landscape) and (max-height: 600px),
       (min-aspect-ratio: 210/100) and (max-height: 799px) {
  :root { --header-h: 30px; }
}
.header {
  display: flex;
  align-items: center;
  padding: 4px clamp(8px,2vw,20px);
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  /* Wider gap so the action buttons are more spaced out horizontally
     (requested by narmod). Was clamp(4px,1.2vw,14px). */
  gap: clamp(6px,2.2vw,18px);
  flex-shrink: 0;
  box-sizing: border-box;
  /* Aligne sur le topBar QML officiel : 38 px (30 en landscapeCompact). */
  min-height: var(--header-h, 38px);
  overflow: hidden;
}

.header-brand {
  font-family: var(--ff-display);
  font-size: clamp(0.7rem, 2vw, 1.05rem);
  color: var(--text-hi);
  letter-spacing: 0.08em;
  display: flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  flex-shrink: 0;
}
.header-brand span { opacity: 0.6; font-size: 1.1em; }
.header-chip {
  height: 1.6em;
  width: auto;
  vertical-align: middle;
  display: inline-block;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.6));
}
/* The lobby ♠ is a tap target to reveal/hide the POKERTH word on phones. */
#lobby-brand .brand-suit {
  cursor: pointer;
  opacity: 0.9;
  transition: opacity 0.15s, transform 0.15s;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
#lobby-brand .brand-suit:hover { opacity: 0.95; }
#lobby-brand .brand-suit:active { transform: scale(0.85); }
#lobby-brand.brand-open .brand-suit { opacity: 1; }

.header-pills {
  flex: 1;
  display: flex;
  gap: clamp(3px, 1vw, 10px);
  min-width: 0;
  overflow: hidden;
}

.pill {
  background: rgba(var(--gold-rgb), 0.1);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: clamp(1px,0.4vh,3px) clamp(4px,1vw,10px);
  font-size: clamp(0.58rem, 1.4vw, 0.75rem);
  color: var(--gold);
  white-space: nowrap;
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-flex;
  align-items: center;
}

.lang-btn.active { background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.2) !important; border-color: var(--gold-dim) !important; color: var(--sel,var(--gold)) !important; }
.btn-watch {
  background: rgba(var(--blue-rgb), 0.12);
  border: 1px solid rgba(var(--blue-rgb), 0.35);
  color: var(--info);
  padding: 4px 10px;
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  border-radius: 2px;
  cursor: pointer;
  letter-spacing: 0.08em;
  transition: background 0.15s;
  flex-shrink: 0;
}
.btn-watch:hover { background: rgba(var(--blue-rgb), 0.25); }
.btn-sm {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  padding: clamp(3px,0.6vh,5px) clamp(6px,1.2vw,14px);
  font-family: var(--ff-mono);
  font-size: clamp(0.62rem, 1.4vw, 0.78rem);
  cursor: pointer;
  border-radius: 2px;
  transition: border-color 0.2s, color 0.2s;
  white-space: nowrap;
  flex-shrink: 0;
}
.btn-sm:hover { border-color: var(--border-hi); color: var(--text-hi); }

/* Uniformisation hauteur des boutons dans tous les headers */
.header .btn-sm,
.cp-header .btn-sm {
  height: 30px;
  min-width: 30px;
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  font-size: var(--fs-sm);
  line-height: 1;
  color: var(--text-hi);
}
/* Bouton carré (icône seule) — un peu plus large pour respirer */
.header .btn-icon,
.cp-header .btn-icon {
  width: 34px;
  padding: 0;
  background: var(--inset);
}

/* ── Unread-chat badge ── */
/* Red counter pinned to the top-right of a 💬 button (game/lobby header
   and the floating FAB) so a closed chat panel never hides new messages. */
#chat-toggle-btn, #lobby-chat-btn, #gchat-fab { position: relative; }
.chat-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--red);
  color: #fff;
  font-family: var(--ff-mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0,0,0,0.5);
  pointer-events: none;
  z-index: 6;
  animation: chatBadgePop 0.25s ease;
}
@keyframes chatBadgePop {
  0%   { transform: scale(0); }
  70%  { transform: scale(1.25); }
  100% { transform: scale(1); }
}
#gchat-fab .chat-badge { top: -3px; right: -3px; }

/* Body */
.lobby-body {
  flex: 1;
  min-height: 0;  /* allow shrinking */
  display: flex;
  overflow: hidden;
}

/* ── Games panel ── */
.pane-games {
  flex: 1;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border);
  overflow: hidden;
}

.create-bar {
  display: flex; gap: var(--sp-3); padding: 10px 12px;
  background: rgba(var(--green-rgb), 0.06);
  border-bottom: 1px solid var(--border);
}
.btn-create {
  flex: 1; background: rgba(var(--green-rgb), 0.15);
  border: 1px solid var(--green); color: var(--green);
  padding: 9px 14px; font-family: var(--ff-display);
  font-size: var(--fs-sm); font-weight: 700; cursor: pointer; border-radius: 4px;
}
.btn-create:hover { background: rgba(var(--green-rgb), 0.28); }
.btn-create:disabled { opacity: 0.5; cursor: default; }
.btn-create-manual {
  background: var(--inset); border: 1px solid var(--border);
  color: var(--text); padding: 9px 12px; font-size: var(--fs-sm);
  cursor: pointer; border-radius: 4px; white-space: nowrap;
}
.btn-create-manual:hover { background: rgba(255,255,255,0.1); }
.create-form { padding: 12px 14px; background: var(--modal-bg); border-bottom: 1px solid var(--border); }
.create-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 8px 12px; margin-bottom: 0; }
/* Le nom de la table occupe toute la largeur du cadre : on sort ce champ de la
   grille auto-fill (sinon il reste cantonné à une colonne de ~130px) et on force
   l'input à 100% de la largeur du cadre. */
.cf-name-wrap { display: block; }
.cf-name-wrap .cf { width: 100%; }
.cf-name-wrap .cf input { width: 100%; box-sizing: border-box; }
.cf { display: flex; flex-direction: column; gap: 3px; }
.cf-sm { min-width: 80px; }
.cf label { font-size: var(--fs-3xs); color: var(--gold-dim); letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cf input, .cf select { background: var(--field-bg); border: 1px solid var(--border); border-radius: 2px; color: var(--cream); padding: 5px 7px; font-family: var(--ff-mono); font-size: var(--fs-base); outline: none; width: 100%; }
.cf input:focus, .cf select:focus { border-color: var(--gold); }

.pane-header {
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-dim);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.games-scroll {
  flex: 1;
  overflow-y: auto;
}

.game-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 16px;
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.07);
  cursor: pointer;
  transition: background 0.12s;
}
.game-row:hover { background: var(--inset-hi); }

.dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dot-open   { background: var(--green); box-shadow: 0 0 6px rgba(var(--green-rgb), 0.5); }
.dot-run    { background: var(--orange); }
.dot-closed { background: #555; }

.game-info { flex: 1; min-width: 0; }
.game-name {
  color: var(--text-hi);
  font-size: var(--fs-base);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.game-meta {
  font-size: var(--fs-xs);
  color: var(--text);
  margin-top: 2px;
  display: flex;
  gap: var(--sp-4);
}
.game-type  { color: var(--gold-dim); }
.game-count { color: var(--gold); font-weight: 500; }

.empty {
  padding: 48px;
  text-align: center;
  color: rgba(154,170,146,0.35);
  font-size: var(--fs-base);
  line-height: 2;
}

/* ── Chat panel ── */
.chat-msgs {
  flex: 1;
  overflow-y: auto;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.msg {
  font-size: var(--fs-sm);
  line-height: 1.45;
  word-break: break-word;
}
.msg .who   { color: var(--gold); font-weight: 700; }
.msg .txt   { color: var(--text-hi); }
.msg.sys    { color: var(--text); font-size: var(--fs-sm); font-style: italic; }
.msg.reaction { font-size: var(--fs-lg); opacity: 0.85; font-style: italic; }
.msg.bc     { color: var(--gold-dim); border-left: 2px solid var(--gold-dim); padding-left: 6px; }
.msg.mine .who { color: var(--green); }
/* Mention : mon pseudo cité dans un message d'autrui → corps en or gras
   (parité QML LobbyHandler, colorAccent = --gold). */
.msg.mention .txt { color: var(--gold); font-weight: 700; }
/* Action « /me … » : corps en italique, format « *Nom fait qqch* » (parité QML isAction). */
.msg.action .txt { font-style: italic; }
/* Le (chat bot) m'adresse directement → corps en rouge gras (parité QML colorDanger). */
.msg.botwarn .txt { color: var(--red); font-weight: 700; }
#g-chat-msgs .msg.botwarn .txt { color: var(--red); font-weight: 700; }
/* Emojis unicode du chat agrandis ~22px (parité QML enlargeEmojis). */
.chat-emoji-lg { font-size: 22px; line-height: 1; vertical-align: -0.15em; }

.chat-input {
  padding: 8px 10px;
  border-top: 1px solid var(--border);
  display: flex;
  gap: var(--sp-3);
  flex-shrink: 0;
}
.chat-input input {
  flex: 1;
  background: var(--field-bg);
  border: 1px solid var(--border);
  color: var(--cream);
  padding: 7px 10px;
  font-family: var(--ff-mono);
  font-size: var(--fs-base);
  outline: none;
  border-radius: 2px;
}
.chat-input input:focus { border-color: var(--gold); }
/* ── Popup de suggestion d'emotes (":smi…" → 😄) — parité ChatBox QML :
   radius 8, lignes 26 px, max 6 visibles + scroll, emoji 15 px + :code:
   secondaire, survol/sélection surlignés. Ancré au-dessus de la saisie. ── */
.chat-input { position: relative; }
.emote-suggest {
  position: absolute;
  left: 10px; right: 10px;
  bottom: calc(100% + 8px);
  z-index: 60;
  max-height: 164px;               /* 6 × 26 px + 2 × 4 px */
  overflow-y: auto;
  padding: var(--sp-1);
  border-radius: 8px;
  background: var(--panel-hi);
  border: 1px solid var(--border);
  box-shadow: 0 6px 18px rgba(0,0,0,.45);
  display: none;
}
.emote-suggest.open { display: block; }
.emote-suggest .es-row {
  display: flex; align-items: center; gap: var(--sp-3);
  height: 26px; padding: 0 6px;
  border-radius: 5px; cursor: pointer;
}
.emote-suggest .es-row.sel { background: rgba(255,255,255,.09); }
.emote-suggest .es-emoji { font-size: 15px; flex: none; line-height: 1; }
.emote-suggest .es-code {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--ff-mono); font-size: 12px; color: var(--text);
}
.emote-suggest .es-row.sel .es-code { color: var(--text-hi); }
.chat-send {
  background: var(--gold);
  color: var(--on-gold);
  border: none;
  padding: 0 14px;
  font-family: var(--ff-display);
  font-size: var(--fs-sm);
  cursor: pointer;
  border-radius: 2px;
  transition: background 0.15s;
}
.chat-send:hover { background: var(--gold-hi); }
/* Palette claire : corps des listes du lobby (joueurs, chat, tri) posés sur le
   gris du panneau comme le QML — leurs styles inline mettent --field-bg blanc. */
:root[data-theme="pokerth-light"] #players-list-body,
:root[data-theme="pokerth-light"] #lobby-chat-panel .chat-msgs { background:transparent !important; }
:root[data-theme="pokerth-light"] .pl-sortbar .sel-wrap select { background:#dedfe2; border-color:transparent; border-radius:var(--r-sm); color:#1d222b; }
/* Champ Message du chat lobby : gris-bleu clair arrondi (pixel QML #d4d9e1). */
:root[data-theme="pokerth-light"] #lobby-chat-panel .chat-input input {
  background:#d4d9e1; border-color:transparent; border-radius:var(--r-sm); color:#1d222b;
}
:root[data-theme="pokerth-light"] #lobby-chat-panel .chat-input input::placeholder { color:#687285; }
/* Chat du LOBBY : icônes façon QML — envoi = avion en papier vert (chat send
   #4ade80 sombre / #16a34a clair), emoji = smiley nu ; aucun chrome de bouton. */
#lobby-chat-panel .chat-send {
  background:none; border:none; padding:0 8px; color:var(--green);
  display:flex; align-items:center; border-radius:var(--r-sm); flex:0 0 auto;
}
/* L'input du chat doit pouvoir rétrécir, sinon il pousse le bouton d'envoi
   hors du cadre quand la colonne est étroite. */
.chat-input { min-width:0; }
.chat-input input { min-width:0; }
.chat-input .chat-emoji-toggle, .chat-input .chat-send { flex:0 0 auto; }
#lobby-chat-panel .chat-send:hover { background:var(--inset-hi); }
:root[data-theme="pokerth"] #lobby-chat-panel .chat-send { color:#4ade80; }
:root[data-theme="pokerth-light"] #lobby-chat-panel .chat-send { color:#16a34a; }
#lobby-chat-panel .chat-emoji-toggle {
  background:none; border:none; padding:0 6px; font-size:1.15rem; border-radius:var(--r-sm);
}
#lobby-chat-panel .chat-emoji-toggle:hover,
#lobby-chat-panel .chat-emoji-toggle.active { background:var(--inset-hi); border:none; }

/* Lobby chat panel — fond unifié + bordure basse nette + ombre, pour que le
   bas de la zone message soit clairement délimité du reste du lobby. */
#lobby-chat-panel {
  background: var(--panel);
  border-bottom: 2px solid var(--border-hi);
  box-shadow: 0 8px 16px rgba(0,0,0,0.5);
  position: fixed;       /* overlay : ne pousse plus les tables, les recouvre */
  top: var(--ovl-top, 48px);             /* juste sous le header (comme #players-panel) */
  left: 0; right: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
}

/* Scrollbars */
::-webkit-scrollbar { width: 3px; height: 3px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

/* Mobile responsive */
/* ══════════════════════════════════
/* ══ GAME STATUS BAR (parité GameStatusBar QML §7 + delta 2.1.3) ══
   Bandeau noir rgba(0,0,0,0.78), hauteur 40 px (28 en landscapeCompact),
   marges 16 px. Gauche : Total $X (vert #99D500, gras) / Mises $Y (#7aa800),
   libellés gris #9e9e9e. Droite : phase (blanc DemiBold, letterSpacing 0.5)
   puis Partie/Main (gris). Tailles 13/11 px, compact 11/10/9 px.
   Centre (spécifique web, conservé) : badge blinds + statut spectateur. */
#pot-strip {
  position: relative;             /* ancre du badge blinds (.gsb-mid absolu) */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 0 16px;                /* marges QML 16 px */
  background: rgba(0,0,0,0.78);
  border-bottom: 1px solid rgba(255,255,255,0.08);
  flex-shrink: 0;
  height: 40px;                   /* QML 2.1.3 : landscapeCompact ? 28 : 40 */
  box-sizing: border-box;
  font-family: var(--ff-display);
  overflow: hidden;
}
.gsb-col {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.3;
  min-width: 0;
  white-space: nowrap;
}
.gsb-right { align-items: flex-end; text-align: right; }
/* Centre (badge blinds + spectateur) : position ABSOLUE à 33 % — décalé à
   gauche du centre et surtout FIXE, indépendant de la largeur des montants
   Total/Mises (demande narmod). Hors flux → gauche/droite restent 1:1 QML. */
/* Pastille blinds CENTRÉE au vrai milieu de la barre (demande narmod
   2026-07-15) : même règle mobile ET desktop → affichage identique partout.
   Remplace l'ancien décalage 33% (mobile) / 230px (desktop). */
.gsb-mid {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.gsb-row { display: inline-flex; align-items: baseline; gap: 5px; }
.gsb-lbl { color: #9e9e9e; font-size: 13px; }
.gsb-row .gsb-lbl + .gsb-lbl { margin-left: 8px; }   /* espace Partie · Main */
.gsb-total { color: #99D500; font-weight: 700; font-size: 13px; }
.gsb-left .gsb-row:last-child .gsb-lbl,
.gsb-gh .gsb-lbl, .gsb-val { font-size: 11px; }
.gsb-bets { color: #7aa800; font-weight: 600; font-size: 11px; }
.gsb-val  { color: #9e9e9e; }
.gsb-phase {
  color: #ffffff;
  font-weight: 600;               /* DemiBold */
  font-size: 13px;
  letter-spacing: 0.5px;
}
/* landscapeCompact (parité Responsive QML 2.1.3) : barre 28 px, tailles 11/10/9 */
@media (orientation: landscape) and (max-height: 600px),
       (min-aspect-ratio: 210/100) and (max-height: 799px) {
  #pot-strip { height: 28px; padding: 0 16px; }
  .gsb-col { line-height: 1.15; }
  .gsb-lbl { font-size: 10px; }
  .gsb-total, .gsb-phase { font-size: 11px; }
  .gsb-left .gsb-row:last-child .gsb-lbl,
  .gsb-gh .gsb-lbl, .gsb-val, .gsb-bets { font-size: 9px; }
  /* Barre 28 px : pas de marge pour grossir — badge blinds figé compact. */
  #pot-strip .blinds-next { height: 18px; padding: 0 9px; font-size: 10px; }
}
/* Compteur "blinds" cliquable à côté du n° de main dans le bandeau du pot.
   Taille asservie au modèle générique --comm-scale (0.55–1.8, posé par
   renderSeats) comme la pastille de connexion / win-hand-badge : le badge
   grossit avec la résolution, borné par clamp() pour rester dans la barre
   de 40 px (base ≈ tailles historiques à échelle 1 ; repli 1 hors table). */
.blinds-next {
  display: inline-flex;
  align-items: center;
  height: clamp(18px, calc(19px * var(--comm-scale, 1)), 28px);
  box-sizing: border-box;
  padding: 0 clamp(8px, calc(9px * var(--comm-scale, 1)), 14px);
  border-radius: var(--r-pill);
  /* Accent du THEME (equivalent web de Theme.colorAccent cote QML), pas un or
     fige : --sel vaut #E3C800 en sombre et #9a7d0a en clair, et suit le theme
     de table choisi. Meme source que #g-spec-badge, les deux pastilles du
     bandeau restent donc assorties. */
  background: rgba(var(--sel-bar-rgb), 0.22);
  border: 1px solid var(--sel-bar);
  color: var(--sel-bar);
  font-family: var(--ff-mono);
  font-weight: 700;
  font-size: clamp(10px, calc(11px * var(--comm-scale, 1)), 16px);
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
/* Le slot n'est qu'un point d'insertion JS : display:contents → le badge
   devient enfant flex DIRECT de .gsb-mid et se centre verticalement
   exactement comme #g-spec-badge (même offset depuis le haut de la barre). */
#g-blinds-slot { display: contents; }
.blinds-next:hover, .blinds-next:focus { background: rgba(var(--sel-bar-rgb), 0.32); border-color: var(--sel-bar); outline: none; }
/* Bandeau d'info/alerte blinds. Centré en haut, masqué par défaut, révélé
   via .show (transition). Affiche : ↑ Blinds  cur → next  · quand. */
.blinds-up-toast {
  position: fixed;
  top: 64px;
  left: 50%;
  transform: translate(-50%, -14px) scale(0.9);
  z-index: 900;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 8px;
  max-width: min(90vw, 360px);
  padding: 9px 18px;
  border-radius: 22px;
  background: linear-gradient(135deg, rgba(var(--gold-rgb), 0.96), rgba(var(--gold-rgb), 0.72));
  color: var(--on-gold);
  font-family: var(--ff-display);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: center;
  box-shadow: 0 8px 28px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.25) inset;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.2,0.9,0.3,1.3);
}
.blinds-up-toast.show { opacity: 1; transform: translate(-50%, 0) scale(1); }
.blinds-up-toast .bu-icon { font-size: var(--fs-lg); line-height: 1; }
.blinds-up-toast .bu-text { font-size: var(--fs-sm); text-transform: uppercase; }
.blinds-up-toast .bu-val {
  font-family: var(--ff-mono);
  font-size: var(--fs-md);
  font-weight: 700;
  background: rgba(0,0,0,0.16);
  padding: 1px 8px;
  border-radius: var(--r-sm);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.blinds-up-toast .bu-arrow { opacity: 0.7; }
.blinds-up-toast .bu-when {
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  opacity: 0.85;
}

/* ══ RESPONSIVE OVAL SIZE via CSS custom props ══
   Échelle continue propre à l'écran de jeu (1100/900/700/740-portrait/500-paysage).
   Exception au canon 600 (décision B) : l'écran de jeu garde 740/768 en portrait —
   le layout téléphone s'étend volontairement aux petites tablettes portrait, comme
   le QML qui choisit ses slots au RATIO de la tableZone et non à la largeur.
   ══ */
:root { --oval-w: 440px; --oval-h: 180px; }
@media (min-width: 1100px)  { :root { --oval-w: 520px; --oval-h: 210px; } }
@media (max-width: 900px)   { :root { --oval-w: 320px; --oval-h: 132px; } }
@media (max-width: 700px)   { :root { --oval-w: 240px; --oval-h: 100px; } }
@media (max-width: 740px) and (orientation: portrait)  { :root { --oval-w: min(58vw,240px); --oval-h: min(24vw,100px); } }
/* Palier « extra-compact » (h<500 = téléphones en paysage), raffinement INTERNE au
   landscapeCompact canonique h<600 — intentionnel, ne pas fusionner avec 600. */
@media (max-height: 500px) and (orientation: landscape){ :root { --oval-w: min(40vw,240px); --oval-h: min(18vh,88px); } }

   RESPONSIVE — orientation-aware
══════════════════════════════════ */



/* ── Confetti rain ── */
@keyframes confettiFall {
  0%   { transform: translateY(-20px) rotate(0deg);   opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateY(105vh) rotate(720deg); opacity: 0; }
}
.confetti-piece {
  position: fixed;
  width: 10px; height: 10px;
  top: -20px;
  pointer-events: none;
  z-index: 700;
  border-radius: 2px;
  animation: confettiFall linear forwards;
}

/* ── Urgence (≤5s) — pulsation rouge ── */
/* Halo d'urgence (ton tour, <=8s) : ombre FIXE portee par un pseudo-element
   promu en couche GPU ; seule l'opacity est animee (composite-only) -> fin du
   repaint plein ecran a chaque frame (batterie/chaleur). Rendu visuel identique.
   position:fixed -> se cale sur le viewport (= l'ecran de jeu plein ecran),
   sans toucher au positionnement de #s-game ni de ses enfants. */
@keyframes urgencyPulse {
  0%,100% { opacity: 0; }
  50%     { opacity: 1; }
}
#s-game.urgent::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 90;
  box-shadow: inset 0 0 60px 10px rgba(var(--red-rgb), 0.22);
  will-change: opacity;
  animation: urgencyPulse 0.6s ease-in-out infinite;
}

/* ── Transition lobby → table ── */
@keyframes tableEnter {
  0%   { opacity: 0; transform: scale(0.94); }
  100% { opacity: 1; transform: scale(1); }
}
#s-game.entering { animation: tableEnter 0.45s cubic-bezier(.2,.8,.3,1) both; }

/* ── Hover fan mes cartes ── */
.pb-cards:hover .pk:first-child {
  transform: rotate(-8deg) translateY(-6px) translateX(-4px);
  transition: transform 0.2s ease;
  z-index: 2;
}
.pb-cards:hover .pk:last-child {
  transform: rotate(8deg) translateY(-6px) translateX(4px);
  transition: transform 0.2s ease;
  z-index: 2;
}
.pb-cards .pk { transition: transform 0.2s ease; z-index: 1; }

/* ── Élimination joueur ── */
@keyframes eliminatePlayer {
  0%   { opacity: 1;  transform: translate(-50%,-50%) scale(1)  rotate(0deg); }
  40%  { opacity: 0.7; transform: translate(-50%,-50%) scale(1.1) rotate(-5deg); }
  100% { opacity: 0;  transform: translate(-50%,-50%) scale(0.3) rotate(15deg); }
}
.seat.eliminated { animation: eliminatePlayer 0.8s ease-in forwards; pointer-events: none; }

/* ── Pot énorme — glow rouge/orange ── */
@keyframes bigPotGlow {
  0%,100% { color: var(--gold); text-shadow: 0 0 8px rgba(var(--gold-rgb), 0.4); }
  50%     { color: #ff8c42;     text-shadow: 0 0 20px rgba(255,100,30,0.7); }
}
.pot-huge { animation: bigPotGlow 1.2s ease-in-out infinite !important; }

/* ── River — révélation dramatique ── */
.pk-river {
  /* Parité QML : river immédiate, même fondu 260 ms que le turn. */
  animation: cardFlip 0.26s cubic-bezier(.3,0,.2,1) both !important;
  animation-delay: 0s !important;
}

/* ── Showdown — flip cartes adversaires ── */
.pk-showdown {
  animation: cardFlip 0.32s cubic-bezier(.3,0,.2,1) both;
}

/* ── Reset action fade entre mains ── */
@keyframes actionFadeOut {
  0%   { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(4px); }
}
.seat-action-label.fading {
  animation: actionFadeOut 0.4s ease-out forwards;
}

/* ── Dealer badge volant ── */
.dealer-badge-fly {
  position: fixed;
  background: var(--gold); color: var(--on-gold);
  border-radius: 50%; width: 18px; height: 18px;
  font-size: var(--fs-3xs); font-weight: 900;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; z-index: 600;
  transition: left 0.6s cubic-bezier(.4,0,.2,1),
              top  0.6s cubic-bezier(.4,0,.2,1),
              opacity 0.2s ease 0.55s;
}

/* ── All-in chips multi ── */
@keyframes allInChip {
  0%   { transform: translate(0,0) scale(1) rotate(0deg);       opacity: 1; }
  60%  { transform: translate(var(--ax),var(--ay)) scale(1.3) rotate(var(--ar)); opacity: 1; }
  100% { transform: translate(var(--bx),var(--by)) scale(0.6) rotate(var(--ar)); opacity: 0; }
}
.allin-chip {
  position: fixed;
  width: 14px; height: 14px;
  border-radius: 50%;
  pointer-events: none; z-index: 550;
  animation: allInChip 0.7s cubic-bezier(.3,0,.7,1) forwards;
}

/* ═══════════════════════════════════════════════════════════
   DESKTOP LARGE (≥ 900px) — Agrandissement table + cartes
   ═══════════════════════════════════════════════════════════ */
@media (min-width: 900px) {

  /* ── Ovale de la table ── */
  .felt-oval {
    width:  min(580px, 64vw) !important;
    height: min(256px, min(32vw, calc(100dvh - 300px))) !important;
  }

  /* ── Cartes communes : tailles gerees par --comm-scale (voir .comm-row,
     slot QML 46x64 x echelle par appareil) — plus d'override fixe ici. ── */

  /* ── Mes cartes dans la player-bar ── */
  .pb-cards .pk {
    width: 62px !important;
    height: 90px !important;
    font-size: var(--fs-xl) !important;
  }
  .pb-cards { gap: 8px !important; }

  /* ── Joueurs (rendu standard : tablette paysage + base desktop) ── */
  .seat-avatar {
    width: 38px !important;
    height: 38px !important;
    font-size: var(--fs-md) !important;
  }
  /* Emoji un peu plus petit sur desktop/tablette (le carré y est plus grand) ;
     mobile garde 1.5em via la règle de base hors media. */
  .seat-avatar.is-bot .seat-initial { font-size: 1.2em !important; }
  .seat-avatar.emoji-av .seat-initial { font-size: 1.2em !important; }
  .seat-name   { font-size: var(--fs-xs) !important; max-width: 84px !important; }
  .seat-money  { font-size: var(--fs-xs) !important; }
  .seat-bet    { font-size: var(--fs-3xs) !important; }
  .seat-action-label { font-size: var(--fs-3xs) !important; }
  .seat { min-width: 54px !important; max-width: 86px !important; }

  .seat.dealer .seat-avatar::after {
    width: 16px !important; height: 16px !important;
    font-size: var(--fs-3xs) !important;
    top: -5px !important; right: -5px !important;
  }
  .blind-badge {
    width: 16px !important; height: 16px !important;
    font-size: var(--fs-3xs) !important;
    top: -5px !important; left: -5px !important;
  }
  .seat .pk.xsm {
    width: 24px !important;
    height: 34px !important;
    font-size: var(--fs-2xs) !important;
  }

  /* ── Scaler : marge pour les sièges qui débordent ── */
  .table-scaler { padding: 80px 110px !important; }

  /* ── Player bar ── */
  .pb-avatar {
    width: 46px !important; height: 46px !important;
    font-size: 1.15rem !important;
  }
  .pb-name  { font-size: var(--fs-md) !important; }
  .pb-money { font-size: var(--fs-sm) !important; }
  .pb-info  { min-width: 110px !important; }

  /* ── Timer SVG autour de l'avatar ── */
  .seat-timer {
    width: 170% !important; height: 170% !important;
    top: -35% !important; left: -35% !important;
  }
  .seat-timer-badge {
    font-size: var(--fs-base) !important;
    margin-top: 16px !important;
    padding: 2px 7px !important;
    min-width: 32px !important;
  }
}

/* ══════════════════════════════════════════════════════════════
   MODE DESKTOP (souris) — agrandissements appliqués UNIQUEMENT aux
   écrans pointés à la souris. Une tablette tactile (même en paysage
   ≥ 900px) garde le rendu standard ci-dessus.
   ══════════════════════════════════════════════════════════════ */
@media (min-width: 900px) and (hover: hover) and (pointer: fine) {

  /* ── Joueurs ── */
  .seat-avatar {
    width: 52px !important;
    height: 52px !important;
    font-size: var(--fs-xl) !important;
  }
  .seat-name   { font-size: var(--fs-md) !important; max-width: 112px !important; }
  .seat-money  { font-size: var(--fs-md) !important; }
  .seat-bet    { font-size: var(--fs-sm) !important; }
  .seat-action-label { font-size: var(--fs-sm) !important; }
  .seat { min-width: 72px !important; max-width: 116px !important; }
  .seat.dealer .seat-avatar::after {
    width: 22px !important; height: 22px !important;
    font-size: var(--fs-sm) !important;
    top: -7px !important; right: -7px !important;
  }
  .blind-badge {
    width: 22px !important; height: 22px !important;
    font-size: var(--fs-xs) !important;
    top: -7px !important; left: -7px !important;
  }
  .seat .pk.xsm {
    width: 32px !important;
    height: 45px !important; /* ratio carte 120:168 (0.714) */
    font-size: var(--fs-sm) !important;
  }

  /* ── Player bar ── */
  .pb-avatar {
    width: 52px !important; height: 52px !important;
    font-size: var(--fs-xl) !important;
  }
  .pb-name  { font-size: var(--fs-lg) !important; }
  .pb-money { font-size: var(--fs-md) !important; }
  .pb-info  { min-width: 120px !important; }
  .pb-action { font-size: var(--fs-md) !important; min-width: 60px !important; }
  #pb-timer  { font-size: var(--fs-md) !important; }
  /* Nos cartes (player-bar du bas) agrandies — desktop souris seulement ;
     la tablette paysage garde 62x90 du bloc min-width:900px ci-dessus. */
  .pb-cards .pk { width: 76px !important; height: 108px !important; font-size: var(--fs-2xl) !important; }
  .pb-cards     { gap: 10px !important; }

  /* ── Contrôles d'action ── */
  /* Boutons d'action, police 15 px. Padding vertical 10 px pour egaler la
     hauteur des themes a boutons-image (skin : border 9 + padding 1 = chrome 20 ;
     ici border 0 + padding 10+10 = chrome 20). Horizontal 18 = meme largeur. */
  .btn-action { font-size: var(--fs-md) !important; padding: 10px 18px !important; }
  .btn-pct { padding: 7px 6px !important; }
  /* Mid-row facon QML : 1/3 · 1/2 · Pot · Tapis compacts groupes a gauche,
     dropdown pousse a droite. (Pas de width fixe sur le Tapis : 52 px cassait
     le border-image 9-slice du skin de boutons.) */
  .mid-row { justify-content: flex-start !important; }
  .mid-row .pct-row { flex: 0 0 auto !important; width: auto !important; }
  .pct-row .btn-pct { flex: 0 0 auto !important; min-width: 52px !important; }
  .mid-row .btn-allin { flex: 0 0 auto !important; min-width: 0 !important; }
  .mid-row .mode-sel-wrap { margin-left: auto !important; flex: 0 0 auto !important; }
  /* Pas d'agrandissement des spans quick-bet : meme taille qu'en base/mobile
     pour garder les boutons 1/3 - 1/2 - Pot a la meme hauteur (compacte). */
  .raise-row .raise-input { font-size: var(--fs-base) !important; }

  /* ── Vignette d'assistance ── */
  .hs-txt { font-size: var(--fs-xs) !important; }

  /* ── Header ── */
  .header { min-height: var(--header-h, 38px) !important; }
  .header-brand { font-size: var(--fs-lg) !important; }
  .header .btn-sm { height: 30px !important; font-size: var(--fs-base) !important; padding: 0 13px !important; }
  .header .btn-icon { width: 34px !important; padding: 0 !important; }

  /* ── Barre d'état de jeu : tailles QML fixes (13/11 px), pas d'override ── */

  /* ── Menu ••• ── */
  #g-overflow-menu, #l-overflow-menu, #cr-overflow-menu, #pv-overflow-menu { width: 264px !important; }
  #g-overflow-menu .btn-sm, #l-overflow-menu .btn-sm, #cr-overflow-menu .btn-sm, #pv-overflow-menu .btn-sm { font-size: var(--fs-md) !important; padding: 9px 32px 9px 14px !important; }

  /* ══ Fenetres d'informations ══ */
  .winner-card { max-width: min(640px, 86vw) !important; padding: 24px 28px !important; }
  .wc-trophy { font-size: 2.5rem !important; }
  .wc-label { font-size: var(--fs-xs) !important; }
  .wc-name { font-size: 1.7rem !important; }
  .wc-gain { font-size: var(--fs-xl) !important; }
  .wc-stat-label { font-size: var(--fs-xs) !important; }
  .wc-stat-value { font-size: var(--fs-lg) !important; }
  .wc-section { font-size: var(--fs-xs) !important; }
  .wc-player-row { grid-template-columns: 30px minmax(0,1fr) auto 120px !important; }
  .wc-player-av { width: 30px !important; height: 30px !important; font-size: var(--fs-sm) !important; }
  .wc-player-name { font-size: var(--fs-md) !important; }
  .wc-player-stack { font-size: var(--fs-sm) !important; }
  .wc-player-delta { font-size: var(--fs-lg) !important; }
  .winner-dismiss { font-size: var(--fs-md) !important; padding: 12px 24px !important; }
  /* Resume de manche : cartes agrandies (desktop souris seulement) */
  .wc-cards-row .pk    { width: 48px !important; height: 68px !important; font-size: var(--fs-md) !important; }
  .wc-player-cards .pk { width: 38px !important; height: 54px !important; font-size: var(--fs-base) !important; }

  .endgame-card { max-width: 600px !important; padding: 26px 34px !important; }
  .eg-trophy { font-size: 3.6rem !important; }
  .eg-title { font-size: var(--fs-2xl) !important; }
  .eg-winner-av { width: 46px !important; height: 46px !important; font-size: 1.9rem !important; }
  .eg-winner-av.letter { font-size: var(--fs-xl) !important; }
  .eg-winner-label { font-size: var(--fs-sm) !important; }
  .eg-winner-name { font-size: 1.28rem !important; }
  .eg-stats-title { font-size: var(--fs-xs) !important; }
  .eg-stat-row { font-size: var(--fs-md) !important; }
  .eg-btn { font-size: var(--fs-md) !important; padding: 12px 14px !important; }

  .gim-card { width: min(460px, 100%) !important; max-height: min(82vh, 680px) !important; }
  .gim-title { font-size: var(--fs-xl) !important; }
  .gim-subtitle { font-size: var(--fs-base) !important; }
  .gim-badge { font-size: var(--fs-xs) !important; }
  .gim-section-title { font-size: var(--fs-xs) !important; }
  .gim-row { font-size: var(--fs-md) !important; }

  .pim-card { max-width: 400px !important; }
  .pim-avatar { width: 112px !important; height: 112px !important; }
  .pim-avatar.is-letter { font-size: 2.9rem !important; }
  .pim-name { font-size: 1.28rem !important; }
  .pim-flag { font-size: var(--fs-md) !important; }

  .km-card:not(.adv-card):not(.jr-card) { width: min(460px, 100%) !important; max-height: min(82vh, 680px) !important; }
  .km-title { font-size: var(--fs-xl) !important; }
  .km-subtitle { font-size: var(--fs-base) !important; }
  .km-row .km-av { width: 40px !important; height: 40px !important; font-size: 1.7rem !important; }
  .km-row .km-av.letter { font-size: var(--fs-lg) !important; }
  .km-row .km-name { font-size: var(--fs-md) !important; }
  .km-row .km-meta { font-size: var(--fs-sm) !important; }

  .ld-card { max-width: 500px !important; padding: 26px 28px !important; }
  .ld-title { font-size: 1.22rem !important; }
  .ld-body { font-size: var(--fs-md) !important; }
  .ld-btn { font-size: var(--fs-md) !important; }
}

/* Tablet */
/* Exception canon (décision B) — écran de jeu, voir §RESPONSIVE OVAL SIZE. */
@media (max-width: 768px) {
  .blind-chip  { width: 19px !important; height: 19px !important; top: -11px !important; left: -11px !important; }
  .dealer-chip { width: 19px !important; height: 19px !important; top: -11px !important; right: -11px !important; }
  .seat-flag   { bottom: -6px !important; right: -6px !important; }
  .seat-flag .cc-flag { width: 16px !important; height: 12px !important; }
  /* Drapeaux agrandis UNIQUEMENT en mode pokerth.net (body.pth-net) */
  body.pth-net .seat-flag   { bottom: -3px !important; right: -12px !important; }
  body.pth-net .seat-flag .cc-flag { width: 20px !important; height: 15px !important; }
  .seat-avatar { width: 28px; height: 28px; font-size: var(--fs-xs); }
  .seat-name,.seat-money,.seat-action-label,.seat-bet { font-size: 0.48rem; }
.pill { font-size: var(--fs-2xs); padding: 2px 5px; }
  .pk { width: 36px; height: 52px; font-size: var(--fs-base); }
  .pk.sm { width: 28px; height: 40px; font-size: var(--fs-xs); }
  /* table-zone padding handled by table-scaler */
  /* Oval moins large : libère de l'espace pour les joueurs sur les côtés */
  .felt-oval { width: min(400px, 72vw) !important; }
}
/* Exception canon (décision B) — table de jeu portrait, voir §RESPONSIVE OVAL SIZE. */
@media (max-width: 740px) and (orientation: portrait) {
  /* Oval: compact to fit 10 seats */
  .felt-oval::before {
  content: '';
  position: absolute;
  inset: 10px;
  border-radius: 50% / 42%;
  border: 2px solid rgba(255,255,255,0.07);
  pointer-events: none;
}
.felt-oval { overflow: visible; width: 68vw; height: 42vw; min-height: 130px; }

  /* Cards */
  .pk { width: 28px; height: 40px; font-size: var(--fs-xs); }
  .pk.sm { width: 22px; height: 32px; font-size: var(--fs-3xs); }

  /* Cartes communes : tailles gerees par --comm-scale (slot QML 46x64,
     echelle 1.15 en portrait telephone) — plus d'override fixe ici. */

  /* Chips : très excentrés pour éviter le chevauchement avec le timer */
  .blind-chip  { width: 17px !important; height: 17px !important; top: -13px !important; left: -13px !important; }
  .dealer-chip { width: 17px !important; height: 17px !important; top: -13px !important; right: -13px !important; }
  .seat-flag   { bottom: -5px !important; right: -5px !important; }
  .seat-flag .cc-flag { width: 12px !important; height: 9px !important; }
  /* Drapeaux agrandis UNIQUEMENT en mode pokerth.net (body.pth-net) */
  body.pth-net .seat-flag   { bottom: -2px !important; right: -11px !important; }
  body.pth-net .seat-flag .cc-flag { width: 16px !important; height: 12px !important; }
  /* Seats: tiny for 10-player tables */
  .seat-avatar { width: 18px; height: 18px; font-size: 0.46rem; }
  .seat-name { font-size: 0.36rem; }
  .seat-money,.seat-action-label,.seat-bet { font-size: 0.3rem; }
  .seat { min-width: 26px; max-width: 40px; gap: 0px; }
  .comm-row { gap: var(--sp-0); }

  /* Player bar */
  .player-bar-left { padding: 4px 10px; gap: 7px; }
  .pb-avatar { width: 28px; height: 28px; font-size: var(--fs-xs); }
  .pb-name { font-size: var(--fs-xs); }
  .pb-money { font-size: var(--fs-3xs); }
  .pb-info { min-width: 60px; }

  /* table padding via scaler */
  /* ── Gabarit PORTRAIT téléphone : valeurs QML Theme.compact (GameActionBar
     2.1.3) — rangée d'action 56 px police 15, rangée de relance 26 px :
     montant 78 (police 13), quick-bets 38, Tapis 52, dropdown 132 à droite.
     Préfixe .my-zone : les anciennes règles nues (.btn-action…) étaient
     MORTES, battues par les règles de base plus bas dans le fichier (une
     @media n'augmente pas la spécificité — même leçon que le bloc paysage). */
  .my-zone .act-buttons-row .btn-action { min-height: 45px; padding: 0 8px; font-size: 15px; letter-spacing: 0.5px; border-radius: var(--act-btn-radius, 9px); min-width: 0; }
  .my-zone .bet-row { gap: var(--sp-2); }
  .my-zone .bet-row .raise-amt-field { width: 78px; flex: 0 0 auto; height: 26px; min-height: 26px; padding: 1px 6px; font-size: 13px; }
  .my-zone .bet-row .raise-slider { flex: 1 1 auto; min-width: 60px; }
  .my-zone .mid-row { gap: var(--sp-1); align-items: center; }
  .my-zone .mid-row .pct-row { flex: 0 0 auto; width: auto; gap: var(--sp-1); }
  .my-zone .mid-row .btn-pct { flex: 0 0 38px; width: 38px; min-width: 38px; height: 26px; min-height: 26px; padding: 0 2px; border-radius: 5px; font-size: 11px; font-weight: 700; }
  .my-zone .mid-row .btn-pct .pct-amt { display: none; }
  .my-zone .mid-row .btn-allin { flex: 0 0 52px; width: 52px; min-width: 52px; height: 26px; min-height: 26px; font-size: 12px; padding: 0 2px !important; white-space: nowrap; }
  .my-zone .mid-row .mode-sel-wrap { flex: 0 1 132px; min-width: 0; height: 26px; margin-left: auto; }
  .my-zone .mid-row .mode-sel-wrap select { height: 100%; padding-top: 0; padding-bottom: 0; line-height: 1.1; }
  /* Thème à SVG : Tapis 52×26 en image étirée (le 9-slice se déchire à cette
     taille — même solution que paysage/desktop). !important : bat le border
     9px transparent + padding de :root[data-btn-img] .btn-action (règle de
     base, plus bas dans le fichier). */
  :root[data-btn-img] .my-zone .mid-row .btn-allin {
    border: none !important;
    background: transparent !important;
    background-image: var(--btn-allin-img) !important;
    background-size: 100% 100% !important;
    background-repeat: no-repeat !important;
    border-radius: var(--r-sm);
  }
  .my-zone { padding: 5px 8px; }
  .pot-bar { font-size: var(--fs-xs); }

.header-brand { font-size: var(--fs-base); }
  #g-blind { display: none; }
}

/* Global action-bar layout (applies at all sizes). These flex containers
   are required for the FOLD / CALL / RAISE / ALL-IN buttons to lay out
   correctly. Previously orphaned after a stray closing brace. */
.btn-action { padding: 12px 14px; font-size: var(--fs-base); flex: 1; min-width: 80px; text-align: center; }
.pct-row { display: flex; gap: 5px; width: 100%; }
.pct-row .btn-pct { flex: 1; padding: 7px 4px; font-size: var(--fs-sm); }
.raise-row { display: flex; gap: 5px; flex: 2; min-width: 160px; }
.raise-row .raise-input { flex: 1; padding: 10px 6px; font-size: var(--fs-base); }
.btn-allin { flex: 1.5; }
#g-blind { display: none; }

/* ── Phone LANDSCAPE (wide, short) ── */
/* Palier « extra-compact » du chrome de jeu (h<500 = téléphones en paysage) —
   raffinement interne au landscapeCompact canonique h<600, intentionnel. */
@media (max-height: 500px) and (orientation: landscape) {
  /* Header aplati facon landscapeCompact du QML officiel : 30 px, marges reduites. */
  .header { min-height: var(--header-h, 30px) !important; padding: 2px 6px !important; }
  .header .btn-sm { height: 26px !important; }
  .header .btn-icon { width: 30px !important; }
  .blind-chip  { width: 18px !important; height: 18px !important; top: -12px !important; left: -12px !important; }
  .dealer-chip { width: 18px !important; height: 18px !important; top: -12px !important; right: -12px !important; }
  .seat-flag   { bottom: -5px !important; right: -5px !important; }
  .seat-flag .cc-flag { width: 14px !important; height: 10px !important; }
  /* Drapeaux agrandis UNIQUEMENT en mode pokerth.net (body.pth-net) */
  body.pth-net .seat-flag   { bottom: -2px !important; right: -11px !important; }
  body.pth-net .seat-flag .cc-flag { width: 17px !important; height: 13px !important; }
  /* Oval: small, left side */
  .felt-oval::before {
  content: '';
  position: absolute;
  inset: 10px;
  border-radius: 50% / 42%;
  border: 2px solid rgba(255,255,255,0.07);
  pointer-events: none;
}
.felt-oval { overflow: visible; width: 52vw; height: 22vh; min-height: 100px; }
  .pk { width: 28px; height: 40px; font-size: var(--fs-xs); }
  .pk.sm { width: 22px; height: 32px; font-size: var(--fs-3xs); }
  .comm-row { gap: var(--sp-0); }
  .seat-avatar { width: 24px; height: 24px; font-size: var(--fs-2xs); }
  .seat-name,.seat-money,.seat-action-label { font-size: 0.42rem; }

  /* Fixed bars: very compact */
  .pot-bar { font-size: var(--fs-2xs); padding: 1px 0; }
  /* NB cascade : les regles de base (.btn-action, .action-grid, .pb-cards .pk,
     .pb-avatar, .player-bar-left...) sont definies PLUS BAS dans le fichier.
     Une @media n'augmente PAS la specificite -> a specificite egale, ces
     regles de base l'emportaient sur ce bloc et la compaction paysage etait
     ignoree (boutons + dock affiches en taille bureau). On porte donc ces
     overrides par .my-zone / .player-bar pour gagner en specificite. */

  /* Dock joueur (.player-bar) — compact */
  .my-zone { padding: 2px 6px !important; }
  .player-bar { padding: 2px 6px !important; }
  /* Largeur du dock DISSOCIEE de la barre d'action : au lieu de s'etirer a
     --bottom-w (560px) / pleine largeur, il s'ajuste a son contenu et reste
     centre (justify-content du parent) -> pastille compacte, plus de grand
     vide en paysage. */
  .player-bar .player-bar-left { padding: 2px 8px; gap: 5px; flex: 0 1 auto; width: -webkit-fit-content; width: fit-content; max-width: 100%; }
  .player-bar .pb-avatar { width: 22px; height: 22px; font-size: var(--fs-3xs); }
  .player-bar .pb-name { font-size: var(--fs-3xs); }
  .player-bar .pb-money { font-size: var(--fs-3xs); }
  .player-bar .pb-info { min-width: 45px; }
  .player-bar .pb-cards .pk { width: 50px; height: 70px; font-size: var(--fs-lg); }
  .player-bar .pb-action { font-size: var(--fs-3xs); min-width: 0; }

  /* Barre d'action — 2 rangees compactes et previsibles.
     Rangee 1 (pleine largeur) : Fold | Call | mode.
     Rangee 2 (pleine largeur) : 1/3 1/2 Pot | relance | All-In.
     La hauteur reelle (dock + barre) est mesuree en JS (updateBottomLayout)
     -> .my-zone se place AU-DESSUS du dock (plus de touches cachees) et la
     table reserve juste l'espace necessaire (riviere jamais masquee). */
  /* Barre d'action paysage : 3 zones compactes (montant+slider / pastilles+All-In+mode /
     Fold-Call-Raise), meme structure que l'officiel mais plus dense. Hauteur mesuree en JS. */
  /* ── Profil PAYSAGE mobile de la barre d'action : valeurs QML
     landscapeCompact (bible §5.5) — rangee d'action 40 px, police 12 px,
     radius 9, letterSpacing 0.5. min-height:40px annule EXPLICITEMENT le
     min-height:54px de la regle de base (definie plus bas dans le fichier,
     c'est elle qui rendait la barre geante en paysage). Meme organisation
     que le portrait/QML : quick-bets compacts a gauche, Tapis, mode a
     droite. */
  .my-zone .action-grid { gap: var(--sp-0); width: 100%; max-width: 100%; }
  .my-zone .action-grid > * { min-width: 0; }
  .my-zone .bet-row { gap: var(--sp-2); }
  /* Champ montant : 78 px (spec QML §5.2, conservee en compact). */
  .my-zone .bet-row .raise-amt-field { width: 78px; flex: 0 0 auto; height: 24px; min-height: 24px; padding: 1px 5px; font-size: var(--fs-xs); }
  .my-zone .bet-row .raise-slider { flex: 1 1 auto; min-width: 60px; }
  .my-zone .mid-row { gap: var(--sp-1); align-items: center; }
  .my-zone .mid-row .pct-row { flex: 0 0 auto; gap: 3px; }
  .my-zone .mid-row .mode-sel-wrap { flex: 0 1 110px; min-width: 0; height: 24px; margin-left: auto; }
  /* Le select gardait son padding vertical de base dans un wrap de 24px ->
     libelle « Manuel » rogne. Padding vertical 0 + height 100% : le texte
     (16px force par la regle iOS anti-zoom) tient et se centre. */
  .my-zone .mid-row .mode-sel-wrap select { height: 100%; padding-top: 0; padding-bottom: 0; line-height: 1.1; }
  /* Tapis : l'image du theme (--btn-allin-img) en fond etire au lieu du
     border-image 9-slice, qui se dechirait sur ce bouton etroit. Reste
     l'image DU THEME (pas une couleur en dur) -> chaque theme garde son Tapis. */
  .my-zone .mid-row .btn-allin {
    flex: 0 0 auto; white-space: nowrap; min-width: 48px; height: 24px; min-height: 24px; font-size: var(--fs-2xs);
    border-image: none !important;
    border: 1px solid #ef5350 !important;
    background: linear-gradient(180deg, #9e2a2a, #5c1111) !important;
    color: #fff !important;
    padding: 0 10px !important;
    border-radius: var(--r-md);
  }
  /* Thème à SVG de boutons : le Tapis mobile garde l'image DU THÈME, étirée
     comme le QML (le hardcode ci-dessus n'est plus que le REPLI sans pack —
     il écrasait le thème, bug de la passe 405-416). !important requis pour
     battre le border !important du repli ; spécificité supérieure → gagne. */
  :root[data-btn-img] .my-zone .mid-row .btn-allin {
    border: none !important;
    background: transparent !important;
    background-image: var(--btn-allin-img) !important;
    background-size: 100% 100% !important;
    background-repeat: no-repeat !important;
    border-radius: var(--r-sm);
  }
  .my-zone .act-buttons-row { gap: var(--sp-1); }
  .my-zone .act-buttons-row .btn-action { min-height: 30px; padding: 0 8px; font-size: var(--fs-xs); letter-spacing: 0.5px; border-radius: var(--act-btn-radius, 9px); min-width: 0; }
  .my-zone .mid-row .btn-pct { flex: 0 0 auto; min-width: 40px; height: 24px; min-height: 24px; padding: 0 8px; border-radius: var(--r-md); font-size: var(--fs-3xs); font-weight: 700; border-width: 1px; }
  .my-zone .mid-row .btn-pct .pct-p { font-size: var(--fs-2xs); }
  .my-zone .mid-row .btn-pct .pct-amt { display: none; }
  /* Pas de badges de touches clavier sur mobile (parite QML), comme en portrait. */
  .my-zone .act-key { display: none !important; }

.header { padding: 2px 6px; }
.pill { font-size: var(--fs-3xs); padding: 1px 4px; }
  #g-blind, #g-players { display: none; }
  /* ── Bas d'ecran en FLUX (deterministe) ──────────────────────────────
     Plutot que 2 barres position:fixed empilees via une hauteur mesuree en
     JS (fragile : la barre d'action flottait au milieu de l'ecran), on remet
     .my-zone et .player-bar dans le flux de .game-area (colonne flex) : la
     table (flex:1) occupe le haut, la barre d'action puis le dock s'empilent
     dessous, colles en bas. position:relative (et non static) -> .player-bar
     reste le contexte de #hand-strength (absolu) et .action-wrap celui de
     l'epingle. */
  .game-area { padding-bottom: 0 !important; }
  .my-zone, .player-bar {
    position: relative !important;
    left: auto !important; right: auto !important; bottom: auto !important;
    z-index: auto;
  }
  .my-zone    { order: 2; }
  .player-bar { order: 3; background: transparent !important; border-top: 0 !important; }
}



/* ══ HEADERS WITH OVERFLOW MENU (game + lobby) ══ */
/* Both screens host a ••• dropdown (#g-overflow-menu / #l-overflow-menu)
   that uses position:absolute relative to its containing .header. The
   lobby was missing position:relative here, so its menu was escaping
   to the viewport and rendering off-screen. Same chrome for both now. */
#s-game .header,
#s-lobby .header,
#s-create .cp-header,
#privacy-page .cp-header {
  position: relative;
  flex-wrap: nowrap;
  align-items: center;
  overflow: visible;
}

/* ••• overflow menu is used at EVERY screen size for a consistent header
   across phone / tablet / desktop (requested by narmod). The ••• button is
   always visible, and the secondary actions live exclusively in its menu. */
#g-overflow-btn,
#l-overflow-btn,
#connect-overflow-btn { display: inline-flex; align-items: center; }

/* Direct header twins of the menu actions: hidden at all sizes (they are
   provided by the ••• menu now). Was previously a mobile-only rule. */
#fs-btn-game,
#lang-toggle-game,
#admin-start-btn,
#admin-startnobots-btn,
#admin-close-btn,
#admin-kick-btn,
#haptic-toggle-btn,
#voice-toggle-btn,
#fs-btn-lobby,
#lang-toggle-lobby { display: none !important; }

/* Menu déroulant */
#g-overflow-menu,
#l-overflow-menu,
#connect-overflow-menu,
#cr-overflow-menu,
#pv-overflow-menu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 200;
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-bar);
  padding: 6px 5px;
  /* Largeur responsive : suit la fenêtre (min 232, plafond 300) au lieu
     d'une valeur fixe — comme le reste de l'app (narmod 19/07). Reste
     bornée pour ne pas s'élargir selon la longueur du libellé. */
  width: clamp(232px, 46vw, 300px);
  box-sizing: border-box;
  flex-direction: column;
  gap: clamp(4px, 1vw, 7px);
  box-shadow: 0 12px 32px rgba(0,0,0,0.7);
}
#g-overflow-menu.open,
#l-overflow-menu.open,
#connect-overflow-menu.open,
#cr-overflow-menu.open,
#pv-overflow-menu.open { display: flex; }
#g-overflow-menu .btn-sm,
#l-overflow-menu .btn-sm,
#connect-overflow-menu .btn-sm,
#cr-overflow-menu .btn-sm,
#pv-overflow-menu .btn-sm {
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  /* Lignes plates comme le menu ☰ : pas de cadre dessiné (le .btn-sm de
     base a un border --border), fond transparent au repos. */
  background: transparent;
  border: 1px solid transparent;
  box-shadow: none;
  /* padding-right généreux : on réserve la place du ✓ (positionné en
     absolu à droite) pour que le texte ne passe jamais dessous. */
  padding: clamp(7px, 1.4vw, 10px) clamp(30px, 5vw, 36px) clamp(7px, 1.4vw, 10px) clamp(12px, 2.2vw, 16px);
  border-radius: 4px;
  font-size: clamp(0.8rem, 1.9vw, 0.95rem);
  position: relative;
  overflow: hidden;
  text-overflow: ellipsis;   /* libellé trop long (autre langue) => "…" au lieu d'élargir */
  white-space: nowrap;
}
/* Coche d'état : ancrée à droite, donc toujours au même endroit quelle
   que soit la longueur du libellé ou la langue. */
#g-overflow-menu .menu-tick,
#l-overflow-menu .menu-tick {
  position: absolute;
  right: 11px;
  top: 50%;
  transform: translateY(-50%);
  font-weight: 700;
  color: var(--green);
  pointer-events: none;
}
#g-overflow-menu .btn-sm:hover,
#l-overflow-menu .btn-sm:hover,
#connect-overflow-menu .btn-sm:hover,
#cr-overflow-menu .btn-sm:hover,
#pv-overflow-menu .btn-sm:hover {
  background: var(--panel-hi);
  border-color: var(--border-hi);
}
/* Group separators inside the ••• menu. Plain hairline between groups,
   and a centred labelled divider for the (admin-only) action block. */
#g-overflow-menu .menu-sep,
#l-overflow-menu .menu-sep {
  height: 1px;
  background: var(--border);
  margin: 5px 8px;
  border: 0;
  flex-shrink: 0;
}
#g-overflow-menu .menu-sep-admin {
  height: auto;
  background: none;
  margin: 8px 4px 3px;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-3xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-dim);
}
#g-overflow-menu .menu-sep-admin::before,
#g-overflow-menu .menu-sep-admin::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Mobile-only sizing tweaks (the ••• show / secondary-hide rules are now
   global, applied above for all screen sizes). */
/* Exception canon (décision B) — chrome du header de jeu, voir §RESPONSIVE OVAL SIZE. */
@media (max-width: 740px) {
  /* Hauteur uniforme pour tous les btn-sm du header jeu */
  #s-game .header .btn-sm {
    height: 30px;
    padding: 0 9px;
    font-size: var(--fs-base);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
  }
  /* Boutons-icone (quitter, son, trophee, roue crantee) : le padding 0 9px
     ci-dessus laissait 16 px de contenu dans les 34 px -> les SVG 22 px se
     faisaient COMPRESSER (flex-shrink) et paraissaient plus petits qu'aux
     headers login/lobby. On restaure padding 0 -> icones 22 px partout. */
  #s-game .header .btn-icon { width: 34px; padding: 0; }
  /* Le menu ••• du jeu reprend le style "liste" (aligné à gauche, plus
     compact) au lieu d'hériter du centrage/hauteur fixe des boutons du
     header ci-dessus => menu nettement moins large. Sélecteur 2 ids pour
     l'emporter sur "#s-game .header .btn-sm". */
  #s-game .header #g-overflow-menu { width: 214px; }
  #s-game .header #g-overflow-menu .btn-sm {
    justify-content: flex-start;
    text-align: left;
    height: auto;
    padding: 8px 24px 8px 11px;
    font-size: var(--fs-xs);
  }
  #g-overflow-menu .menu-tick,
  #l-overflow-menu .menu-tick { right: 9px; }
  #s-game .header-brand {
    font-size: var(--fs-sm);
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Nom de table sur mobile : DANS LE FLUX flex (pas d'absolu → jamais sous
     les icones de droite) mais CENTRE entre la porte (quitter) et le premier
     bouton de droite (son) — demande narmod. flex:1 + justify center ; le
     nom tronque en « ... » et cede toujours la place aux boutons. */
  #s-game .header-brand--game {
    position: static;
    transform: none;
    max-width: none;
    flex: 1 1 auto;
    min-width: 0;
    justify-content: center;
  }
  /* header-pills : plus besoin de spacer — la brand flex:1 ci-dessus occupe
     deja tout l'espace libre et pousse les boutons a droite. */
  #s-game .header-pills { display: none; }
  #s-game .header { gap: var(--sp-1); padding: 3px 8px; }
  /* Hauteur de header UNIFORME (demande narmod) : meme 38 px que desktop,
     tablette et login — base topBar QML 2.1.3. Padding vertical 4 px
     (boutons 30 px + 4+4 = 38). L'ancien 48 px mobile est retire. */
  #s-game .header { padding-top: 4px; padding-bottom: 4px; min-height: var(--header-h, 38px); }
  /* Barre d'état : hauteur/tailles QML identiques au desktop (40 px, 13/11) —
     le mode landscapeCompact (28 px) est géré par sa propre media query. */
  /* Mobile : même asservissement --comm-scale que la règle de base, base un
     cran au-dessus (12 px ≈ l'ancien 0.68rem à échelle 1). */
  #pot-strip .blinds-next { font-size: clamp(10px, calc(12px * var(--comm-scale, 1)), 16px); }

  /* ── Lobby header on narrow phones ──
     On small/large-font devices the "POKERTH" word + redundant buttons
     squeezed the name + player-count pills (they got clipped). Free the
     space: collapse the brand to just the ♠ glyph, drop the standalone
     Fullscreen + language buttons (both still reachable via the ••• menu),
     and tighten the gap. The pills (flex:1) then get the room they need. */
  /* The ♠ acts as a toggle: tap it to slide POKERTH in/out. Collapsed by
     default on narrow screens (max-width:0 + fade), expanded when JS adds
     .brand-open to #lobby-brand. The width transition gives the small
     reveal effect. */
  #s-lobby .header-brand .brand-text {
    display: inline-block;
    max-width: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    transition: max-width 0.28s ease, opacity 0.22s ease, margin 0.28s ease;
    margin-left: 0;
  }
  #s-lobby #lobby-brand.brand-open .brand-text {
    max-width: 8em;
    opacity: 1;
    margin-left: 0;
  }
  #s-lobby #fs-btn-lobby,
  #s-lobby #lang-toggle-lobby { display: none; }
  #s-lobby .header { gap: var(--sp-2); padding: 3px 8px; }
  /* Header du lobby aligné sur le header du jeu, pour une hauteur uniforme
     entre les écrans (demande narmod). Même variable que #s-game .header. */
  #s-lobby .header { padding-top: 4px; padding-bottom: 4px; min-height: var(--header-h, 38px); }
  #s-lobby .header-pills { flex: 1; min-width: 0; }
}


/* ═══════════════════════════════════════════════════════
   ANIMATIONS DE JEU
   ═══════════════════════════════════════════════════════ */

/* ── Distribution des cartes (hole cards) ── */
@keyframes dealCard {
  0%   { transform: translateY(60px) rotate(-8deg) scale(0.6); opacity: 0; }
  60%  { transform: translateY(-4px) rotate(1deg) scale(1.04); opacity: 1; }
  100% { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; }
}
.pk-deal {
  animation: dealCard 0.38s cubic-bezier(.2,.8,.3,1) both;
}
.pk-deal:nth-child(2) { animation-delay: 0.15s; }

/* ── Flip cartes communes (amélioré) ── */
@keyframes cardFlip {
  0%   { transform: rotateY(90deg) scale(0.85); opacity: 0; }
  55%  { transform: rotateY(-6deg) scale(1.06); opacity: 1; }
  80%  { transform: rotateY(3deg) scale(0.99); }
  100% { transform: rotateY(0deg) scale(1); opacity: 1; }
}
/* Timings officiels (bible §9) : flop échelonné 0 / 120 / 240 ms, turn et
   river IMMÉDIATS — durée 260 ms partout (fondu QML ; on garde le flip web,
   héritage ShowFlipCardsAnimation du client Qt-Widgets, aux timings QML). */
.pk-flip { animation: cardFlip 0.26s cubic-bezier(.3,0,.2,1) both; }
.pk-flip:nth-child(1) { animation-delay: 0s; }
.pk-flip:nth-child(2) { animation-delay: 0.12s; }
.pk-flip:nth-child(3) { animation-delay: 0.24s; }
.pk-flip:nth-child(4) { animation-delay: 0s; }
.pk-flip:nth-child(5) { animation-delay: 0s; }

/* ── Joueur actif — anneau pulsant ── */
@keyframes activeRing {
  0%   { box-shadow: 0 0 0 0 rgba(var(--gold-rgb), 0.7), 0 0 12px rgba(var(--gold-rgb), 0.4); }
  50%  { box-shadow: 0 0 0 5px rgba(var(--gold-rgb), 0), 0 0 20px rgba(var(--gold-rgb), 0.6); }
  100% { box-shadow: 0 0 0 0 rgba(var(--gold-rgb), 0.7), 0 0 12px rgba(var(--gold-rgb), 0.4); }
}
.seat.active .seat-avatar {
  animation: activeRing 1.2s ease-in-out infinite !important;
}

/* ── Mon tour — barre actions pulse ── */
@keyframes myTurnBorder {
  0%,100% { border-top-color: var(--gold); box-shadow: 0 -3px 18px rgba(var(--gold-rgb), 0.25); }
  50%     { border-top-color: #ffe066;    box-shadow: 0 -3px 32px rgba(var(--gold-rgb), 0.55); }
}
.my-zone.my-turn-active {
  animation: myTurnBorder 1.5s ease-in-out infinite;
}

/* ── Gagnant — explosion d'étoiles ── */
@keyframes starPop {
  0%   { transform: translate(-50%,-50%) scale(0) rotate(0deg);   opacity: 1; }
  60%  { transform: translate(var(--tx),var(--ty)) scale(1) rotate(var(--rot)); opacity: 1; }
  100% { transform: translate(var(--tx),var(--ty)) scale(0.3) rotate(var(--rot)); opacity: 0; }
}
.win-star {
  position: fixed;
  font-size: var(--fs-xl);
  pointer-events: none;
  z-index: 600;
  animation: starPop 1.1s cubic-bezier(.2,.8,.3,1) forwards;
  left: 50%; top: 40%;
}

/* ── Action joueur — badge flash ── */
@keyframes actionFlash {
  0%   { transform: scale(0.5); opacity: 0; }
  50%  { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(1);   opacity: 1; }
}
.seat-action-label.flash {
  animation: actionFlash 0.3s ease-out both;
}

/* ── Pot — comptage animé ── */
@keyframes potBump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.18); color: #ffe066; }
  100% { transform: scale(1); }
}
.pot-bump { animation: potBump 0.35s ease-out; }

/* ── Pli (fold) — carte qui tombe ── */
@keyframes foldCard {
  0%   { transform: translateY(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(30px) rotate(15deg); opacity: 0; }
}
.pk-fold { animation: foldCard 0.28s ease-in forwards; }

/* ── Jeton volant ── */
.flying-chip {
  position: fixed;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #ffe066, #c8a820);
  border: 2px solid rgba(255,255,255,0.5);
  box-shadow: 0 2px 8px rgba(0,0,0,0.5), inset 0 1px 2px rgba(255,255,255,0.3);
  font-size: 0.4rem; color: #3a2000; font-weight: 900;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; z-index: 500;
  transition: left 0.5s cubic-bezier(.4,0,.2,1),
              top  0.5s cubic-bezier(.25,0.46,0.45,0.94),
              opacity 0.18s ease 0.42s,
              transform 0.5s ease;
}

/* ══ CARD FLIP ANIMATION — (replaced above) ══ */
@keyframes _cardFlip_unused {
  0%   { transform: rotateY(90deg) scale(0.85); opacity: 0; }
  60%  { transform: rotateY(-8deg) scale(1.04); opacity: 1; }
  100% { transform: rotateY(0deg)  scale(1);    opacity: 1; }
}
.pk-flip { animation: cardFlip 0.32s cubic-bezier(.4,0,.2,1) both; }
.pk-flip:nth-child(2) { animation-delay: 0.07s; }
.pk-flip:nth-child(3) { animation-delay: 0.14s; }
.pk-flip:nth-child(4) { animation-delay: 0.21s; }
.pk-flip:nth-child(5) { animation-delay: 0.28s; }

/* ══ CHIP ANIMATION ══ */
.flying-chip {
  position: fixed;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #f0c040, #c8a820);
  border: 2px solid rgba(255,255,255,0.4);
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
  font-size: 0.45rem; color: #3a2000; font-weight: 900;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; z-index: 500;
  transition: left 0.55s cubic-bezier(.4,0,.2,1),
              top  0.55s cubic-bezier(.4,0,.2,1),
              opacity 0.2s ease 0.45s,
              transform 0.55s ease;
}

/* ══ HAND STRENGTH DISPLAY ══ */
#hand-strength {
  /* Couche pleine largeur posee sur le bord haut de .player-bar.
     height:0 -> n'ajoute aucune hauteur : la barre garde sa taille. */
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 0;
  pointer-events: none;
  z-index: 3;
  --hs-col: var(--gold);
}
#hand-strength .hs-track {
  position: absolute;
  left: 10px; right: 10px; top: 0;
  height: 3px;
  border-radius: 0 0 3px 3px;
  background: rgba(255,255,255,0.12);
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
}
#hand-strength .hs-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--hs-col);
  border-radius: 0 0 3px 3px;
  transition: width 0.35s cubic-bezier(.4,0,.2,1), background 0.3s ease;
}
.pb-right-zone {
  flex: 1 1 auto;
  min-width: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
}
.pb-act-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}
.hs-lbl {
  flex: 0 0 auto;
  align-self: center;
  max-width: 100%;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 8px;
  background: rgba(0,0,0,0.80);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 5px;
  pointer-events: none;
}
:root:not([data-theme="pokerth-light"]) .hs-lbl {
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,255,255,0.18);
}
:root[data-theme="pokerth"] .hs-lbl,
:root[data-theme="dark"] .hs-lbl,
:root[data-theme="redfelt"] .hs-lbl {
  background: rgba(96,110,135,0.40);
  border: 1px solid rgba(255,255,255,0.13);
}
.hs-txt {
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  line-height: 1.15;
  letter-spacing: 0.01em;
  font-weight: 700;
  color: var(--gold);
  text-align: center;
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-shadow: 0 0 3px rgba(0,0,0,0.85), 0 1px 1px rgba(0,0,0,0.9);
}

/* ══ PANNEAU RÉACTIONS FLOTTANT (header) ══ */
#g-reaction-panel {
  flex-direction: column;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  padding: 10px 14px 12px;
  flex-shrink: 0;
}
@keyframes slideDown {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.react-panel-title {
  font-size: var(--fs-3xs);
  color: var(--gold-dim);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.react-panel-close {
  background: none; border: none; color: var(--text);
  cursor: pointer; font-size: var(--fs-md); padding: 0 2px; line-height: 1;
}
/* Bouton "couper les reactions" : emoji barre d'une interdiction quand actif */
.react-title-actions { display: flex; align-items: center; gap: var(--sp-3); }
.react-mute-btn {
  position: relative;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-size: var(--fs-md); line-height: 1;
  padding: 0; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.react-mute-btn:hover { background: rgba(var(--gold-rgb), 0.15); border-color: var(--gold-dim); }
/* Épingle du panneau réactions : même gabarit que le bouton mute. Non épinglé
   (défaut) = la fenêtre se ferme après chaque réaction (parité QML) ; épinglé
   = bord + fond or, la fenêtre reste ouverte. */
.react-pin-btn {
  position: relative;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-size: var(--fs-base); line-height: 1;
  padding: 0; cursor: pointer;
  filter: grayscale(1); opacity: 0.6;
  transition: background 0.15s, border-color 0.15s, filter 0.15s, opacity 0.15s;
}
.react-pin-btn:hover { background: rgba(var(--gold-rgb), 0.15); border-color: var(--gold-dim); }
.react-pin-btn:active { transform: scale(0.92); }
.react-pin-btn.pinned {
  filter: none; opacity: 1;
  border-color: var(--gold-dim);
  background: rgba(var(--gold-rgb), 0.2);
}
.react-mute-btn:active { transform: scale(0.92); }
.react-mute-btn .rm-emo { transition: filter 0.15s, opacity 0.15s; pointer-events: none; }
.react-mute-btn.muted { border-color: rgba(var(--red-rgb), 0.55); }
.react-mute-btn.muted .rm-emo { filter: grayscale(1); opacity: 0.5; }
.react-mute-btn::after {
  content: ""; position: absolute;
  width: 19px; height: 19px;
  border: 2px solid var(--red); border-radius: 50%;
  pointer-events: none;
}
.react-mute-btn::before {
  content: ""; position: absolute;
  width: 19px; height: 2px;
  background: var(--red); border-radius: 2px;
  transform: rotate(-45deg);
  pointer-events: none;
}
/* Grille grisee + inerte quand les reactions sont coupees */
.react-grid.react-muted { filter: grayscale(1); opacity: 0.4; }
.react-grid.react-muted .react-btn { pointer-events: none; cursor: default; }
.react-grid.react-muted .react-btn:hover { background: var(--inset); border-color: var(--border); transform: none; }
.react-grid {
  display: grid;
  /* Desktop: all 30 reactions on a single line. 1fr tracks fill the
     available width so they never overflow; max-width keeps the cells
     from ballooning on ultra-wide screens, margin auto re-centres. */
  grid-template-columns: repeat(30, 1fr);
  gap: 3px;
  max-width: 1120px;
  margin: 0 auto;
}
@media (max-width: 900px) {
  /* Tablet: 2 lines (15 + 15). */
  .react-grid { grid-template-columns: repeat(15, 1fr); max-width: none; }
}
@media (max-width: 600px) {
  /* Phone : grille montrant 2 lignes ; si tout ne rentre pas -> scroll vertical.
     Tablette (601-900px) et desktop gardent leur propre grille. */
  .react-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 40px);
    justify-content: center;
    /* largeur definie + marge nulle : annule le `margin:0 auto` de base qui,
       sur un item flex, empechait l'etirement (=> 1 seule colonne). */
    width: 100%;
    max-width: none;
    margin: 0;
    gap: var(--sp-2);
    max-height: 88px;       /* ~2 lignes (cellule 40px + interligne) */
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }
  /* Use nearly the full panel width on phones (was 14px each side). */
  #g-reaction-panel { padding: 8px 5px 9px; }
}
.react-btn {
  aspect-ratio: 1;       /* square, height follows the column width */
  width: 100%;           /* fill the grid track (size set by .react-grid) */
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: var(--fs-xl);     /* desktop emoji size (cells ~34px) */
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.12s ease, background 0.12s, border-color 0.12s;
  position: relative;
  padding: 0;            /* no padding → compact cell */
}
@media (max-width: 900px) {
  /* Tablet: bigger cells → bigger glyphs. */
  .react-btn { font-size: 1.7rem; }
}
@media (max-width: 600px) {
  /* Phone : pastilles carrees, taille de cellule pilotee par la grille. */
  .react-btn { font-size: 1.5rem; }
}
.react-btn:hover {
  background: rgba(var(--gold-rgb), 0.15);
  border-color: var(--gold-dim);
  transform: scale(1.2);
}
.react-btn:active { transform: scale(0.92); }
.react-btn .rc {
  position: absolute;
  bottom: 1px; right: 3px;
  font-size: 0.45rem;
  font-family: monospace;
  color: var(--gold);
  line-height: 1;
  pointer-events: none;
}

/* Ancien .reaction-bar (dans chat) — masqué */
/* ══ RÉACTIONS RAPIDES ══ */
.reaction-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 5px 10px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  justify-content: center;
  flex-wrap: wrap;
}
.reaction-bar-label {
  font-size: var(--fs-3xs);
  color: var(--text);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  flex-basis: 100%;
  text-align: center;
  margin-bottom: 1px;
  opacity: 0.6;
}
.reaction-btn {
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 4px 10px;
  font-size: var(--fs-lg);
  cursor: pointer;
  transition: transform 0.12s ease, background 0.15s, border-color 0.15s;
  display: flex; align-items: center; gap: var(--sp-1);
  line-height: 1;
  position: relative;
  overflow: visible;
}
.reaction-btn:hover {
  background: rgba(var(--gold-rgb), 0.15);
  border-color: var(--gold-dim);
  transform: scale(1.15);
}
.reaction-btn:active { transform: scale(0.92); }
.reaction-btn .react-count {
  font-size: var(--fs-2xs);
  font-family: monospace;
  color: var(--gold);
  min-width: 10px;
}

/* Emoji flottant animé au-dessus de la table */
@keyframes floatReaction {
  0%   { transform: translateY(0)  scale(0.5) rotate(-8deg); opacity: 0; }
  15%  { transform: translateY(-20px) scale(1.3) rotate(5deg);  opacity: 1; }
  70%  { transform: translateY(-120px) scale(1) rotate(-3deg); opacity: 1; }
  100% { transform: translateY(-180px) scale(0.8) rotate(8deg); opacity: 0; }
}
.floating-reaction {
  position: fixed;
  font-size: 2.2rem;
  pointer-events: none;
  z-index: 650;
  animation: floatReaction 2.2s cubic-bezier(.2,.8,.3,1) forwards;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.5));
}

/* Badge réaction sur avatar joueur */
@keyframes reactionBadge {
  0%   { transform: scale(0) rotate(-20deg); opacity: 0; }
  30%  { transform: scale(1.3) rotate(5deg);  opacity: 1; }
  70%  { transform: scale(1)   rotate(0deg);  opacity: 1; }
  100% { transform: scale(0.9) rotate(0deg);  opacity: 0; }
}
.seat-reaction {
  position: absolute;
  top: -18px; left: 50%;
  transform: translateX(-50%);
  font-size: var(--fs-xl);
  pointer-events: none;
  animation: reactionBadge 2.5s ease forwards;
  z-index: 10;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.6));
}

/* ══ RÉACTIONS ANIMÉES (chorégraphies CSS/JS) ══ */
.rfx { position: fixed; z-index: 700; pointer-events: none; width: 0; height: 0; }
.rfx .rfx-big { position: absolute; left: 0; top: 0; font-size: var(--fs-hero); display: inline-block;
  filter: drop-shadow(0 3px 10px rgba(0,0,0,0.55)); }
.rfx .rfx-pt { position: absolute; left: 0; top: 0; will-change: transform, opacity; line-height: 1; }
.rfx .rfx-ring { position: absolute; left: 0; top: 0; width: 30px; height: 30px;
  border: 3px solid var(--gold-hi); border-radius: 50%;
  transform: translate(-50%,-50%) scale(0.3); opacity: 0.9; animation: rfxRing 0.8s ease-out forwards; }
@keyframes rfxRing { to { transform: translate(-50%,-50%) scale(4); opacity: 0; } }
@keyframes rfxPop  {0%{transform:translate(-50%,-50%) scale(.2);opacity:0}25%{transform:translate(-50%,-50%) scale(1.45);opacity:1}55%{transform:translate(-50%,-60%) scale(1.05)}100%{transform:translate(-50%,-150%) scale(.9);opacity:0}}
@keyframes rfxFire {0%{transform:translate(-50%,-50%) scale(.3);opacity:0}20%{transform:translate(-50%,-55%) scale(1.4);opacity:1}40%{transform:translate(-50%,-70%) scale(1.2) rotate(-4deg)}60%{transform:translate(-50%,-90%) scale(1.35) rotate(4deg)}100%{transform:translate(-50%,-150%) scale(1);opacity:0}}
@keyframes rfxShake{0%{transform:translate(-50%,-50%) scale(.3);opacity:0}15%{transform:translate(-50%,-55%) scale(1.35) rotate(0);opacity:1}25%{transform:translate(-50%,-60%) rotate(-14deg)}35%{transform:translate(-50%,-65%) rotate(14deg)}45%{transform:translate(-50%,-72%) rotate(-12deg)}55%{transform:translate(-50%,-80%) rotate(12deg)}70%{transform:translate(-50%,-95%) rotate(-6deg)}85%{transform:translate(-50%,-115%) rotate(4deg)}100%{transform:translate(-50%,-150%) rotate(0);opacity:0}}
@keyframes rfxBeat {0%{transform:translate(-50%,-50%) scale(.2);opacity:0}20%{transform:translate(-50%,-55%) scale(1.5);opacity:1}33%{transform:translate(-50%,-60%) scale(1.05)}48%{transform:translate(-50%,-70%) scale(1.4)}63%{transform:translate(-50%,-82%) scale(1.1)}100%{transform:translate(-50%,-150%) scale(1);opacity:0}}
@keyframes rfxSpin {0%{transform:translate(-50%,-50%) scale(.3) rotate(0);opacity:0}25%{transform:translate(-50%,-60%) scale(1.45) rotate(200deg);opacity:1}100%{transform:translate(-50%,-150%) scale(1) rotate(720deg);opacity:0}}
@keyframes rfxShine{0%{transform:translate(-50%,-50%) scale(.3);opacity:0;filter:brightness(1)}25%{transform:translate(-50%,-58%) scale(1.45);opacity:1}50%{filter:brightness(2.2) drop-shadow(0 0 10px var(--gold-hi))}100%{transform:translate(-50%,-150%) scale(1.05);opacity:0;filter:brightness(1)}}
@keyframes rfxFlex {0%{transform:translate(-50%,-50%) scale(.3);opacity:0}20%{transform:translate(-50%,-55%) scale(1.5)}35%{transform:translate(-50%,-60%) scale(1.1)}50%{transform:translate(-50%,-70%) scale(1.45)}70%{transform:translate(-50%,-90%) scale(1.15)}100%{transform:translate(-50%,-150%) scale(1);opacity:0}}
.rfx-anim-pop  { animation: rfxPop  1.6s cubic-bezier(.2,.8,.3,1) forwards; }
.rfx-anim-fire { animation: rfxFire 1.7s ease-out forwards; }
.rfx-anim-shake{ animation: rfxShake 1.7s ease-out forwards; }
.rfx-anim-beat { animation: rfxBeat 1.7s ease-out forwards; }
.rfx-anim-spin { animation: rfxSpin 1.6s cubic-bezier(.2,.7,.3,1) forwards; }
.rfx-anim-shine{ animation: rfxShine 1.6s ease-out forwards; }
.rfx-anim-flex { animation: rfxFlex 1.6s ease-out forwards; }

/* ══ RECONNECT BANNER ══ */
/* In-app "new version available" banner (bottom, gold accent). Created on
   the fly by the inline SW-update checker when /__ver changes after a deploy. */
#update-banner {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%);
  z-index: 1000;
  display: flex; align-items: center; gap: var(--sp-5);
  background: var(--modal-bg);
  border: 1px solid var(--gold);
  border-radius: 8px;
  padding: 9px 12px 9px 16px;
  box-shadow: 0 6px 22px rgba(0,0,0,0.55);
  font-family: var(--ff-display); font-size: var(--fs-base);
  color: var(--cream); letter-spacing: 0.04em;
  max-width: calc(100% - 24px);
  animation: fadeIn 0.3s ease;
}
#update-banner button {
  background: var(--gold); color: var(--on-gold); border: none;
  border-radius: 5px; padding: 6px 14px; cursor: pointer;
  font-family: var(--ff-display); font-weight: 700; font-size: var(--fs-sm);
  letter-spacing: 0.06em; white-space: nowrap;
  transition: filter 0.12s;
}
#update-banner button:hover { filter: brightness(1.12); }

#reconnect-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 999;
  background: rgba(var(--red-rgb), 0.95);
  color: #fff; text-align: center;
  padding: 6px 12px; font-size: var(--fs-sm);
  font-family: var(--ff-display); letter-spacing: 0.08em;
  display: none; align-items: center; justify-content: center; gap: var(--sp-4);
  animation: fadeIn 0.3s ease;
}
#reconnect-banner.visible { display: flex; }
#reconnect-banner .rc-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #fff; animation: pulse 1s infinite;
}
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }

/* ── Pastille de connexion sur le feutre ──
   Remplace le bandeau plein écran quand la table est affichée (voir
   _showBanner). Ancrée comme .comm-row (centre des cartes communes,
   --comm-shift-y compris) ; DANS #g-table-scaler → hérite du scale générique
   de la table, et la police suit --comm-scale (même modèle que
   .win-hand-badge / .pot-badge) → grossit/rétrécit avec la résolution. */
.conn-pill {
  position: absolute;
  top: calc(50% + var(--comm-shift-y, 0px)); left: 50%;
  transform: translate(-50%, -50%);
  z-index: 60;                 /* au-dessus des cartes et du badge de main */
  display: flex; align-items: center; justify-content: center;
  gap: max(5px, calc(8px * var(--comm-scale, 1)));
  padding: max(3px, calc(5px * var(--comm-scale, 1))) max(9px, calc(14px * var(--comm-scale, 1)));
  border-radius: var(--r-pill);
  background: rgba(var(--red-rgb), 0.95);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 0 14px rgba(var(--red-rgb), 0.5), 0 4px 14px rgba(0, 0, 0, 0.45);
  color: #fff;
  font-family: var(--ff-display); letter-spacing: 0.08em;
  font-size: max(10px, calc(12px * var(--comm-scale, 1)));
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;        /* n'intercepte jamais un tap destiné au feutre */
  animation: fadeIn 0.3s ease;
}
.conn-pill .rc-dot {
  width: max(6px, calc(8px * var(--comm-scale, 1)));
  height: max(6px, calc(8px * var(--comm-scale, 1)));
  border-radius: 50%; background: #fff; animation: pulse 1s infinite;
  flex: none;
}

/* ══ HANDS HELP OVERLAY ══ */
#hands-overlay {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background: transparent; pointer-events: none;  /* fenêtre flottante, pas de backdrop */
  padding: var(--sp-5);
}
#hands-card-inner { pointer-events: auto; }
.hand-row {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 7px 6px; border-bottom: 1px solid rgba(var(--gold-rgb), 0.07);
  border-radius: 4px; transition: background 0.12s;
}
.hand-row:hover { background: var(--inset-hi); }
.hand-rank {
  width: 20px; text-align: center; flex-shrink: 0;
  font-size: var(--fs-2xs); color: var(--gold-dim); font-family: var(--ff-display);
}
.hand-cards { display: flex; gap: var(--sp-0); flex-shrink: 0; }
.hc {
  width: 22px; height: 32px; border-radius: var(--r-xs);
  background: #f8f5ee; border: 1px solid #ccc;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  font-size: var(--fs-3xs); font-weight: 700; line-height: 1.1;
  color: #111; box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.hc.r { color: #c0392b; }
.hand-info { flex: 1; min-width: 0; }
.hand-name {
  font-size: var(--fs-sm); color: var(--text-hi); font-weight: 600;
  font-family: var(--ff-display); letter-spacing: 0.04em;
  display: flex; align-items: center; gap: var(--sp-2);
}
.hand-ico { font-size: var(--fs-md); line-height: 1; flex-shrink: 0; }
.hand-desc { font-size: var(--fs-2xs); color: var(--text); margin-top: 1px; }
.hand-desc .hand-ex { color: var(--gold-hi); }
/* Rail de force (vert fort → gris faible) à gauche de chaque ligne */
.hand-rail { width: 4px; border-radius: var(--r-xs); flex-shrink: 0; align-self: stretch; }
/* Carte qui COMPTE = éclairée ; carte inutile = estompée */
.hc.key  { box-shadow: 0 0 0 1.5px var(--gold-hi), 0 0 7px rgba(224,192,112,0.55); }
.hc.kick { opacity: 0.34; filter: grayscale(0.55); }
/* Légende pédagogique */
.hands-legend {
  display: flex; align-items: center; justify-content: center;
  gap: var(--sp-5); flex-wrap: wrap; font-size: var(--fs-2xs); color: var(--text);
  padding: 8px 0 7px; margin-bottom: 4px;
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.07);
}
.hands-legend .hl { display: flex; align-items: center; gap: 5px; }
.hl-mini { width: 13px; height: 18px; border-radius: 2px; background: #f8f5ee; border: 1px solid #ccc; display: inline-block; }
.hl-mini.bright { box-shadow: 0 0 0 1.5px var(--gold-hi), 0 0 5px rgba(224,192,112,0.6); }
.hl-mini.dim { opacity: 0.34; filter: grayscale(0.5); }
.hl-grad { width: 46px; height: 7px; border-radius: 4px; display: inline-block;
  background: linear-gradient(90deg,#2ecc71,#c9b144,#6f6353); }

/* ══ ANIMATIONS — Distribution, jetons, flip, stats ══ */

/* Carte volante lors de la distribution */
.fly-card {
  position: fixed; pointer-events: none; z-index: 400;
  width: 26px; height: 37px;
  background: var(--card-back) center / 100% 100% no-repeat, #16301a;
  border-radius: var(--r-xs); border: 1px solid rgba(255,255,255,0.25);
  box-shadow: 0 3px 10px rgba(0,0,0,0.5);
  transition: left 0.42s cubic-bezier(.2,.8,.3,1),
              top  0.42s cubic-bezier(.2,.8,.3,1),
              transform 0.42s ease, opacity 0.15s ease;
}

/* Jeton volant vers le pot */
.fly-chip {
  position: fixed; pointer-events: none; z-index: 400;
  width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f5e67a, #c8a850 60%, #8b6914);
  border: 2px solid #5a3800;
  box-shadow: 0 2px 6px rgba(0,0,0,0.6);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.38rem; font-weight: 900; color: #3d2b00;
  transition: left 0.5s cubic-bezier(.3,.9,.4,1),
              top  0.5s cubic-bezier(.3,.9,.4,1),
              opacity 0.2s ease 0.35s, transform 0.5s ease;
}

/* Flip 3D des cartes communes */
@keyframes flipCard3D {
  0%   { transform: perspective(400px) rotateY(-90deg) scale(0.85); opacity: 0; }
  55%  { transform: perspective(400px) rotateY(8deg)   scale(1.04); opacity: 1; }
  80%  { transform: perspective(400px) rotateY(-3deg)  scale(1); }
  100% { transform: perspective(400px) rotateY(0deg)   scale(1); opacity: 1; }
}
.pk.flip-reveal {
  animation: flipCard3D 0.45s cubic-bezier(.25,.8,.25,1) both;
}

/* Panneau statistiques de session */
#stats-overlay {
  position: fixed; top: 36px; right: 0;
  width: 240px; max-height: calc(100vh - 36px);
  background: var(--panel);
  border-left: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  z-index: 200; overflow-y: auto;
  animation: slideDown 0.2s ease;
}
.stats-header {
  padding: 8px 12px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--fs-2xs); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold-dim);
}
.stats-body { padding: 10px 12px; display: flex; flex-direction: column; gap: var(--sp-3); }
.stat-row { display: flex; justify-content: space-between; align-items: center; }
.stat-label { font-size: var(--fs-2xs); color: var(--text); }
.stat-val { font-size: var(--fs-xs); font-weight: 700; font-family: var(--ff-mono); }
.stat-val.pos { color: var(--pos); }
.stat-val.neg { color: var(--neg); }
.stat-divider { border: none; border-top: 1px solid var(--border); margin: 4px 0; }
/* Stats panel tabs (Session / Total / Ranking) */
.stats-tabs { display: flex; border-bottom: 1px solid var(--border); }
.stats-tab {
  flex: 1; background: none; border: none; cursor: pointer;
  padding: 7px 4px; font-size: var(--fs-2xs); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text); font-family: var(--ff-display);
  border-bottom: 2px solid transparent; transition: color 0.12s, border-color 0.12s;
}
.stats-tab.active { color: var(--sel,var(--gold)); border-bottom-color: var(--sel,var(--gold)); }
.stat-note { font-size: var(--fs-3xs); color: var(--gold-dim); line-height: 1.3; margin-bottom: 2px; }
.stat-empty { font-size: var(--fs-2xs); color: var(--text); text-align: center; padding: 14px 0; }
.stats-reset {
  margin-top: 2px; background: rgba(var(--red-rgb), 0.12); color: var(--red);
  border: 1px solid rgba(var(--red-rgb), 0.4); border-radius: 5px; cursor: pointer;
  padding: 7px; font-size: var(--fs-2xs); font-family: var(--ff-display); letter-spacing: 0.06em;
  transition: background 0.12s;
}
.stats-reset:hover { background: rgba(var(--red-rgb), 0.22); }
/* Leaderboard rows: rank · avatar · name · net on top, sub-line below */
.board-list { display: flex; flex-direction: column; }
.board-row {
  display: grid; align-items: center;
  grid-template-columns: 1.6rem 1.4rem 1fr auto;
  grid-template-areas: "rank av name net" "sub sub sub sub";
  column-gap: 6px; row-gap: 1px;
  padding: 6px 0; border-bottom: 1px solid var(--border);
}
.board-row.me { background: rgba(var(--gold-rgb), 0.10); border-radius: 4px; padding-left: 4px; padding-right: 4px; }
.board-rank { grid-area: rank; font-size: var(--fs-sm); text-align: center; }
.board-av   { grid-area: av; font-size: var(--fs-md); text-align: center; line-height: 1; }
.board-name { grid-area: name; font-size: var(--fs-xs); color: var(--cream); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-net  { grid-area: net; font-size: var(--fs-xs); font-weight: 700; font-family: var(--ff-mono); }
.board-net.pos { color: var(--pos); }
.board-net.neg { color: var(--neg); }
.board-sub  { grid-area: sub; font-size: var(--fs-3xs); color: var(--gold-dim); font-family: var(--ff-mono); }
.board-sort { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 6px; }
.board-sort > span { color: var(--gold-dim); font-size: var(--fs-xs); }
.board-sort select {
  flex: 1; background: var(--field-bg); border: 1px solid var(--border);
  border-radius: var(--r-xs); color: var(--cream); padding: 3px 6px;
  font-family: var(--ff-mono); font-size: var(--fs-xs); outline: none; cursor: pointer;
}
.board-myrank {
  font-size: var(--fs-2xs); color: var(--gold); font-family: var(--ff-mono);
  text-align: center; padding: 2px 0 6px; letter-spacing: 0.04em;
}
.hand-hist-item {
  background: var(--inset); border: 1px solid var(--border);
  border-radius: 4px; padding: 6px 8px; font-size: var(--fs-3xs);
}
.hand-hist-cards { display: flex; gap: 3px; margin-top: 3px; }
.hand-hist-result { margin-top: 3px; font-weight: 700; }



/* Loading dots */
@keyframes blink {
  0%,80%,100% { opacity: 0.2; }
  40%          { opacity: 1; }
}
.ld span { animation: blink 1.3s infinite; }
.ld span:nth-child(2) { animation-delay: 0.22s; }
.ld span:nth-child(3) { animation-delay: 0.44s; }

.btn-join {
  background: #2b3444;
  color: #ffffff;
  border: none;
  padding: 4px 12px;
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  border-radius: 2px;
  cursor: pointer;
  letter-spacing: 0.1em;
  transition: background 0.15s;
  flex-shrink: 0;
}
.btn-join:hover { background: #384252; }
.gl-guestlock { align-self: center; font-size: var(--fs-2xs); color: var(--text); opacity: 0.55; white-space: nowrap; padding: 3px 6px; border: 1px dashed var(--border); border-radius: var(--r-sm); }
.game-row { cursor: pointer; }

/* ═══ MOBILE: compact buttons in the available-tables list ═══
   On screens up to 540px, the Rejoindre + Regarder buttons were
   eating the entire row width, truncating the table name to
   "WebGame-o..." (see screenshot IMG_8007). The cluster on the
   right used to be: '2/2  ▶ REJOINDRE  👁 REGARDER'. We shrink the
   buttons and the count badge, drop the letter-spacing so the
   labels are tighter, and use shorter padding. The .game-info
   container already has flex:1 + min-width:0 (line 438), so any
   space freed here is automatically given to the name. */
@media (max-width: 599.98px) {
  .game-row { gap: var(--sp-3); padding: 10px 12px; }
  .game-name { font-size: var(--fs-base); }
  .game-meta { font-size: var(--fs-xs); gap: var(--sp-2); }
  .game-count { font-size: var(--fs-sm); }
  .btn-join {
    padding: 4px 8px;
    font-size: var(--fs-2xs);
    letter-spacing: 0.04em;
  }
  .btn-watch {
    padding: 4px 7px;
    font-size: var(--fs-2xs);
    letter-spacing: 0.04em;
  }
  /* Shrink the gap inside the right-hand button cluster */
  .game-row > div:last-child { gap: 6px !important; }
}

/* Even tighter on very narrow phones (e.g. iPhone SE, ~320-400px wide).
   The Rejoindre label has been "REJOINDRE / Partie rapide" stuff and
   risks dominating the row again. Just trim further. */
@media (max-width: 400px) {
  .game-row { padding: 9px 10px; gap: var(--sp-2); }
  .btn-join  { padding: 3px 6px; font-size: var(--fs-3xs); }
  .btn-watch { padding: 3px 5px; font-size: var(--fs-3xs); }
  .game-count { font-size: var(--fs-xs); }
  .game-row > div:last-child { gap: 4px !important; }
}

/* ═══ GAME SCREEN ═══ */
#s-game { overflow: visible; flex-direction: column; }

.game-area {
  position: relative; /* ancre des boutons de zoom de la table */
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 300px; /* fallback si flex échoue */
  overflow: visible;
  /* Space for fixed bottom bars */
  padding-bottom: clamp(110px, 17dvh, 140px);
}

.table-zone { display:flex; align-items:center; justify-content:center; overflow:visible; position:relative;
  flex: 1;
  min-height: 160px; /* garde-fou : ne jamais s'effondrer */
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.table-scaler { overflow: visible;
  padding: 30px 45px;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: center center;
  flex-shrink: 0;
  min-width: 300px;  /* garantit scrollWidth > 0 */
  min-height: 150px;
}

.felt-oval::before {
  content: '';
  position: absolute;
  inset: 10px;
  border-radius: 50% / 42%;
  border: 2px solid rgba(255,255,255,0.07);
  pointer-events: none;
}
.felt-oval { overflow: visible;
  width: min(520px, 90vw);
  height: min(240px, min(46vw, calc(100dvh - 250px)));
  min-height: 110px;
  background:
    /* Halo éclairage central (lampe au-dessus) */
    radial-gradient(ellipse 55% 45% at 50% 45%, rgba(255,255,220,0.07) 0%, transparent 70%),
    /* Ombres de bord (profondeur) */
    radial-gradient(ellipse 90% 80% at 50% 50%, transparent 60%, rgba(0,0,0,0.35) 100%),
    /* Texture tissu — lignes diagonales très fines */
    repeating-linear-gradient(
      45deg,
      transparent,
      transparent 3px,
      rgba(0,0,0,0.06) 3px,
      rgba(0,0,0,0.06) 4px
    ),
    repeating-linear-gradient(
      -45deg,
      transparent,
      transparent 3px,
      rgba(0,0,0,0.04) 3px,
      rgba(0,0,0,0.04) 4px
    ),
    /* Couleur de base dégradée */
    var(--felt-img, radial-gradient(ellipse 80% 60% at 50% 50%, var(--felt-base-hi) 0%, var(--felt-base-mid) 55%, var(--felt-base-lo) 100%));
  border-radius: 50% / 45%;
  border: 8px solid var(--rail);
  box-shadow:
    0 0 0 3px var(--rail-dark),
    0 0 0 5px var(--rail-glow),
    inset 0 2px 16px rgba(0,0,0,0.5),
    inset 0 -4px 20px rgba(0,0,0,0.3),
    0 20px 60px rgba(0,0,0,0.8),
    0 0 40px rgba(0,0,0,0.4);
  position: relative;
  overflow: visible;
  flex-shrink: 0;
}

/* Community cards — centred inside oval.
   The previous value top:56% pushed the row 6% below center, which on
   mobile/tablet visibly drifted the cards toward the bottom rim of the
   felt. Pure 50% centers them on the vertical axis of the oval (the
   gradient halo and shadow ring are already designed around 50%/45%). */
/* ── Cartes communes : modele QML 2.1.3 (bible §9) — slot 46x64 (ratio
   120:168 ≈ 0.714), spacing 3, le tout multiplie par --comm-scale
   (equivalent communityScale QML). UNE seule regle de taille pour tous les
   appareils ; seule l'echelle change par media ci-dessous (valeurs calees
   sur les rendus existants pour eviter toute regression) :
   desktop 1.35 (≈62x87) · tablette/base 1.0 (46x64 natif) ·
   phone portrait 1.15 (≈53x74) · paysage compact 0.62 (≈29x40). */
:root { --comm-scale: 1; }
@media (min-width: 900px) and (min-height: 600px) { :root { --comm-scale: 1.35; } }
/* Exception canon (décision B) — voir §RESPONSIVE OVAL SIZE. */
@media (max-width: 740px) and (orientation: portrait) { :root { --comm-scale: 1.15; } }
@media (orientation: landscape) and (max-height: 600px) { :root { --comm-scale: 0.62; } }
.comm-row {
  position: absolute;
  /* --comm-shift-y : décalage vertical piloté par renderSeats (parité QML
     communityArea — barycentre des boxes en paysage, ~centre en portrait). */
  top: calc(50% + var(--comm-shift-y, 0px)); left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  gap: calc(3px * var(--comm-scale, 1));
  align-items: center;
  justify-content: center; /* #g-comm est en flux pleine largeur (ID position:relative) -> centrer les cartes dedans */
}
.comm-row .pk {
  width: calc(46px * var(--comm-scale, 1));
  height: calc(64px * var(--comm-scale, 1));
  font-size: calc(1.02rem * var(--comm-scale, 1));
  border-radius: calc(5px * var(--comm-scale, 1));
}

/* Pot display */
.pot-display { display: none; }

/* Badge pot au-dessus des cartes (parité pot badge QML §9). Positionné dans le
   feutre, juste au-dessus de la rangée de cartes communes. Affiché sur TOUTES
   les tailles (mobile compris, demande narmod) quand le pot est non nul
   (classe .has-pot posée par setPot). */
.pot-badge {
  display: none;
  position: absolute;
  left: 50%;
  top: calc(50% + var(--comm-shift-y, 0px)); /* suit la rangée de cartes */
  /* Ancrage QML : bottom du badge = top des cartes communes + marge 8px,
     le tout suivant communityScale (--comm-scale). Demi-hauteur de carte
     32px + marge 8px = 40px x echelle -> position ET taille identiques au
     client officiel, en portrait comme en paysage, sur tous les appareils. */
  --pot-badge-lift: calc(40px * var(--comm-scale, 1));
  transform: translate(-50%, calc(-100% - var(--pot-badge-lift)));
  z-index: 6;
  align-items: center;
  gap: var(--sp-2);
  padding: max(2px, calc(3px * var(--comm-scale, 1))) max(7px, calc(10px * var(--comm-scale, 1)));
  background: rgba(0, 0, 0, 0.5);
  border: 1.5px solid var(--sel, #E3C800);   /* accent or QML (colorAccent), stable clair/sombre */
  border-radius: var(--r-pill);
  color: var(--sel, #E3C800);
  font-family: var(--ff-display);
  font-weight: 700;
  font-size: max(10px, calc(13px * var(--comm-scale, 1))); /* suit communityScale */
  letter-spacing: 0.05em;
  white-space: nowrap;
  box-shadow: 0 2px 9px rgba(0, 0, 0, 0.42);
  pointer-events: none;
}
.pot-badge::before {
  content: '';
  width: max(9px, calc(12px * var(--comm-scale, 1)));
  height: max(9px, calc(12px * var(--comm-scale, 1)));
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, #ffe89a 0%, #f2c94c 55%, #c99a1e 100%);
  border: 2px dashed rgba(0, 0, 0, 0.28);
  box-sizing: border-box;
  flex: 0 0 auto;
}
.pot-badge.has-pot { display: inline-flex; }
/* Le badge se positionne via transform:translate ; l'animation générique
   .pot-pop (transform:scale) écraserait ce translate → le badge sautait sur
   les cartes au flop. Pop dédié qui conserve le translate, et pas de
   display:inline-block forcé (respecte la visibilité tablette/desktop). */
.pot-badge.pot-pop { display: none; animation: potBadgePop 0.3s ease-out; }
.pot-badge.has-pot.pot-pop { display: inline-flex; }
@keyframes potBadgePop {
  0%, 100% { transform: translate(-50%, calc(-100% - var(--pot-badge-lift))) scale(1); }
  40%      { transform: translate(-50%, calc(-100% - var(--pot-badge-lift))) scale(1.16); }
}

.pot-bar {
  text-align: center;
  padding: 3px 0;
  font-family: var(--ff-display);
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--gold);
  letter-spacing: 0.12em;
  background: rgba(0,0,0,0.25);
  flex-shrink: 0;
}

.my-seat-row {
  display: flex;
  justify-content: center;
  padding: 4px 0;
  flex-shrink: 0;
}

/* Seats */
.seat {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-0);
  min-width: 44px;
  max-width: 68px;
}
/* Sièges cliquables : tap/clic → popup d'info joueur. #g-seats reste en
   pointer-events:none ; on réactive l'interaction au niveau du siège. Les
   sièges « fantômes » (joueur parti) restent non cliquables. Le halo de survol
   (drop-shadow, suit la forme ronde + la palette) est limité aux pointeurs
   précis pour éviter un survol « collé » au tap. */
.seat { pointer-events: auto; cursor: pointer; }
.seat-ghost { pointer-events: none; cursor: default; }
@media (hover: hover) {
  .seat:hover .seat-avatar { filter: drop-shadow(0 0 6px rgba(var(--gold-rgb), 0.85)); }
}

.seat-avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(0,0,0,0.5);
  border: 2px solid rgba(var(--gold-rgb), 0.3);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-xs); color: var(--text-hi);
  font-family: var(--ff-display);
  position: relative;
  transition: border-color 0.3s, box-shadow 0.3s;
}

/* ── PokerTH official avatar (downloaded from pokerth.net) ──
   When a player has uploaded an avatar on their pokerth.net account, we
   slot it in as an <img class="seat-pth-img"> inside the circular avatar
   wrapper. The wrapper gets .has-pth-avatar so we know to:
     - hide the text fallback (.seat-initial)
     - drop the background tint (the image fills the whole area)
   The image clips itself to a circle via border-radius:50% (no need to
   clip the parent). This is CRITICAL: setting overflow:hidden on the
   .seat-avatar would also clip the SB/BB chip (positioned top:-8px,
   left:-8px) and the dealer chip (top:-8px, right:-8px), which sit
   intentionally outside the circle for visibility. By keeping the
   parent overflow:visible and clipping only the <img> itself, we get
   the round avatar AND the chips remain visible on top. */
.seat-avatar.has-pth-avatar { background: rgba(0,0,0,0.2); }
.seat-avatar.has-pth-avatar > .seat-initial { display: none; }
.seat-avatar > .seat-pth-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* border-radius on a replaced element (<img>) clips the image content
     itself -- no overflow:hidden on the parent needed. */
  border-radius: 50%;
  /* Image must not block pointer events on overlapping chips/badges. */
  pointer-events: none;
  /* Stay BELOW the overlays. Badges/timer have explicit z-index >= 3. */
  z-index: 0;
}
/* Same treatment for the player-bar avatar (your own seat at the bottom).
   No overflow:hidden here either -- the green ring and shadow stay
   intact, the image clips itself via border-radius. */
.pb-avatar.has-pth-avatar { padding: 0; }
.pb-avatar > .pb-pth-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  pointer-events: none;
}
.me-oval-seat .seat-avatar {
  border: 2px solid var(--green) !important;
  box-shadow: 0 0 8px rgba(var(--green-rgb), 0.4);
}
.seat.active .seat-avatar {
  border-color: var(--gold);
  box-shadow: 0 0 12px rgba(var(--gold-rgb), 0.6);
}
/* Countdown arc around active seat avatar */
.seat-timer {
  position: absolute;
  width: 160%; height: 160%;
  top: -30%; left: -30%;
  pointer-events: none;
  overflow: visible;
  z-index: 2;
}
.seat-timer circle.bg  { fill:none; stroke:rgba(0,0,0,0.45); stroke-width:4.5; }
.seat-timer circle.arc { fill:none; stroke-width:4; stroke-linecap:round; }
/* Fond opaque derrière le chiffre */
.seat-timer circle.center-bg {
  fill: transparent;
  stroke: none;
}
.seat-timer text {
  font-size: 10px;
  font-family: monospace;
  font-weight: 900;
  text-anchor: middle;
  dominant-baseline: middle;
}
/* Quand le timer tourne : initiale ET emoji toujours visibles (au-dessus du SVG arc) */
.seat-avatar.timing > .seat-initial {
  display: flex !important;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 6;
}
.seat-avatar.emoji-av.timing > .seat-initial { display: flex; position: relative; z-index: 6; }
/* Avatar image (photo perso / PokerTH) : ne JAMAIS afficher l'initiale par-dessus,
   même pendant le timer. Plus specifique + !important pour battre la regle .timing. */
.seat-avatar.timing.has-pth-avatar > .seat-initial { display: none !important; }
.seat.active .seat-name,
.seat.active .seat-money { opacity: 0.35; transition: opacity 0.3s; }
/* Dealer chip : rendu via SVG chipSvg() dans renderSeats */
.dealer-chip {
  position: absolute; top:-8px; right:-8px;
  z-index: 3; pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.7));
  animation: chipPop 0.4s cubic-bezier(.17,.67,.35,1.45) both;
}
/* Badges SB / BB */
.blind-chip {
  position: absolute; top:-8px; left:-8px;
  z-index: 4; pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.6));
  animation: chipPop 0.4s cubic-bezier(.17,.67,.35,1.45) both;
}
/* Drapeau pays sur l'avatar (coin bas-droite, n'empiète pas sur SB/BB/Dealer
   qui sont en haut). Masqué si absent (non rendu). */
.seat-flag {
  position: absolute; bottom: -6px; right: -6px;
  z-index: 4; pointer-events: none;
  line-height: 0;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.8));
  animation: chipPop 0.4s cubic-bezier(.17,.67,.35,1.45) both;
}
.seat-flag .cc-flag { width: 18px; height: 13px; display: block; }
@keyframes chipPop {
  0%   { transform: scale(0) rotate(-40deg); opacity: 0; }
  65%  { transform: scale(1.25) rotate(8deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
.seat.folded .seat-avatar::before {
  content: '✕';
  position: absolute;
  font-size: var(--fs-xs);
  color: var(--neg);
  font-weight: 900;
  z-index: 3;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}
.seat.me .seat-avatar { border-color: var(--green); }

/* Eliminated / sitting-out seat: stays in place around the felt so the
   other players don't visually rotate between hands, but appears faded
   with a dim border and a small "OUT" badge. The slight grayscale also
   defuses any colour cue (turn highlight, dealer chip) that may linger
   from a previous hand. */
/* .seat-out reste cliquable : pointer-events:auto + cursor:pointer herites
   de .seat -> un tap ouvre la popup d'info du joueur elimine/absent, comme
   en jeu (le handler de clic ne saute que .seat-ghost).
   Estomper le contenu, pas la pastille : l'opacite d'un parent plafonne
   celle de ses enfants (::after compris) -> le badge resterait invisible.
   On grise avatar/nom/tapis/mise separement et on garde la pastille a
   pleine opacite, par-dessus, dans une couleur qui suit le theme. */
.seat.seat-out .seat-plate,
.seat.seat-out .seat-foot {
  opacity: 0.4;
  filter: grayscale(0.6);
}
.seat.seat-out::after {
  content: 'OUT';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) rotate(-10deg);
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #fff;
  background: var(--red);
  padding: 2px 7px;
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: 4px;
  box-shadow: 0 1px 5px rgba(0,0,0,0.45);
  z-index: 4;
  pointer-events: none;
}

.seat-name {
  font-size: var(--fs-xs); color: var(--text-hi);
  white-space: nowrap; text-overflow: ellipsis;
  max-width: 68px; overflow: hidden; text-align: center;
}
.seat-money {
  font-size: var(--fs-xs); color: var(--gold);
  font-family: var(--ff-mono);
}
.seat-bet {
  font-size: var(--fs-3xs);
  background: rgba(0,0,0,0.6); border: 1px solid var(--border);
  border-radius: 20px; padding: 1px 5px;
  color: var(--cream); white-space: nowrap;
}
.seat-action-label {
  font-size: var(--fs-3xs); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text);
}

/* ── Vignette d'action ovale posée sur la box (fidélité client officiel) ──
   Texte traduit (i18n), couleur par action : Fold rouge · Check/Call bleu ·
   Bet/Raise vert · All-in rouge sombre (palette Theme.qml, bible §7). */
.seat-action-badge {
  position: absolute;
  /* Posée sur les cartes (moitié droite de la rangée avatar+cartes), comme le
     client officiel — la rangée du haut est centrée dans .seat, on décale donc
     la vignette vers la droite pour la caler au-dessus des cartes. */
  top: -5px; left: calc(50% + 17px); transform: translateX(-50%);
  z-index: 7;
  white-space: nowrap;
  font-family: var(--ff-display);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em;
  padding: 2px 10px; border-radius: var(--r-pill);
  color: #fff;
  border: 1px solid rgba(0,0,0,0.35);
  box-shadow: 0 2px 6px rgba(0,0,0,0.45);
  pointer-events: none;
}
/* Couleurs = colonne « Badge » du Theme QML (actionBadgeColor : plus sombre que
   le Bottom des boutons), bord = Edge. Surchargeables par thème via var(). */
.seat-action-badge.act-c1 { background: var(--act-badge-fold, #5a1010);  border-color: var(--act-edge-fold, #e87070); } /* Fold */
.seat-action-badge.act-c2,
.seat-action-badge.act-c3 { background: var(--act-badge-call, #122a55);  border-color: var(--act-edge-call, #6aa0e8); } /* Check / Call */
.seat-action-badge.act-c4,
.seat-action-badge.act-c5 { background: var(--act-badge-raise, #123f0b); border-color: var(--act-edge-raise, #7ad06a); } /* Bet / Raise */
.seat-action-badge.act-c6 { background: var(--act-badge-allin, #3c0a0a); border-color: var(--act-edge-allin, #ef5350); } /* All-in */

@keyframes pulse-gold {
  0%,100% { box-shadow: 0 0 10px rgba(var(--gold-rgb), 0.5); }
  50%      { box-shadow: 0 0 22px rgba(var(--gold-rgb), 0.9); }
}

/* ═══ POKER CARDS ═══ */
.pk {
  width: 42px; height: 60px;
  border-radius: 4px;
  position: relative;
  background: #fff; color: #111;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  font-size: var(--fs-md); font-weight: 800;
  /* Ombre portée multi-couche pour effet 3D */
  box-shadow:
    0 1px 0 rgba(255,255,255,0.8) inset,
    0 -1px 0 rgba(0,0,0,0.1) inset,
    2px 4px 8px rgba(0,0,0,0.45),
    4px 8px 20px rgba(0,0,0,0.25),
    0 0 0 1px rgba(0,0,0,0.08);
  border: 1px solid rgba(0,0,0,0.15);
  line-height: 1.1; user-select: none; flex-shrink: 0;
}
/* ♥ cœur : rouge profond classique */
.pk.red { color: #c0392b; }
/* ♦ carreau : rouge plus orangé/vermillon pour le distinguer du ♥ (narmod)
   — les deux étant identiquement rouges, les confondre était facile. */
.pk.diamond { color: #e85a2c; }
/* Deck 4 couleurs (parite 2.1.2 nobus_4c_classic) : ♦ bleu, ♣ vert ;
   ♥ rouge et ♠ noir inchanges. Glyphes seulement (un deck d'images prime). */
/* Dos de carte « Medaillon + Treillis » (theme feutre/or) : SVG vectoriel
   net et scalable a toutes les tailles, rasterise une fois, zero cout runtime.
   Defini une seule fois dans --card-back, partage avec .fly-card. */
.pk.back {
  background: var(--card-back) center / 100% 100% no-repeat, #16301a;
  color: transparent; font-size: 0;
}
.pk.back::after { content: none; }
/* ── Slot vide des community cards : placeholder QML officiel (Bible §9) ──
   Rectangle noir 30 % + bord blanc 38 %, PAS de dos de carte ni d'ombre 3D.
   La carte n'apparaît que lors de la révélation (flip inchangé). */
.pk.comm-slot {
  background: rgba(0,0,0,0.30);
  border: 1px solid rgba(255,255,255,0.38);
  box-shadow: none;
  color: transparent; font-size: 0;
}
.pk.comm-slot::after { content: none; }

/* ── Jeu de cartes : deck SVG (axe "Cartes", data-deck="svg") ──
   Defaut = glyphes (.c-rank/.c-suit). Avec data-deck="svg", chaque face .pk
   affiche son SVG (chemin pose en variable inline --cf par cardToHtml/cardHtml)
   et les glyphes sont masques ; le dos (et les fly-cards de distribution)
   passent par --card-back surcharge ci-dessous. Switch 100% CSS, instantane,
   sans re-render. Assets : /cards/svg/*.svg (PokerTH, AGPL-3.0). */
:root[data-deck] .pk:not(.back):not(.comm-slot) {
  background-image: var(--cf, none);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center;
  background-color: transparent;
}
:root[data-deck] .pk:not(.back):not(.comm-slot) .c-rank,
:root[data-deck] .pk:not(.back):not(.comm-slot) .c-suit { display: none; }
/* Dos : --card-back est pose en inline sur <html> par le boot + _refreshDeck
   (deck-aware), pour .pk.back ET .fly-card, quel que soit le deck. */
.pk.sm { width: 32px; height: 46px; font-size: var(--fs-sm); font-weight: 700; }
.pk.md { width: 46px; height: 66px; font-size: var(--fs-lg); font-weight: 800; }
.pk.xsm { width: 20px; height: 29px; font-size: var(--fs-3xs); font-weight: 700; border-radius: var(--r-xs); }
.pk.lg { width: 58px; height: 84px; font-size: var(--fs-xl); font-weight: 900; }
/* Plus grosses lettres + plus gros symboles de couleur pour lisibilité (narmod).
   La 'couleur' (suit) prend ~1.3em au lieu de 0.9em, le rang ~1.35em au lieu de 1em.
   Avec `line-height:1` et flex-column, deux lignes de ~2.6em tiennent
   dans toutes les tailles de carte (xsm/sm/md/lg) sans débordement. */
/* Carte Classique : agencement standard facon PokerTH — index (rang+symbole)
   en haut-gauche et bas-droite (pivote), grand symbole au centre. */
.pk .c-rank { font-size: 1.35em; line-height: 1; }
.pk .c-suit { font-size: 1.3em; line-height: 1; margin-top: 1px; }
/* Petites cartes : on garde un seul index (coin haut-gauche) + le centre, pour rester lisible. */
/* ♠ pique : fond légèrement bleuté pour distinguer de ♣ trèfle (tous deux noirs) */
.pk.spade { background: linear-gradient(160deg, #f4f7ff 0%, #edf1fc 100%); }

/* ── Bottom zone: my cards + actions ── */
.my-zone {
  position: fixed;
  bottom: calc(56px + env(safe-area-inset-bottom)); /* above player-bar, clears gesture nav */
  left: 0; right: 0;
  z-index: 29;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  gap: var(--sp-3);
  /* Nécessaire pour que #hand-strength se positionne par rapport à this */
  overflow: visible;
}

.my-cards {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
}

.my-label {
  font-size: var(--fs-sm);
  color: var(--green);
  letter-spacing: 0.05em;
  font-weight: 600;
}
.my-stack {
  font-size: var(--fs-xs);
  color: var(--gold);
  margin-top: 2px;
}
.me-info {
  display: flex;
  flex-direction: column;
  margin-right: 8px;
}

/* Conteneur centre a la largeur de la barre (--bottom-w) : ancre le pin et
   l'oeil sur la barre, pas sur le bord de l'ecran (tablette/desktop). */
.action-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
  max-width: var(--bottom-w);
  display: flex;
  align-items: center;
  justify-content: center;
}
.action-bar {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  flex: 1;
}

.btn-action {
  padding: 8px 14px;
  border-radius: 8px;
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  cursor: pointer;
  border: none;
  transition: filter 0.12s, transform 0.08s;
  white-space: nowrap;
}
.btn-action:active { transform: scale(0.96); }
.btn-action:hover  { filter: brightness(1.15); }

.btn-fold  { background: var(--btn-fold-bg, #6b2020); color: var(--btn-fold-fg, #ffd0d0); }
.btn-check { background: var(--btn-check-bg, #1a5c1a); color: var(--btn-check-fg, #c0ffc0); }
.btn-call  { background: var(--btn-call-bg, #1a4a8a); color: var(--btn-call-fg, #c0d8ff); }
.btn-raise { background: var(--btn-raise-bg, var(--gold)); color: var(--btn-raise-fg, var(--on-gold)); }
/* Compact auto check/fold toggle, sits next to Call/Check. Discreet at
   rest; turns green when armed for the next turn. Icon-only on narrow. */
.btn-auto {
  flex: 0 0 auto;
  min-width: 46px;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  background: rgba(var(--gold-rgb), 0.08);
  color: var(--gold);
  border: 1px solid var(--border);
}
.btn-auto .auto-tx { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.06em; }
.btn-auto .auto-ic { width: 16px; height: 16px; display: block; flex: none; }
.btn-auto .auto-ic.ic-check { color: #5fd089; } /* will auto-check */
.btn-auto .auto-ic.ic-fold  { color: #e08a6f; } /* will auto-fold  */
.btn-auto:hover { background: rgba(var(--gold-rgb), 0.15); border-color: var(--gold-dim); }
.btn-auto.armed {
  background: rgba(var(--green-rgb), 0.22);
  border-color: var(--green);
  color: var(--on-green);
  box-shadow: 0 0 0 1px rgba(var(--green-rgb), 0.35), 0 0 12px rgba(var(--green-rgb), 0.25);
}
.btn-auto.armed .auto-ic { color: var(--on-green); } /* light glyph for contrast on green */
.action-top-row .btn-auto { flex: 0 0 auto; min-width: 46px; }
@media (max-width: 480px) { .btn-auto { min-width: 48px; } }

/* ── Panneau "aperçu des actions" (ouvert en tapant ses cartes) ── */
.pb-cards { cursor: pointer; }
/* Aperçu hors-tour : le MÊME panneau d'action que pendant notre tour, mais
   rendu non interactif — tout est neutralisé au clic SAUF le bouton AUTO,
   le seul réglage qu'on peut armer à l'avance. */
.actions-preview {
  position: relative;
  width: 100%;
  box-sizing: border-box;
  pointer-events: none;            /* coupe Fold / Call / % / relance / All-In */
  opacity: 0.96;
}
.actions-preview .btn-auto { pointer-events: auto; opacity: 1; }  /* AUTO reste activable */
/* Hors-tour (apercu) : touches d'action grisees (desaturees + attenuees) pour
   signaler qu'elles ne sont pas jouables. Le dropdown de mode reste intact.
   grayscale() porte sur les couleurs du theme en cours -> conforme a toutes
   les palettes (y compris boutons-images). */
/* Pré-sélection : les 4 boutons d'action restent CLIQUABLES et colorés en
   aperçu — on peut armer/désarmer une action avant son tour (client officiel).
   Un bouton désactivé (relance indisponible) reste grisé et inactif. */
.actions-preview .btn-action { pointer-events: auto; filter: saturate(0.5); opacity: 0.62; }
.actions-preview .btn-action:disabled { pointer-events: none; filter: grayscale(0.9); opacity: 0.4; }
.actions-preview .btn-action.prearmed { filter: none; opacity: 1; }  /* action pre-armee : pleine couleur */
/* Contrôles de montant : encore inactifs en aperçu (la pré-relance part au min). */
.actions-preview .btn-pct,
.actions-preview .raise-slider,
.actions-preview .raise-display {
  /* Hors-tour : couleurs conservees mais ternies (desaturees + attenuees),
     signal uniforme « pas ton tour » sans virer au gris. */
  filter: saturate(0.5);
  opacity: 0.62;
}
.actions-preview .mode-sel-wrap { pointer-events: auto; opacity: 1; }  /* mode dropdown reste activable en aperçu */

/* Action pré-armée : bord or + point or en haut à droite (bible §5.3). */
.btn-action.prearmed {
  position: relative;
  outline: 2px solid #FFD700;
  outline-offset: -2px;
  box-shadow: 0 0 0 1px #FFD700, 0 0 12px rgba(255,215,0,0.55);
}
.btn-action.prearmed::after {
  content: '';
  position: absolute;
  top: -4px; right: -4px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: #FFD700;
  box-shadow: 0 0 4px rgba(255,215,0,0.9);
}
/* Hidden by default; shown only when the user enables it from the ••• menu. */
/* All-In : bouton orange compact dans la ligne 1/3-1/2-Pot (layout officiel).
   Les themes a images de boutons (data-btn-img) repeignent via border-image. */
.btn-allin {
  background: var(--btn-allin-bg, linear-gradient(180deg, #e08a2e, #b5651d));
  color: var(--btn-allin-fg, #fff);
  border: 1px solid var(--btn-allin-bd, #f0a350); outline: none;
  padding: 8px 12px; font-size: var(--fs-xs); letter-spacing: 0.06em;
}
.btn-allin:hover { filter: brightness(1.08); }
.btn-allin b { color: var(--btn-allin-fg-b, #fff); }
/* Image-backed action buttons (9-slice SVG/PNG via the Buttons axis). */
:root[data-btn-img] .btn-action { border: 9px solid transparent; background: transparent; padding: 1px 9px !important; }
:root[data-btn-img] .btn-fold  { border-image: var(--btn-fold-img) 9 fill / 9px / 0 stretch; color: var(--btn-fold-fg, #fff); }
:root[data-btn-img] .btn-check { border-image: var(--btn-check-img) 9 fill / 9px / 0 stretch; color: var(--btn-check-fg, #fff); }
:root[data-btn-img] .btn-call  { border-image: var(--btn-call-img) 9 fill / 9px / 0 stretch; color: var(--btn-call-fg, #fff); }
:root[data-btn-img] .btn-raise { border-image: var(--btn-raise-img) 9 fill / 9px / 0 stretch; color: var(--btn-raise-fg, #fff); }
:root[data-btn-img] .btn-allin { border-image: var(--btn-allin-img) 9 fill / 9px / 0 stretch; color: var(--btn-allin-fg, #fff); }
:root[data-btn-img] .btn-allin b { color: var(--btn-allin-fg-b, #fff); }


.raise-input {
  background: var(--field-bg);
  border: 1px solid var(--border-hi);
  border-radius: 2px;
  color: var(--cream);
  padding: 7px 8px;
  font-family: var(--ff-mono);
  font-size: var(--fs-base);
  width: 72px;
  outline: none;
}
.raise-input:focus { border-color: var(--gold); }

/* ══ PANNEAUX FLOTTANTS (chat + réactions) — hors du flux flex ══
   position:fixed → la zone de table garde toujours toute sa hauteur */
#g-chat-panel {
  position: fixed !important;
  top: var(--ovl-top, 48px);           /* juste sous le header */
  left: 0; right: 0;
  z-index: 100;
  max-height: min(280px, 38dvh) !important;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 20px rgba(0,0,0,0.6);
}
#g-reaction-panel {
  position: fixed !important;
  top: var(--ovl-top, 48px);
  left: 0; right: 0;
  z-index: 100;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 20px rgba(0,0,0,0.6);
}
/* Log panel — same visual treatment as #g-chat-panel so the two
   feel like siblings (the user opens them with adjacent header
   buttons). Only difference is z-index 99 vs 100, keeping the chat
   one tick above when both are open. */
#g-log-panel {
  position: fixed !important;
  top: var(--ovl-top, 48px);
  left: 0; right: 0;
  z-index: 100;
  max-height: min(140px, 22dvh) !important;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 20px rgba(0,0,0,0.6);
  display: flex; /* makes flex-direction:column from inline style effective */
  flex-direction: column;
}
/* Log body — scrollable like .chat-msgs (this is the class on #g-log-body).
   min-height:0 is required so the flex child can shrink and scroll instead
   of overflowing the clamped panel — that absence was why the journal never
   scrolled before. */
.log-panel-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 12px;
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--cream);
}
.log-panel-body::-webkit-scrollbar { width: 6px; }
.log-panel-body::-webkit-scrollbar-track { background: transparent; }
.log-panel-body::-webkit-scrollbar-thumb { background: rgba(var(--gold-rgb), 0.18); border-radius: var(--r-xs); }
.log-panel-body::-webkit-scrollbar-thumb:hover { background: rgba(var(--gold-rgb), 0.32); }
/* Log message rows — mirror the .chat-msgs basic look without the
   bubble-style backgrounds (log lines are denser, more like a
   monospace journal). */
.log-msgs {
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--chatlog-text, var(--cream));
}
.log-msgs > div {
  padding: 1px 0;
  border-bottom: 1px solid var(--inset);
}
.log-msgs > div:last-child { border-bottom: none; }
/* Custom scrollbar matching the chat panel */
.log-msgs::-webkit-scrollbar { width: 6px; }
.log-msgs::-webkit-scrollbar-track { background: transparent; }
.log-msgs::-webkit-scrollbar-thumb {
  background: rgba(var(--gold-rgb), 0.18);
  border-radius: var(--r-xs);
}
.log-msgs::-webkit-scrollbar-thumb:hover { background: rgba(var(--gold-rgb), 0.32); }

.g-chat-panel-header { display:flex; align-items:center; justify-content:space-between; padding:4px 10px; background:var(--chrome-tint); border-bottom:1px solid var(--border); flex-shrink:0; }
/* Poignée de redimensionnement du chat (bord bas) — glissable au doigt */
.chat-resize-handle {
  flex-shrink: 0; height: 18px;
  display: flex; align-items: center; justify-content: center;
  cursor: ns-resize; touch-action: none;
  -webkit-user-select: none; user-select: none;
  background: var(--chrome-tint); border-top: 1px solid var(--border);
}
.chat-resize-handle .crh-grip {
  width: 42px; height: 4px; border-radius: var(--r-xs);
  background: var(--gold-dim); transition: background .15s, width .15s;
}
.chat-resize-handle:hover .crh-grip,
.chat-resize-handle.dragging .crh-grip { background: var(--gold-hi); width: 54px; }
.gchat-input { display:flex; gap:5px; padding:5px 10px; background:var(--panel); border-bottom:1px solid var(--border); flex-shrink:0; }
.gchat-input input { flex:1; background:var(--field-bg); border:1px solid var(--border); border-radius:2px; color:var(--cream); padding:5px 8px; font-family: var(--ff-mono); font-size:var(--fs-sm); outline:none; }
.gchat-input input:focus { border-color:var(--gold); }
.gchat-input button { background:rgba(var(--gold-rgb), 0.12); border:1px solid var(--gold-dim); color:var(--gold); padding:5px 10px; border-radius:2px; cursor:pointer; font-size:var(--fs-sm); }

.waiting-msg {
  color: var(--text); font-size: var(--fs-sm);
  font-style: italic; padding: 4px 0;
}
/* ══ PASSWORD PROMPT ══ */
#password-prompt {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.75);
}
.pp-card {
  background: var(--modal-bg); border: 1px solid var(--gold-dim);
  border-top: 3px solid var(--gold); border-radius: 8px;
  padding: 20px 24px; width: min(340px, 92vw);
  display: flex; flex-direction: column; gap: var(--sp-5);
  box-shadow: 0 0 60px rgba(0,0,0,0.8);
}
.pp-title { font-family: var(--ff-display); font-size: var(--fs-md); color: var(--text-hi); letter-spacing: 0.1em; }
.pp-label { font-size: var(--fs-2xs); color: var(--gold-dim); letter-spacing: 0.15em; text-transform: uppercase; margin-bottom: 4px; }
.pp-input { background: var(--field-bg); border: 1px solid var(--border); border-radius: 2px; color: var(--cream); padding: 9px 11px; font-family: var(--ff-mono); font-size: var(--fs-md); outline: none; width: 100%; }
.pp-input:focus { border-color: var(--gold); }
.pp-btns { display: flex; gap: var(--sp-3); }
.pp-btns .btn-primary { flex: 1; padding: 9px; font-size: var(--fs-sm); }
.pp-cancel { flex: 0 0 auto; background: transparent; border: 1px solid var(--border); color: var(--text); padding: 9px 16px; border-radius: 2px; cursor: pointer; font-family: var(--ff-mono); font-size: var(--fs-sm); }
.pp-cancel:hover { border-color: var(--border-hi); color: var(--text-hi); }

/* ══ INSTALL POPUP (PWA add-to-home-screen instructions) ══ */
#install-popup {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.75);
  padding: var(--sp-5);
}
.ip-card {
  background: var(--modal-bg); border: 1px solid var(--gold-dim);
  border-top: 3px solid var(--gold); border-radius: 8px;
  padding: 20px 24px; width: min(360px, 92vw);
  display: flex; flex-direction: column; gap: 14px;
  box-shadow: 0 0 60px rgba(0,0,0,0.8);
}
.ip-title { font-family: var(--ff-display); font-size: var(--fs-md); color: var(--text-hi); letter-spacing: 0.08em; text-align: center; }
.ip-body { font-size: var(--fs-base); color: var(--cream); line-height: 1.55; }
.ip-step { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 10px; }
.ip-step:last-child { margin-bottom: 0; }
.ip-step .ip-ico { flex: 0 0 auto; min-width: 18px; color: var(--gold-dim); font-weight: 700; }
.ip-step b { color: var(--gold); font-weight: 600; }
.ip-btns { display: flex; justify-content: center; }
.ip-btns .pp-cancel { padding: 9px 30px; }

/* ══ WINNER OVERLAY ══ */
.winner-overlay {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  /* PAS de voile noir (demande narmod) : la table reste visible derriere,
     seuls la carte et son ombre apparaissent. pointer-events:none sur le
     conteneur -> la table reste cliquable autour ; la carte re-active ses
     propres clics. */
  background: transparent;
  pointer-events: none;
  padding: var(--sp-5);
  animation: fadeIn 0.25s ease;
}
.winner-overlay .winner-card { pointer-events: auto; }
@keyframes fadeIn { from { opacity:0 } to { opacity:1 } }
.winner-card {
  background: var(--modal-bg);
  border: 1px solid var(--gold-dim); border-top: 3px solid var(--gold);
  border-radius: var(--r-bar); padding: 18px 22px;
  max-width: min(440px, 94vw); width: 100%;
  /* Flex column so the players list can be the ONLY scrollable part,
     keeping the header / common cards / Continue button always visible
     even with a full 10-player results list. Previously the whole card
     was a single overflow:auto block, so with 10 players the Continue
     button fell below the fold and was unreachable on small phones. */
  display: flex; flex-direction: column;
  max-height: 88dvh; overflow: hidden;
  box-shadow: 0 0 80px rgba(var(--gold-rgb), 0.2), 0 24px 60px rgba(0,0,0,0.8);
  animation: popIn 0.3s cubic-bezier(0.175,0.885,0.32,1.275);
}
@keyframes popIn { from { transform:scale(0.75); opacity:0 } to { transform:scale(1); opacity:1 } }
.wc-header { display:flex; align-items:center; gap:var(--sp-4); padding-bottom:12px; border-bottom:1px solid var(--border); margin-bottom:12px; }
.wc-trophy { font-size:2rem; line-height:1; }
.wc-titles { flex:1; }
.wc-label { font-family: var(--ff-display); font-size:var(--fs-2xs); letter-spacing:0.22em; text-transform:uppercase; color:var(--gold-dim); }
.wc-name { font-family: var(--ff-display); font-size:clamp(1rem,4vw,1.4rem); font-weight:700; color:var(--gold); }
.wc-gain { font-size:clamp(0.9rem,3.5vw,1.15rem); color:var(--pos); font-weight:700; text-align:right; }
.wc-stats { display:flex; gap:var(--sp-2); margin-bottom:12px; flex-wrap:wrap; }
.wc-stat { flex:1; min-width:65px; background:var(--inset); border:1px solid var(--border); border-radius:4px; padding:6px 8px; text-align:center; }
.wc-stat-label { font-size:var(--fs-3xs); color:var(--gold-dim); letter-spacing:0.1em; text-transform:uppercase; margin-bottom:2px; }
.wc-stat-value { font-size:var(--fs-base); color:var(--cream); font-weight:700; }
.wc-section { font-size:var(--fs-3xs); letter-spacing:0.18em; text-transform:uppercase; color:var(--gold-dim); margin-bottom:5px; }
.wc-cards-row { display:flex; gap:var(--sp-1); margin-bottom:12px; flex-wrap:wrap; }
.wc-players {
  margin-bottom:14px;
  /* Only this region scrolls; flex:1 lets it take the remaining space,
     min-height:0 allows it to shrink below its content height so the
     overflow actually kicks in inside the flex column. */
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  /* a touch of right padding so the scrollbar doesn't overlap deltas */
  padding-right: 2px;
}
/* Grid (et non flex) : colonnes figées => les cartes de chaque joueur
   restent alignées verticalement quel que soit le montant du delta.
   Col1 avatar | Col2 info (élastique) | Col3 cartes (largeur constante)
   | Col4 delta (largeur FIXE, ne pousse plus les cartes). */
.wc-player-row { display:grid; grid-template-columns:24px minmax(0,1fr) auto 90px; align-items:center; gap:7px; padding:5px 7px; border-radius:4px; margin-bottom:3px; background:var(--inset); }
.wc-player-row.wc-winner { background:rgba(var(--gold-rgb), 0.08); border:1px solid rgba(var(--gold-rgb), 0.2); }
.wc-player-row.wc-me-row { border-left:3px solid var(--green); }
.wc-player-av { width:24px; height:24px; border-radius:50%; background:rgba(0,0,0,0.5); border:1px solid var(--border); display:flex; align-items:center; justify-content:center; font-size:var(--fs-2xs); color:var(--text-hi); flex-shrink:0; }
.wc-player-info { min-width:0; }
.wc-player-name { font-size:var(--fs-xs); color:var(--text-hi); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.wc-player-stack { font-size:var(--fs-3xs); color:var(--text); }
.wc-player-cards { display:flex; gap:var(--sp-0); justify-content:flex-end; }
.wc-player-cards .pk.placeholder { opacity:0.22; }
.wc-player-delta { font-size:var(--fs-sm); font-weight:700; text-align:right; white-space:nowrap; }
.wc-player-delta.pos { color:var(--pos); }
.wc-player-delta.neg { color:var(--neg); }
/* Bouton au style bouton QML (bible §5.5 + §12.3, action primaire verte) :
   degrade Top->Bottom, bord Edge, radius 9, bold ls 0.5, press scale 0.96. */
/* « Continuer » : mêmes couleurs que le bouton Connexion de la page de login
   (.btn-primary : ardoise #2b3444, texte blanc, radius 2, ombre douce). */
.winner-dismiss { background:#2b3444; color:#ffffff; border:none; padding:12px 24px; font-family: var(--ff-display); font-size:var(--fs-base); font-weight:700; border-radius:2px; cursor:pointer; letter-spacing:0.15em; box-shadow:0 4px 16px rgba(0,0,0,0.28); transition:background 0.15s, transform 0.1s, box-shadow 0.15s; display:block; width:100%; margin-top:4px; flex:0 0 auto; }
.winner-dismiss:hover { background:#384252; box-shadow:0 6px 24px rgba(0,0,0,0.4); }
.winner-dismiss:active { transform:scale(0.98); }


/* ── Player bar + my-zone : cachées hors jeu (contrôlées par body.in-game) ── */
body:not(.in-game) .player-bar,
body:not(.in-game) .my-zone {
  display: none !important;
}

/* ── Player bar (me) ── */
.player-bar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 30;
  display: flex;
  justify-content: center;
  padding: 3px 6px;
  padding-bottom: max(3px, env(safe-area-inset-bottom));
  background: var(--panel);
  border-top: 1px solid rgba(var(--green-rgb), 0.3);
}
.player-bar-left {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  max-width: var(--bottom-w);
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(var(--green-rgb), 0.4);
  border-radius: 8px;
  padding: 5px 14px;
}
.pb-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(0,0,0,0.5);
  border: 2px solid var(--green);
  box-shadow: 0 0 8px rgba(var(--green-rgb), 0.5);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--ff-display);
  font-size: var(--fs-md); color: var(--text-hi);
  flex-shrink: 0;
}
.pb-info { display: flex; flex-direction: column; gap: var(--sp-0); min-width: 80px; }
.pb-name { font-size: var(--fs-sm); color: var(--green); font-weight: 700; }
.pb-money { font-size: var(--fs-xs); color: var(--gold); }
.pb-cards {
  display: flex;
  flex-direction: row;
  gap: 5px;
  align-items: center;
}
/* Override pk size specifically in player bar */
.pb-cards .pk { width: 42px; height: 60px; font-size: var(--fs-md); font-weight: 800; }
.pb-action {
  font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text);
  min-width: 50px;
}
.player-bar.pb-active .player-bar-left {
  border-color: var(--gold);
  box-shadow: 0 0 12px rgba(var(--gold-rgb), 0.4);
  animation: pulse-gold 1.5s infinite;
}

/* Action grid */
/* Largeur partagee du bas d'ecran : le dock (.player-bar-left) et les
   boutons d'action (.action-grid) gardent exactement la meme largeur.
   Un seul chiffre a changer pour bouger les deux. */
:root { --bottom-w: 560px; }
.action-grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  width: 100%;
  max-width: var(--bottom-w);
  margin: 0 auto;
  box-sizing: border-box; /* inclut padding+border : evite le debordement pleine largeur mobile */
}
/* ── Barre d'action : panneau centré borné (fidélité client officiel) ──
   Sur desktop/tablette, le fond épouse la largeur des boutons (radius,
   comme le QML officiel, bible §5) au lieu de s'étirer sur toute la largeur
   de l'écran. Actif aussi sur tout desktop/souris (hover+pointer:fine),
   fenêtre étroite comprise. Les téléphones tactiles (pointer:coarse) gardent
   la bande pleine largeur collée au bas. */
@media (min-width: 900px) and (min-height: 600px), (hover: hover) and (pointer: fine) {
  .my-zone { background: transparent; border-top: none; }
  .my-zone .action-grid {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: 8px 10px;
    box-shadow: 0 6px 20px rgba(0,0,0,0.38);
  }
  /* Tour actif : le halo doré est porté par le panneau BORNÉ, pas par une
     bande dorée pleine largeur sur .my-zone. */
  .my-zone.my-turn-active { animation: none; border-top: none; }
  .my-zone.my-turn-active .action-grid {
    border-color: var(--gold);
    animation: myTurnPanelGlow 1.5s ease-in-out infinite;
  }
}
@keyframes myTurnPanelGlow {
  0%,100% { box-shadow: 0 6px 20px rgba(0,0,0,0.38), 0 0 0 1px var(--gold), 0 0 18px rgba(var(--gold-rgb), 0.35); }
  50%     { box-shadow: 0 6px 20px rgba(0,0,0,0.38), 0 0 0 1px #ffe066,     0 0 30px rgba(var(--gold-rgb), 0.6); }
}
/* ── Mon tour : halo doré NET sur le panneau d'action (TOUTES tailles) ──
   L'ancien halo fort (myTurnPanelGlow) etait verrouille derriere
   @media(min-width:900px) ; sur telephone/paysage court, le seul signal
   etait la pulsation de la bordure-haut de .my-zone sur 1px -> quasi
   invisible. Ici : cadre or pulse + petit "pop" a chaque nouveau tour,
   partout. .action-grid est recree a chaque tour -> le pop se rejoue seul.
   Fidelite QML §4.3 : « cadre or pulse (turn glow) quand c'est mon tour ». */
.my-zone.my-turn-active .action-grid {
  border-radius: var(--r-lg);
  animation: actBarTurnPop 0.55s cubic-bezier(.2,.9,.3,1.15) both,
             actBarTurnPulse 1.4s ease-in-out 0.5s infinite;
}
@keyframes actBarTurnPop {
  0%   { box-shadow: 0 0 0 0 rgba(var(--gold-rgb), 0);            transform: scale(1); }
  35%  { box-shadow: 0 0 0 2px var(--gold), 0 0 36px 8px rgba(var(--gold-rgb), 0.9);  transform: scale(1.03); }
  100% { box-shadow: 0 0 0 2px var(--gold), 0 0 18px 2px rgba(var(--gold-rgb), 0.45); transform: scale(1); }
}
@keyframes actBarTurnPulse {
  0%,100% { box-shadow: 0 0 0 2px var(--gold), 0 0 16px 2px rgba(var(--gold-rgb), 0.42); }
  50%     { box-shadow: 0 0 0 2px #ffe066,     0 0 32px 7px rgba(var(--gold-rgb), 0.74); }
}
/* Layout officiel : 3 zones (montant+slider / pastilles+All-In+mode / Fold-Call-Raise) */
/* Bas : Fold | Call/Check | Raise — trois boutons egaux */
.act-buttons-row { display: flex; gap: var(--sp-2); }
/* Echelle CONTINUE de la barre d'action avec la fenetre (--bar-k, posee par
   updateBottomLayout : 1 a partir de 1400x860, plancher 0.78) — la barre se
   redimensionne au fil du resize Safari/Chrome comme le client QML. Les
   blocs mobiles (portrait/paysage) surchargent avec leurs valeurs QML
   fixes et ne sont pas affectes. */
.act-buttons-row .btn-action { flex: 1; min-width: 0; padding: calc(10px * var(--bar-k, 1)) calc(12px * var(--bar-k, 1)); min-height: calc(54px * var(--bar-k, 1) - 10px); border-radius: var(--act-btn-radius, 9px); font-size: calc(0.9rem * var(--bar-kf, 1)); }
/* Haut : champ montant editable + slider */
.bet-row { display: flex; gap: var(--sp-3); align-items: center; }
.bet-row .raise-slider { flex: 1; }
.raise-amt-field {
  flex: 0 0 auto; width: 78px; /* largeur QML fixe, conservee aussi en paysage -> continuite */
  background: var(--field-bg);
  border: 2px solid var(--btn-raise-bg, #4CAF50);
  border-radius: 7px;
  color: var(--btn-raise-bg, #4CAF50);
  padding: calc(8px * var(--bar-k, 1)) calc(6px * var(--bar-k, 1)); font-family: var(--ff-mono); font-size: calc(0.81rem * var(--bar-kf, 1));
  font-weight: 700; text-align: center; outline: none;
}
.raise-amt-field:focus { border-color: var(--gold); }
.raise-amt-field:disabled { opacity: 0.3; cursor: not-allowed; filter: grayscale(0.6); }
/* Milieu : 1/3 1/2 Pot | All-In | mode */
/* Parité GameActionBar.panelWidth (QML) : en paysage le panneau d'action est
   CENTRÉ, large de max(largeur visuelle des cartes communes, 380 px) — posé
   par renderSeats dans --abar-w. Portrait / hors placement officiel : la
   variable est absente -> pleine largeur (comportement historique). */
/* !important : les blocs média portrait/paysage plus bas posent max-width:100%
   et gagneraient la cascade ; --abar-w n'est posée QUE quand la règle QML
   s'applique (paysage officiel), sinon repli none = aucun effet. */
/* margins auto en !important : (1) #g-actions est un flex justify-content:
   flex-end -> sans auto-margins la grille clampée partait à droite ;
   (2) le bloc média fs+hide-pbar portrait pose margin:0. Les auto-margins
   ne décalent rien quand max-width vaut none (grille pleine largeur). */
.my-zone .action-grid { max-width: var(--abar-w, none) !important; margin-left: auto !important; margin-right: auto !important; }
/* ── Zone PORTRAIT (placement officiel, data-abar posé par renderSeats) :
   budget vertical de GameActionBar QML — raiseSection topPadding 4 /
   leftPadding-rightPadding 8 / bottomPadding 2, spacing 3 ; rangée de
   boutons : marges internes 5 (haut, via gap+2) et 6 (bas). L'enrobage web
   (my-zone 5px, panneau 8/10, gaps 6) coûtait ~25 px de tableZone → cartes
   plus petites que le client officiel à fenêtre égale. ── */
html[data-abar="portrait"] .my-zone { padding-top: 0 !important; padding-bottom: 0 !important; }
html[data-abar="portrait"] .my-zone .action-grid { padding: 4px 8px 2px !important; gap: 3px !important; }
html[data-abar="portrait"] .my-zone .act-buttons-row { margin-top: 2px; margin-bottom: 6px; gap: var(--sp-3); }
.mid-row { display: flex; gap: var(--sp-2); align-items: stretch; }
/* Parite QML GameActionBar : quick-bets a taille fixe, All-In colle juste
   apres Pot, seul le dropdown de mode est pousse a droite (margin-left auto).
   Avant, pct-row s'etirait (flex 1 1 auto) et poussait Tapis contre le
   dropdown dans les fenetres 740-900 px. */
.mid-row .pct-row { flex: 0 0 auto; width: auto; }
.mid-row .btn-allin { flex: 0 0 auto; min-width: 0; white-space: nowrap; }
.mode-sel-wrap { flex: 0 0 auto; }
.mid-row .mode-sel-wrap { flex: 0 1 calc(132px * var(--bar-kf, 1)); margin-left: auto; }
/* First two buttons side by side */
.action-top-row {
  display: flex; gap: var(--sp-2);
}
.action-top-row .btn-action:not(.btn-auto) { flex: 1; }

.pct-row {
  display: flex; gap: 5px;
}
.btn-pct {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  background: rgba(var(--gold-rgb), 0.1); border: 1px solid var(--gold-dim);
  color: var(--gold); padding: calc(7px * var(--bar-k, 1)) calc(4px * var(--bar-k, 1)); min-height: calc(6.5px + 31.5px * var(--bar-k, 1)); /* 38px a k=1, 24px pile a la frontiere paysage (k=0.556) */ border-radius: 7px; cursor: pointer;
  font-family: var(--ff-mono); text-align: center;
}
.btn-pct .pct-p { font-size: calc(0.74rem * var(--bar-kf, 1)); font-weight: 700; color: var(--gold); }
.btn-pct .pct-amt { font-size: calc(0.6rem * var(--bar-kf, 1)); font-weight: 400; color: var(--text); }
.btn-pct:hover { background: rgba(var(--gold-rgb), 0.22); }
/* Bets rapides : vert QML sur TOUTES les tables (GameActionBar 2.1.3 les code
   EN DUR — #1b5e20 / bord #4CAF50 / hover #388e3c / press #2e7d32 — ils ne
   sont PAS themables via StyleProvider : meme un tapis importe les affiche
   verts dans le client officiel). L'ancienne restriction aux tapis maison
   faisait diverger le web des tables importees (retour narmod 15/07). */
.btn-pct { background: #1b5e20; border-color: #4CAF50; color: #fff; }
.btn-pct .pct-p { color: #fff; }
.btn-pct:hover { background: #388e3c; }
.btn-pct:active { background: #2e7d32; }
.btn-pct:disabled,
.btn-action:disabled {
  opacity: 0.28;
  cursor: not-allowed;
  filter: grayscale(0.7);
  pointer-events: none;
}
.raise-input:disabled {
  opacity: 0.3;
  cursor: not-allowed;
  background: var(--field-bg) !important;
}
.raise-row { display: flex; gap: 5px; align-items: stretch; }
.raise-row .raise-input { flex: 1; }
.raise-row .btn-raise { flex: 2; }
/* Sélecteur de mode (remplace l'ancien bouton AUTO dans la rangée d'action) */
.mode-sel-wrap select { font-size: var(--fs-sm); padding: 6px 22px 6px 8px; height: 100%; }
/* Mode auto actif (Auto Check/Call ou Auto Check/Fold) : le dropdown est
   encadré d'or — même or de pré-sélection que le QML (#FFD700). Remplace
   l'ancien toast « Auto checked/called » (demande narmod 2026-07-18). */
.mode-sel-wrap.mode-auto select {
  border-color: #FFD700 !important;
  box-shadow: 0 0 0 1px #FFD700, 0 0 10px rgba(255, 215, 0, 0.45);
}
.mode-sel-wrap .sel-arr { right: 7px; font-size: var(--fs-xs); }

/* Action log */
.game-log {
  position: fixed;
  bottom: 160px; left: 8px;
  width: 190px; max-height: 130px;
  overflow-y: auto;
  background: rgba(0,0,0,0.6);
  border-radius: 4px; padding: 5px 7px;
  font-size: var(--fs-2xs); color: var(--text);
  pointer-events: none;
  z-index: 5;
  border: 1px solid var(--inset);
}
.log-line { padding: 1px 0; border-bottom: 1px solid var(--inset); }
.g-chat-input { display:flex; gap:var(--sp-2); padding:5px 10px; background:var(--panel); border-bottom:1px solid var(--border); }
.g-chat-input input { flex:1; background:var(--field-bg); border:1px solid var(--border); border-radius:2px; color:var(--cream); padding:4px 7px; font-family: var(--ff-mono); font-size:var(--fs-sm); outline:none; }
.g-chat-input input:focus { border-color:var(--gold); }

/* Badge timer sous le cercle avatar */
.seat-timer-badge {
  font-size: var(--fs-xs);
  font-family: var(--ff-mono);
  font-weight: 900;
  color: var(--timer-normal, #ffe234);
  letter-spacing: 0.05em;
  line-height: 1;
  min-width: 26px;
  text-align: center;
  /* Compteur de timeout AU-DESSUS de l'avatar (order:-1 dans la colonne flex
     .seat) plutôt que dessous. Petite marge basse = écart vers l'avatar. */
  order: -1;
  margin-top: 0;
  margin-bottom: 4px;
  padding: 1px 5px;
  background: var(--timer-bg, rgba(0,0,0,0.62));
  border-radius: var(--r-xs);
  border: 1px solid rgba(var(--gold-rgb), 0.35);
  text-shadow: var(--timer-glow, 0 1px 2px rgba(0,0,0,0.9));
  box-shadow: 0 1px 5px rgba(0,0,0,0.55);
}

/* ══ Slider de mise mobile (design A : conteneur + bulle de valeur) ══ */
.raise-row-mobile {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  background: rgba(0,0,0,0.3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 6px 8px;
}
.raise-slider {
  flex: 1;
  accent-color: var(--gold, rgb(var(--gold-rgb)));
  height: 4px;
  cursor: pointer;
  min-width: 0;
}
/* Slider vert QML (#4CAF50) sur les tapis maison PokerTH + Spectator, comme les
   bets rapides ; les tapis a theme importe gardent l'accent dore. */
html:not([data-table]) .raise-slider,
html[data-table=""] .raise-slider,
html[data-table="pokerth-live"] .raise-slider { accent-color: #4CAF50; }
.raise-display {
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  color: var(--on-gold);
  font-weight: 700;
  min-width: 52px;
  text-align: center;
  flex-shrink: 0;
  background: var(--gold, rgb(var(--gold-rgb)));
  border-radius: 14px;
  padding: 3px 11px;
}
.raise-row-mobile .btn-raise { flex: 0 0 auto; padding: 10px 20px; }

/* Case « Ne plus afficher cette fenêtre » de l'overlay winner : discrète,
   centrée au-dessus du bouton Continuer ; pilote l'option avancée
   winner_popup (même clé que la case des Options avancées). */
.wc-hide-opt {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: 6px 0 2px;
  font-size: var(--fs-xs); color: var(--gold-dim);
  cursor: pointer; user-select: none;
}
.wc-hide-opt input { accent-color: var(--gold, rgb(var(--gold-rgb))); cursor: pointer; }
.wc-hide-opt:hover { color: var(--gold); }

/* ══ Combinaison gagnante dans l'overlay winner ═════════════ */
.wc-best-hand {
  text-align: center;
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--gold, rgb(var(--gold-rgb)));
  background: rgba(var(--gold-rgb), 0.1);
  border: 1px solid rgba(var(--gold-rgb), 0.3);
  border-radius: var(--r-sm);
  padding: 8px 14px;
  margin: 8px 0 4px;
  letter-spacing: 0.04em;
}


/* ══ WAITING PANEL ══
   Rich waiting-room display shown between JoinGameAck and
   GameStartInitial. Lives inside the same #g-actions container that
   normally hosts the action buttons; replaces the previous plain
   .waiting-msg italic string. */
.waiting-panel {
  display: flex; flex-direction: column; align-items: center;
  gap: 7px; padding: 10px 14px; max-width: 480px; margin: 0 auto;
}
.wp-title {
  font-family: var(--ff-display); font-size: var(--fs-md); letter-spacing: 0.1em;
  color: var(--text-hi); text-transform: uppercase;
}
.wp-count {
  font-size: var(--fs-base); color: var(--cream);
}
.wp-count b { color: var(--gold); font-weight: 700; }
.wp-bar {
  display: flex; gap: var(--sp-2); margin: 2px 0;
}
.wp-dot {
  width: 10px; height: 10px; border-radius: 50%;
  border: 1px solid var(--gold-dim);
}
.wp-dot-on  { background: var(--gold); box-shadow: 0 0 6px rgba(var(--gold-rgb), 0.7); }
.wp-dot-off { background: transparent; }
.wp-ok, .wp-need {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0.04em;
  padding: 2px 0;
}
.wp-ok   { color: rgb(var(--green2-rgb)); }
.wp-need { color: var(--wp-need-fg); }
.wp-list {
  list-style: none; margin: 4px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 10px;
  width: 100%;
}
.wp-player {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 3px 10px 3px 4px;
  font-size: var(--fs-sm);
}
.wp-av {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--inset);
}
.wp-av.emoji-av { font-size: var(--fs-lg); line-height: 1; }
.wp-av-letter   { font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }

/* ── Unified avatar-chip rules for compact UI lists ──
   The _avatarChipHtml helper produces <span class="<chipClass>
   has-pth-avatar"><img class="chip-pth-img" src="..."></span> when a
   PokerTH image is available. We need a single CSS rule that handles
   the image regardless of which chipClass (wp-av, eg-winner-av,
   wc-player-av) wraps it. Trick: target the image directly via its
   own class, and rely on the fact that <img> is a replaced element
   so border-radius alone clips its content -- no overflow:hidden on
   the parent needed (which would clip any sibling badge). */
.chip-pth-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
  pointer-events: none;
}
/* Drop the background tint when the chip hosts an image; the image
   already fills the circle, the tint would only show through if the
   image were transparent (the PokerTH logo placeholder has a tiny
   transparent margin -- a darker tint reads better than white). */
.wp-av.has-pth-avatar,
.eg-winner-av.has-pth-avatar,
.wc-player-av.has-pth-avatar {
  background: rgba(0,0,0,0.2);
  padding: 0;
  overflow: visible;  /* badges (none currently here, but future-proof) */
}
.wp-name  { color: var(--cream); }
.wp-me    {
  font-size: var(--fs-2xs); color: var(--gold);
  text-transform: uppercase; letter-spacing: 0.1em;
  background: rgba(var(--gold-rgb), 0.12); padding: 1px 5px; border-radius: var(--r-xs);
}
.wp-hint {
  font-size: var(--fs-xs); color: var(--gold-dim);
  font-style: italic; margin-top: 4px; text-align: center;
}
.wp-hint-admin { color: rgb(var(--green2-rgb)); font-style: normal; font-weight: 600; }

/* ── Wait-page (parité GameWaitPage QML) : recouvre le feutre avant le début.
   Remplie par renderWaitingPanel() dans #g-wait-page, masquée à
   GameStartInitial. Options différenciées admin (case bots + Démarrer +
   Quitter) / joueur simple (Quitter seul). ── */
.wait-page {
  position: absolute; inset: 0; z-index: 40;
  display: flex; flex-direction: column; align-items: center;
  gap: var(--sp-5); overflow-y: auto;
  padding: 20px 14px calc(20px + env(safe-area-inset-bottom, 0px));
  background: var(--field-bg);
}
.wait-page .wp-card {
  width: 100%; max-width: 440px;
  display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-4);
}
.wait-page .wp-title {
  text-align: center; font-size: var(--fs-md); font-weight: 700;
  color: var(--text-hi); letter-spacing: 0.02em; margin: 0;
}
.wp-info {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 3px;
}
.wp-info-name { font-weight: 700; color: var(--cream); font-size: var(--fs-md); margin-bottom: 3px; }
.wp-info-row { font-size: var(--fs-sm); color: var(--gold-dim); }
.wp-info-row b { color: var(--gold); font-weight: 700; }
.wp-players-hdr {
  font-size: var(--fs-xs); color: var(--gold-dim); text-transform: uppercase;
  letter-spacing: 0.12em; text-align: center; margin-top: 2px;
}
.wp-fillbots {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  font-size: var(--fs-base); color: var(--text); padding: 6px 2px; user-select: none;
}
.wp-fillbots input { width: 16px; height: 16px; accent-color: var(--green); cursor: pointer; flex: 0 0 auto; }
.wp-actions { display: flex; gap: var(--sp-3); margin-top: 4px; }
.wp-actions .wp-btn {
  flex: 1; padding: 12px 10px; border-radius: var(--r-md);
  font-weight: 700; letter-spacing: 0.4px; font-size: var(--fs-base);
  cursor: pointer; border: 1px solid var(--border);
  background: var(--panel-hi, var(--panel)); color: var(--text);
  transition: transform .09s, filter .12s;
}
/* Quitter la partie : tuile rouge comme « Annuler » de la création
   (.btn-cf-cancel) — piloté par la palette QML via --red / --red-rgb.
   Scopé sous .wp-actions pour battre la spécificité de .wp-actions .wp-btn. */
.wp-actions .wp-btn-leave { color: var(--red); background: rgba(var(--red-rgb), 0.10); border-color: rgba(var(--red-rgb), 0.5); }
.wp-actions .wp-btn-leave:not(:disabled):hover { background: rgba(var(--red-rgb), 0.20); }
/* Démarrer la partie : même couleur que « Créer une partie » du lobby
   (.lfb-create / .cf-create-btn) — navy neutre QML, texte blanc. */
.wp-actions .wp-btn-start {
  color: #ffffff; border-color: transparent;
  background: #2b3444;
}
.wp-actions .wp-btn-start:not(:disabled):hover { background: #384252; }
.wp-btn-start:disabled { opacity: 0.45; cursor: not-allowed; filter: grayscale(0.45); }
.wp-btn:not(:disabled):active { transform: scale(0.97); }
/* When the action-bar hosts the waiting panel (no real action buttons
   yet), override its default right-alignment so the panel sits in the
   middle of the bottom strip. Once the game starts, .waiting-panel is
   replaced by buttons and the default flex-end alignment kicks back in. */
.action-bar:has(.waiting-panel) {
  justify-content: center;
}
/* Fallback for browsers that don't support :has() — we also widen the
   panel itself so it occupies the full bar width and centres its inner
   contents via its own align-items:center. Modern browsers (Chrome 105+,
   Safari 15.4+, Firefox 121+) all support :has(), but this belt-and-
   braces approach makes the centring work even on older mobile Safari. */
.waiting-panel { width: 100%; }

/* Start-now banner — shown when the admin can launch with bots.
   Pulsing animation draws attention without being too noisy. */
.wp-ready-row {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  margin-top: 8px; padding: 10px 14px;
  background: linear-gradient(180deg, rgba(var(--green2-rgb), 0.10), rgba(var(--green2-rgb), 0.04));
  border: 1px solid rgba(var(--green2-rgb), 0.4);
  border-radius: var(--r-sm);
  animation: wpReadyAppear 0.4s ease-out;
}
@keyframes wpReadyAppear {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.wp-ready-label {
  font-size: var(--fs-sm); color: #88e4a3; font-weight: 600;
  letter-spacing: 0.04em;
}
.wp-ready-btn {
  padding: 9px 18px;
  background: linear-gradient(180deg, rgba(var(--green2-rgb), 0.35), rgba(var(--green2-rgb), 0.18));
  border: 1px solid rgb(var(--green2-rgb));
  border-radius: 4px;
  color: #d0ffd8;
  font-family: var(--ff-display);
  font-size: var(--fs-base);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  animation: wpReadyPulse 1.6s ease-in-out infinite;
  transition: transform 0.12s;
}
.wp-ready-btn:hover {
  background: linear-gradient(180deg, rgba(var(--green2-rgb), 0.55), rgba(var(--green2-rgb), 0.3));
  transform: scale(1.04);
}
.wp-ready-btn:active { transform: scale(0.97); }
@keyframes wpReadyPulse {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(var(--green2-rgb), 0.5),
                0 1px 4px rgba(0,0,0,0.4) inset;
  }
  50% {
    box-shadow: 0 0 0 8px rgba(var(--green2-rgb), 0),
                0 1px 4px rgba(0,0,0,0.4) inset;
  }
}

/* On mobile, keep things compact */
@media (max-width: 599.98px) {
  .waiting-panel { padding: 8px 10px; gap: 5px; }
  .wp-ready-row { padding: 8px 10px; gap: 5px; }
  .wp-ready-label { font-size: var(--fs-xs); }
  .wp-ready-btn { padding: 7px 14px; font-size: var(--fs-xs); }
  .wp-title { font-size: var(--fs-base); }
  .wp-player { font-size: var(--fs-xs); padding: 2px 8px 2px 3px; }
  .wp-av { width: 20px; height: 20px; }
}


/* ══ END-OF-GAME OVERLAY ══
   Full-screen panel shown when the tournament finishes (EndOfGame
   message). Style is heavier than the per-hand winner-overlay:
   bigger trophy, dramatic gold gradient, dedicated stats section. */
.endgame-overlay {
  position: fixed; inset: 0; z-index: 110;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.85);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: endgameFadeIn 0.4s ease-out;
}
@keyframes endgameFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.endgame-card {
  background: var(--modal-bg);
  border: 1px solid var(--gold);
  border-top: 4px solid var(--gold);
  border-radius: var(--r-lg);
  padding: 22px 28px;
  max-width: 480px; width: calc(100% - 32px);
  box-shadow: 0 8px 40px rgba(0,0,0,0.8), 0 0 60px rgba(var(--gold-rgb), 0.15);
  display: flex; flex-direction: column; gap: 14px;
  animation: endgamePop 0.55s cubic-bezier(0.2,0.9,0.3,1.1);
}
@keyframes endgamePop {
  0%   { transform: scale(0.85) translateY(20px); opacity: 0; }
  100% { transform: scale(1)    translateY(0);    opacity: 1; }
}
.eg-trophy {
  text-align: center; font-size: 3rem; line-height: 1;
  filter: drop-shadow(0 4px 12px rgba(var(--gold-rgb), 0.4));
  animation: trophyBob 2.2s ease-in-out infinite;
}
@keyframes trophyBob {
  0%,100% { transform: translateY(0) rotate(-2deg); }
  50%     { transform: translateY(-4px) rotate(2deg); }
}
.eg-title {
  text-align: center;
  font-family: var(--ff-display);
  font-size: 1.25rem; letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-hi);
  text-shadow: 0 2px 8px rgba(var(--gold-rgb), 0.3);
}
.eg-winner {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-4);
  padding: 10px 14px;
  background: rgba(var(--gold-rgb), 0.08);
  border: 1px solid var(--gold-dim);
  border-radius: var(--r-sm);
}
.eg-winner-av {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--inset);
  font-size: var(--fs-2xl); line-height: 1;
  border: 2px solid var(--gold);
}
.eg-winner-av.letter { font-size: var(--fs-lg); font-weight: 700; color: var(--gold); }
.eg-winner-label { font-size: var(--fs-2xs); color: var(--gold-dim);
  text-transform: uppercase; letter-spacing: 0.12em; }
.eg-winner-name  { font-size: var(--fs-lg); color: var(--cream); font-weight: 600; }
.eg-winner.me {
  background: rgba(var(--green2-rgb), 0.12);
  border-color: rgba(var(--green2-rgb), 0.5);
}
.eg-winner.me .eg-winner-av { border-color: rgb(var(--green2-rgb)); }
.eg-stats-section {
  background: rgba(0,0,0,0.35);
  border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 12px 14px;
}
.eg-stats-title {
  font-size: var(--fs-2xs); color: var(--gold-dim);
  text-transform: uppercase; letter-spacing: 0.15em;
  margin-bottom: 8px;
}
.eg-stat-row {
  display: flex; justify-content: space-between; align-items: center;
  font-size: var(--fs-sm); padding: 3px 0;
}
.eg-stat-label { color: var(--text); }
.eg-stat-val   { color: var(--cream); font-weight: 600; font-family: var(--ff-mono); }
.eg-stat-val.pos { color: var(--pos); }
.eg-stat-val.neg { color: var(--neg); }
.eg-stat-divider {
  border: none; border-top: 1px solid var(--border);
  margin: 6px 0;
}
/* Encart session : fond noir 0.35 pensé pour le sombre → en thème clair il vire au gris
   moyen et écrase le contraste des libellés. On l'éclaircit en thème clair (palette QML). */
:root[data-theme="pokerth-light"] .eg-stats-section {
  background: rgba(0,0,0,0.05);
  border-color: rgba(0,0,0,0.10);
}
.eg-actions {
  display: flex; gap: var(--sp-4); margin-top: 4px;
}
.eg-btn {
  flex: 1; padding: 10px 14px;
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--cream);
  font-family: var(--ff-display);
  font-size: var(--fs-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.eg-btn:hover { background: var(--inset-hi); border-color: var(--gold-dim); }
.eg-btn.primary {
  background: linear-gradient(180deg, rgba(var(--gold-rgb), 0.25), rgba(var(--gold-rgb), 0.12));
  border-color: var(--gold);
  color: var(--gold-hi);
}
.eg-btn.primary:hover {
  background: linear-gradient(180deg, rgba(var(--gold-rgb), 0.4), rgba(var(--gold-rgb), 0.2));
}
@media (max-width: 599.98px) {
  .endgame-card { padding: 16px 18px; gap: var(--sp-4); }
  .eg-trophy { font-size: 2.4rem; }
  .eg-title { font-size: var(--fs-md); letter-spacing: 0.14em; }
  .eg-winner-av { width: 32px; height: 32px; font-size: var(--fs-xl); }
  .eg-winner-name { font-size: var(--fs-md); }
  .eg-stat-row { font-size: var(--fs-xs); }
}


/* ══ AUTO CHECK/FOLD CHECKBOX ══
   Rendered above the action grid by renderMyTurnActions() so the user
   can arm the auto-action for their NEXT turn within the same hand.
   Deliberately discreet — small, low-contrast — because it represents
   a fully optional courtesy feature, not a primary action button. */
.auto-cf-row {
  display: flex; align-items: center; gap: 9px;
  background: rgba(var(--gold-rgb), 0.06);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 11px; margin: 0 0 7px;
  cursor: pointer; user-select: none;
  flex-basis: 100%;
  transition: background 0.15s, border-color 0.15s;
}
.auto-cf-row:hover { background: rgba(var(--gold-rgb), 0.1); border-color: var(--gold-dim); }
.auto-cf-label { font-size: var(--fs-xs); color: var(--gold-dim); font-weight: 500; font-family: var(--ff-mono); }
.auto-cf-row:has(input:checked) .auto-cf-label { color: var(--cream); font-weight: 700; }
.auto-cf-hint { margin-left: auto; font-size: var(--fs-3xs); color: var(--gold-dim); font-style: italic; }
/* iOS-style toggle switch */
.auto-switch { position: relative; display: inline-block; width: 38px; height: 21px; flex-shrink: 0; }
.auto-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.auto-switch-track { position: absolute; inset: 0; background: rgba(255,255,255,0.12);
  border: 1px solid var(--gold-dim); border-radius: 21px; transition: 0.2s; }
.auto-switch-track::before { content: ""; position: absolute; height: 15px; width: 15px; left: 2px; top: 2px;
  background: var(--cream); border-radius: 50%; transition: 0.2s; }
.auto-switch input:checked + .auto-switch-track { background: rgba(var(--green-rgb), 0.5); border-color: var(--green); }
.auto-switch input:checked + .auto-switch-track::before { transform: translateX(17px); background: var(--on-green); }
@media (max-width: 599.98px) {
  .auto-cf-row { padding: 6px 9px; margin-bottom: 5px; gap: var(--sp-3); }
  .auto-cf-label { font-size: var(--fs-xs); }
  .auto-cf-hint { font-size: var(--fs-3xs); }
}


/* ══ SPECTATOR BANNER ══
   Shown at the top of the game screen (just below the header,
   above the pot strip) when the user is watching as a spectator.
   Subtle blue tint to differentiate from regular player view, with
   a small animated pulse on the eye emoji to draw attention without
   being noisy. */
/* Statut spectateur intégré au bandeau du pot #pot-strip (parité GameStatusBar
   QML §7) : pastille or « Spectating » (visible si je suis spectateur) + œil
   avec compteur (visible dès qu'au moins un spectateur regarde). g-pot (flex:1)
   pousse ces éléments à droite, juste avant la phase (#g-round). */
#g-spec-badge {
  display: none;               /* activé par JS via .on quand _amSpectator */
  align-items: center;
  /* Modele generique --comm-scale (comme .blinds-next / .conn-pill /
     .win-hand-badge) : le badge est COLLE au badge des blindes dans .gsb-mid,
     il doit donc grandir avec lui. Valeurs strictement identiques a
     .blinds-next, sinon les deux pastilles voisines divergent des que
     --comm-scale quitte 1 (desktop = 1.35). */
  height: clamp(18px, calc(19px * var(--comm-scale, 1)), 28px);
  box-sizing: border-box;
  padding: 0 clamp(8px, calc(9px * var(--comm-scale, 1)), 14px);
  margin-right: 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--sel-bar);
  background: rgba(var(--sel-bar-rgb), 0.22);
  color: var(--sel-bar);
  font-size: clamp(10px, calc(11px * var(--comm-scale, 1)), 16px);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  flex-shrink: 0;
}
#g-spec-badge.on { display: inline-flex; }
#g-spec-count {
  display: none;               /* activé par JS via .on quand count > 0 */
  align-items: center;
  gap: 3px;
  margin-right: 8px;
  color: #eff1f5;
  font-size: clamp(10px, calc(11px * var(--comm-scale, 1)), 16px);
  font-weight: 700;
  flex-shrink: 0;
  cursor: default;
}
#g-spec-count.on { display: inline-flex; }
#g-spec-count .sc-eye {
  font-size: 0.92em;
  opacity: 0.9;
  animation: sbEyePulse 2.4s ease-in-out infinite;
}
@keyframes sbEyePulse {
  0%,100% { opacity: 0.7; transform: scale(1); }
  50%     { opacity: 1;   transform: scale(1.12); }
}
@media (max-width: 599.98px) {
  /* Mobile : la pastille texte « Spectating » est redondante avec l'oeil
     juste a cote et mange ~100px du bandeau -> masquee. Quand JE regarde
     (.me pose par updateSpectatorStrip), l'OEIL herite du contour jaune de
     la pastille : l'info reste, en ~30px. */
  #g-spec-badge.on { display: none; }
  #g-spec-count { margin-right: 6px; }
  #g-spec-count.me {
    height: 18px; box-sizing: border-box; padding: 0 7px;
    border-radius: var(--r-pill);
    border: 1px solid var(--sel-bar);
    background: rgba(var(--sel-bar-rgb), 0.22);
    color: var(--sel-bar);
  }
}

/* Replacement message that occupies the action area when the user
   is a spectator. Same vertical footprint as the action buttons so
   the layout doesn't jump around between hands. */



/* ══ QUIT-GAME CONFIRMATION DIALOG ══
   Centred modal with 2 buttons: Quit / Cancel. Shown when the user
   clicks the ✕ from inside a game. Gold-bordered card matching the
   rest of the UI, with backdrop blur and a soft pop animation. */
/* Shared modal container for the three confirmation dialogs:
   #leave-dialog (quit a game in progress)
   #disconnect-dialog (disconnect from the lobby)
   #quick-create-dialog (set player count on a quick-create) — this one
   already has its own rule because it was added in a separate commit
   with the same body; consolidating could be a future cleanup. */
#leave-dialog,
#disconnect-dialog {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.7);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  animation: ldFade 0.25s ease-out;
}
@keyframes ldFade { from { opacity: 0; } to { opacity: 1; } }
.ld-card {
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: 14px;
  padding: 22px 24px;
  max-width: 400px; width: calc(100% - 32px);
  box-shadow: 0 8px 32px rgba(0,0,0,0.7);
  animation: ldPop 0.35s cubic-bezier(0.2,0.9,0.3,1.1);
}
@keyframes ldPop {
  from { transform: scale(0.9) translateY(8px); opacity: 0; }
  to   { transform: scale(1)   translateY(0);   opacity: 1; }
}
.ld-title {
  font-family: var(--ff-display);
  font-size: 1.15rem; font-weight: 700; letter-spacing: 0.01em;
  color: var(--text-hi); text-align: left; margin-bottom: 10px;
}
.ld-body {
  font-size: var(--fs-md); color: var(--cream);
  text-align: left; margin-bottom: 18px; line-height: 1.45;
}
/* row-reverse : Annuler (2e enfant) a gauche, action (1er enfant) a droite,
   comme le dialogue officiel — sans toucher au HTML. */
.ld-buttons {
  display: flex; flex-direction: row-reverse; gap: var(--sp-4);
}
.ld-btn {
  flex: 1 1 0; min-width: 0;
  padding: 11px 16px;
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--cream);
  font-family: var(--ff-display);
  font-size: var(--fs-sm);
  letter-spacing: 0.1em; text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.ld-btn:hover  { background: var(--inset-hi); }
.ld-btn:active { transform: scale(0.98); }
.ld-btn.ld-quit {
  background: transparent;
  border: 1px solid var(--border-hi);
  color: var(--cream);
}
.ld-btn.ld-quit:hover  { background: var(--inset); }
.ld-btn.ld-quit:active { transform: scale(0.98); }
.ld-btn.ld-cancel {
  background: transparent;
  border: 1px solid var(--border-hi);
  color: var(--cream);
}
.ld-btn.ld-cancel:hover  { background: var(--inset); }
.ld-btn.ld-cancel:active { transform: scale(0.98); }
@media (max-width: 599.98px) {
  .ld-card { padding: 16px 18px; }
  .ld-title { font-size: var(--fs-md); }
  .ld-body { font-size: var(--fs-sm); }
  .ld-btn { padding: 9px 12px; font-size: var(--fs-xs); }
}


/* ══ QUICK-CREATE DIALOG ══
   Reuses the .ld-* styles from the leave-dialog (gold card, backdrop,
   buttons). Adds a centred input row and a green 'Create' button to
   match the semantic 'positive action' colour used elsewhere. */
#quick-create-dialog {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.7);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  animation: ldFade 0.25s ease-out;
}
.qc-control {
  display: flex; align-items: center; justify-content: center;
  gap: var(--sp-5); margin: 0 0 18px;
}
.qc-control label {
  font-family: var(--ff-display);
  font-size: var(--fs-sm); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold-dim);
}
.qc-control input[type="number"] {
  width: 70px;
  padding: 8px 10px;
  background: var(--field-bg);
  border: 1px solid var(--gold-dim);
  border-radius: 4px;
  color: var(--text-hi);
  font-family: var(--ff-mono);
  font-size: var(--fs-lg);
  text-align: center;
  outline: none;
  transition: border-color 0.15s;
}
.qc-control input[type="number"]:focus { border-color: var(--gold); }
.ld-btn.ld-create {
  background: var(--qml-pos-grad);
  border-color: var(--qml-pos-edge);
  color: var(--qml-pos-fg); font-weight: 600;
}
.ld-btn.ld-create:hover { background: var(--qml-pos-grad-hi); }
@media (max-width: 599.98px) {
  .qc-control { gap: var(--sp-3); }
  .qc-control input[type="number"] { font-size: var(--fs-md); width: 60px; padding: 6px 8px; }
}


/* ══ PLAYERS ONLINE DROPDOWN PANEL ══
   Triggered by clicking the #h-players pill in the lobby header.
   Same visual chrome as #g-chat-panel / #g-log-panel so the three
   dropdowns feel like siblings. Adds a search input row above the
   scrollable list for quick filtering when many players are online. */
#players-panel {
  position: fixed !important;
  top: var(--ovl-top, 48px);
  left: 0; right: 0;
  z-index: 100;
  max-height: min(360px, 50dvh) !important;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 20px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
}
.players-search {
  padding: 6px 10px;
  background: var(--chrome-tint);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.players-search input {
  width: 100%;
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  color: var(--cream);
  padding: 5px 10px;
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  outline: none;
  box-sizing: border-box;
}
.players-search input:focus { border-color: var(--gold); }
/* Palette claire : champ de recherche gris plein arrondi, sans bordure,
   placeholder col300 (parite QML Universal light). */
:root[data-theme="pokerth-light"] .players-search input {
  background:#b9bbbf; border-color:transparent; border-radius:var(--r-sm); color:#1d222b;
}
:root[data-theme="pokerth-light"] .players-search input::placeholder { color:#687285; }
:root[data-theme="pokerth-light"] .players-search input:focus { border-color:#9a9ca1; }
/* Body container — the inline style on the element sets flex/min-height/
   overflow/padding/background to match the chat panel pattern exactly.
   This rule keeps only the bits inline styles don't cover. */
.players-list {
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
}
.players-list .pl-row {
  display: grid;
  grid-template-columns: var(--pl-cols, 22px minmax(0,1fr) 16px 22px 48px 48px);
  align-items: center;
  gap: var(--sp-3);
  padding: 4px 0;          /* container provides the 12px lateral padding now */
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  color: var(--cream);
  border-bottom: 1px solid var(--inset);
}
.players-list .pl-row:last-child { border-bottom: none; }
.players-list .pl-row:hover { background: rgba(var(--gold-rgb), 0.08); }
.players-list .pl-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.players-list .pl-name-link { color: inherit; text-decoration: none; cursor: pointer; }
.players-list .pl-name-link:hover, .players-list .pl-name-link:active { color: var(--gold-hi); }
.players-list .pl-flag { flex: none; display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--sp-1); font-size: var(--fs-md); line-height: 1; }
.players-list .pl-cc { font-size: var(--fs-2xs); color: var(--gold-dim); font-family: var(--ff-mono); letter-spacing: 0.04em; white-space: nowrap; }
.players-list .pl-flag .cc-flag { width: 20px; height: 15px; }
.players-list .pl-star { flex: none; width: 1.4em; text-align: center; font-size: var(--fs-md); line-height: 1; color: var(--gold); }
.players-list .pl-id   { flex: none; min-width: 4.2em; text-align: right; color: var(--gold-dim); font-size: var(--fs-xs); }
.players-list .pl-row.pl-me { color: var(--gold); }
/* ── Avatar chip in the players-online list ──
   Same priority order as everywhere else (real PokerTH image >
   placeholder logo > emoji > 🤖 > initial letter). The chip-pth-img
   rule (defined globally for compact lists) handles image clipping. */
.pl-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--inset);
  font-size: var(--fs-lg);
  line-height: 1;
}
.pl-av.letter { font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }
.pl-av.has-pth-avatar {
  background: rgba(0,0,0,0.2);
  padding: 0;
  overflow: visible;
}
.players-list .pl-empty {
  padding: var(--sp-5);
  text-align: center;
  font-style: italic;
  color: var(--gold-dim);
  font-size: var(--fs-xs);
}
/* Custom scrollbar matching chat/log */
.players-list::-webkit-scrollbar { width: 6px; }
.players-list::-webkit-scrollbar-track { background: transparent; }
.players-list::-webkit-scrollbar-thumb {
  background: rgba(var(--gold-rgb), 0.18);
  border-radius: var(--r-xs);
}
.players-list::-webkit-scrollbar-thumb:hover { background: rgba(var(--gold-rgb), 0.32); }
/* ═══════════════════════════════════════════════════════════════════
   Inline SVG flag (used by the language-toggle button).
   We size against the inherited font-size so the flag scales with
   the button text — same look on mobile and desktop. The aspect
   ratio (2:1) matches the viewBox in i18n.mjs.
   ═══════════════════════════════════════════════════════════════════ */
.lang-flag {
  width: 1.5em;
  height: 0.75em;
  vertical-align: middle;
  display: inline-block;
  border-radius: 1.5px;
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

/* Overflow-menu language entries (lobby + game headers): the flag SVG is
   followed directly by the language label, separated only by a literal
   space that collapses against the inline-block flag. Give the flag a
   right margin so flag and label don't touch. Scoped to these two
   buttons only — the icon-only header buttons and the dropdown picker
   (which already uses flex `gap`) are untouched. */
#lang-toggle-game-mob .lang-flag,
#lang-toggle-lobby-mob .lang-flag {
  margin-right: 8px;
}

/* ═══════════════════════════════════════════════════════════════════
   Connect-screen top-right button bar.
   The lang/refresh/fullscreen trio sits outside any `.header` block,
   so the global `.header .btn-sm` uniformization rule doesn't reach
   them. Apply the same dimensions here so the three (or four) buttons
   line up neatly.
   ═══════════════════════════════════════════════════════════════════ */
#s-connect > div:first-child .btn-icon,
#s-connect .corner-links .btn-icon {
  height: 30px;
  min-width: 30px;
  padding: 0 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  font-size: var(--fs-sm);
  line-height: 1;
  color: var(--text-hi);
  /* Frameless : icône nue sur le bandeau (plus de chip). */
  background: transparent;
  border: 1px solid transparent;
  box-shadow: none;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
#s-connect > div:first-child .btn-icon:hover,
#s-connect .corner-links .btn-icon:hover {
  background: rgba(255,255,255,0.07);
  border-color: transparent;
}
#s-connect > div:first-child .btn-icon,
#s-connect .corner-links .btn-icon {
  width: 30px;
  padding: 0;
  background: transparent;
}

#s-connect .corner-links .btn-icon{ text-decoration:none; }

/* ═══ Bandeau header de la page de connexion ═══════════════════════════
   Barre unique en haut, même chrome que le header lobby/jeu (.header :
   fond --panel + bord bas --border). position:absolute pour ne pas
   décentrer la carte ; overflow:visible + ancrage positionné pour que
   #connect-overflow-menu tombe sous la barre (même principe que
   #s-lobby .header). ☰ liens + 🏆 à gauche · install + ••• à droite.
   Le style/taille fin des boutons est traité à l'étape suivante. */
#s-connect .connect-header{
  position:absolute; top:0; left:0; right:0; z-index:20;
  overflow:visible;
  justify-content:space-between;
}
#s-connect .connect-header .hdr-group{ display:flex; align-items:center; gap:var(--sp-2); }
/* Ancrage des menus overflow sur LEUR bouton (et non sur toute la barre)
   pour éviter le décalage horizontal du padding — comme le menu ☰.
   Connexion utilise le même wrapper .hdr-ovf-wrap que lobby/jeu. */
.hdr-ovf-wrap{ position:relative; display:inline-flex; align-items:center; }
/* Icônes pleines : plus d'encadré (ni fond, ni bord, ni ombre) — l'icône
   seule sur la barre. */
#s-connect .connect-header .btn-icon{
  background:transparent;
  border-color:transparent;
  box-shadow:none;
  backdrop-filter:none; -webkit-backdrop-filter:none;
}
#s-connect .connect-header .btn-icon:hover{
  background:rgba(255,255,255,0.07);
  border-color:transparent;
}
/* Couleurs des icônes : neutres au repos (le trophée aussi — narmod 23/07,
   il ne passe en or doré que fenêtre ouverte, cf. .win-open), install vert.
   Les SVG utilisent currentColor -> on colore le bouton. */
#s-connect .connect-header #cl-links-connect > summary{ color:var(--text-hi); }
#s-connect .connect-header #ranking-btn-connect{ color:var(--text-hi); }
#s-connect .connect-header #install-btn{ color:#3ba55d; }
#s-connect .connect-header #connect-overflow-btn{ color:var(--text-hi); }

/* ═══ Headers lobby + jeu : même traitement que connexion ═══════════════
   Icônes pleines (sans encadré) + couleurs. Frameless scopé aux .btn-icon
   pour ne pas toucher aux boutons-texte admin (Start/Close/Kick). */
#s-lobby .header .btn-icon,
#s-game .header .btn-icon,
#s-create .cp-header .btn-icon,
#privacy-page .cp-header .btn-icon{
  background:transparent;
  border-color:transparent;
  box-shadow:none;
}
#s-lobby .header .btn-icon:hover,
#s-game .header .btn-icon:hover,
#s-create .cp-header .btn-icon:hover,
#privacy-page .cp-header .btn-icon:hover{
  background:rgba(255,255,255,0.07);
  border-color:transparent;
}
/* Aucun contour au focus/clic non plus (comme le client officiel) : pas de
   ring navigateur, pas de bord, pas d'ombre — repos, hover, focus, actif. */
#s-connect .connect-header .btn-icon,
#s-connect .connect-header .btn-icon:focus,
#s-connect .connect-header .btn-icon:focus-visible,
#s-connect .connect-header .btn-icon:active,
#s-connect .connect-header #cl-links-connect > summary:focus,
#s-connect .connect-header #cl-links-connect > summary:focus-visible,
#s-lobby .header .btn-icon,
#s-game .header .btn-icon,
#s-create .cp-header .btn-icon,
#s-lobby .header .btn-icon:focus,
#s-game .header .btn-icon:focus,
#s-create .cp-header .btn-icon:focus,
#s-lobby .header .btn-icon:focus-visible,
#s-game .header .btn-icon:focus-visible,
#s-create .cp-header .btn-icon:focus-visible,
#s-lobby .header .btn-icon:active,
#s-game .header .btn-icon:active,
#s-create .cp-header .btn-icon:active,
#privacy-page .cp-header .btn-icon,
#privacy-page .cp-header .btn-icon:focus,
#privacy-page .cp-header .btn-icon:focus-visible,
#privacy-page .cp-header .btn-icon:active{
  outline:none;
  border-color:transparent;
  box-shadow:none;
}
#s-lobby .header #ranking-btn-lobby{ color:var(--text-hi); }
/* Page « Créer une partie » : flèche retour + roue crantée neutres. */
#s-create .cp-header #cr-overflow-btn{ color:var(--text-hi); }
#privacy-page .cp-header #pv-overflow-btn{ color:var(--text-hi); }
#s-create .cp-header #ranking-btn-create{ color:var(--text-hi); }
#s-lobby .header #lobby-chat-btn{ color:var(--text-hi); }
#s-lobby .header #l-overflow-btn{ color:var(--text-hi); }
#s-game .header #sound-toggle-btn{ color:var(--text-hi); }
#s-game .header #ranking-btn-game{ color:var(--text-hi); }
#s-game .header #g-overflow-btn{ color:var(--text-hi); }

/* Mode clair : les icônes acier #c3ccda deviennent quasi invisibles sur la
   barre claire -> on les fonce (près du noir) pour un contraste marqué. */
:root[data-theme="pokerth-light"] #s-connect .connect-header #cl-links-connect > summary,
:root[data-theme="pokerth-light"] #s-connect .connect-header #connect-overflow-btn,
:root[data-theme="pokerth-light"] #s-lobby .header #lobby-chat-btn,
:root[data-theme="pokerth-light"] #s-lobby .header #l-overflow-btn,
:root[data-theme="pokerth-light"] #s-game .header #sound-toggle-btn,
:root[data-theme="pokerth-light"] #s-game .header #g-overflow-btn,
:root[data-theme="pokerth-light"] #s-connect .connect-header #ranking-btn-connect,
:root[data-theme="pokerth-light"] #s-lobby .header #ranking-btn-lobby,
:root[data-theme="pokerth-light"] #s-create .cp-header #ranking-btn-create,
:root[data-theme="pokerth-light"] #s-game .header #ranking-btn-game{
  color:#1d222b;
}
/* ... sauf quand leur fenêtre est ouverte : l'or doré reprend la main. */
:root[data-theme="pokerth-light"] .btn-icon.win-open{ color:var(--sel, #9a7d0a) !important; }
#s-connect .corner-links .btn-icon img{ display:block; width:18px; height:18px; }

/* ═══════════════════════════════════════════════════════════════════
   Credits footer (connect screen only).
   Sits at the bottom of #s-connect without disturbing the centered
   login card. Hidden on lobby/game screens to avoid eating playable
   space. Mentions only the repo for this fork — no upstream PokerTH
   link (to stay respectfully unaffiliated).
   ═══════════════════════════════════════════════════════════════════ */
.connect-footer {
  position: absolute;
  bottom: 10px;
  left: 0;
  right: 0;
  text-align: center;
  color: var(--text-hi);
  font-family: var(--ff-mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
  line-height: 1.5;
  opacity: 0.95;
  text-shadow: 0 1px 4px rgba(0,0,0,0.95), 0 0 2px rgba(0,0,0,0.8);
  pointer-events: auto;
  z-index: 1;
}
/* Icône Discord au-dessus de la ligne de crédits (pied de page classique).
   Pastille ronde blurple officielle + logo blanc, comme les icônes sociales
   d'un footer de site. Sélecteur .connect-footer .cf-discord pour battre la
   règle générique .connect-footer a (couleur or + soulignement pointillé). */
/* Rangée d'icônes sociales (Discord · GitHub · pokerth.net) : pastilles
   translucides et discrètes au repos, pleine couleur de marque au survol. */
.connect-footer .connect-social {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: 6px;
}
.connect-footer .cf-social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border-bottom: none;
  background: rgba(20,24,34,0.55);      /* pastille sombre : ressort sur le fond clair chargé */
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  opacity: 1;
  transition: background 0.2s, transform 0.2s, opacity 0.2s, box-shadow 0.2s;
}
.connect-footer .cf-social svg,
.connect-footer .cf-social img { opacity: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.5)); }
.connect-footer .cf-social:hover {
  opacity: 1;
  transform: scale(1.08);
  box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
/* Couleurs de marque révélées au survol uniquement. */
.connect-footer .cf-discord:hover { background: #5865F2; }   /* blurple Discord */
.connect-footer .cf-github:hover  { background: #24292e; }   /* gris GitHub */
.connect-footer .cf-web:hover     { background: rgba(40,46,60,0.75); }  /* logo coloré : pas de teinte or */

.connect-footer-line {
  margin: 1px 0;
}
.connect-footer a {
  color: var(--gold-hi);
  text-decoration: none;
  text-shadow: 0 1px 4px rgba(0,0,0,0.95);
  border-bottom: 1px dotted rgba(var(--gold-rgb), 0.5);
  transition: color 0.2s, border-color 0.2s;
}
.connect-footer a:hover {
  color: var(--gold);
  border-bottom-color: var(--gold);
}
/* pokerth-light: footer overlays the dark flames, so the theme's dark
   tokens would vanish -> warm-light values that harmonise with the fire. */
:root[data-theme="pokerth-light"] .connect-footer { color: #ece8dc; }
:root[data-theme="pokerth-light"] .connect-footer a {
  color: #f0d68a;
  border-bottom-color: rgba(240,214,138,0.5);
}
:root[data-theme="pokerth-light"] .connect-footer a:hover {
  color: #ffe9ad;
  border-bottom-color: #ffe9ad;
}
/* On very short screens (e.g. landscape mobile) hide the footer so
   the login card has more room. */
@media (max-height: 599.98px) {
  .connect-footer { display: none; }
}

/* Là où le cadre de login chevauche le footer, le cadre passe AU-DESSUS
   (z-index) et recouvre les raccourcis/crédits. Aucune modification de taille
   du cadre ni du footer — simple ordre d'empilement.
   Était limité à @media (max-width:640px) : sur desktop/tablette le footer
   repassait devant le bas du cadre (constaté narmod 22/07). Règle désormais
   valable sur toutes les tailles. */
#s-connect > .card { position: relative; z-index: 2; }



/* ── Kick player modal (opened by admin from header) ──
   Lists table players with an inline trash button to kick. Same
   visual language as #player-info-modal and #game-info-modal. */
#kick-modal,
#kick-confirm-modal,
#report-confirm-modal,
#invite-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
}
.km-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.65);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.km-card {
  position: relative;
  background: var(--modal-bg);
  border: 1px solid var(--gold-dim);
  border-radius: 8px;
  padding: 18px 18px 16px;
  width: min(360px, 100%);
  max-height: min(80vh, 600px);
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  -webkit-overflow-scrolling: touch;
  animation: slideDown 0.18s ease;
}
.km-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-md);
  padding: 2px 6px;
  line-height: 1;
}
.km-close:hover { color: var(--gold); }
.km-title {
  font-size: var(--fs-lg);
  color: var(--cream);
  font-family: var(--ff-display);
  font-weight: 600;
  text-align: center;
  padding-right: 24px;
  letter-spacing: 0.04em;
}
.km-subtitle {
  font-size: var(--fs-xs);
  color: var(--gold-dim);
  text-align: center;
  letter-spacing: 0.05em;
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.15);
  padding-bottom: 8px;
  margin-bottom: 2px;
}
.km-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.km-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 8px 10px;
  background: var(--inset);
  border: 1px solid var(--inset);
  border-radius: 4px;
}
.km-row .km-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--inset);
  font-size: var(--fs-xl);
  line-height: 1;
}
.km-row .km-av.letter { font-size: var(--fs-md); font-weight: 700; color: var(--gold); }
.km-row .km-av.has-pth-avatar { background: rgba(0,0,0,0.2); padding: 0; overflow: visible; }
.km-row .km-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-0);
}
.km-row .km-name {
  color: var(--cream);
  font-family: var(--ff-mono);
  font-size: var(--fs-base);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.km-row .km-meta {
  color: var(--gold-dim);
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.05em;
}
.km-row .km-kick {
  flex-shrink: 0;
  background: rgba(var(--red-rgb), 0.18);
  border: 1px solid rgba(var(--red-rgb), 0.4);
  color: var(--red);
  border-radius: 4px;
  padding: 6px 10px;
  font-size: var(--fs-md);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
.km-row .km-kick:hover {
  background: rgba(var(--red-rgb), 0.35);
  border-color: var(--red);
}
.km-row .km-kick:active { transform: scale(0.95); }
.km-row.km-self {
  /* Yourself: shown for context but no kick button */
  opacity: 0.7;
}
.km-row.km-self .km-name::after {
  content: ' (vous, admin)';
  color: var(--gold-dim);
  font-size: var(--fs-xs);
}
.km-empty {
  text-align: center;
  color: var(--gold-dim);
  font-style: italic;
  padding: 18px;
}

/* ── Kick-confirm modal ── small nested alert dialog */
.kcm-card {
  position: relative;
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: 14px;
  padding: 22px 24px 18px;
  width: min(360px, 100%);
  box-shadow: 0 8px 32px rgba(0,0,0,0.7);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-4);
  animation: slideDown 0.18s ease;
}
/* Le dialogue officiel n'a pas d'icone — on la masque pour rester fidele. */
.kcm-icon { display: none; }
.kcm-title {
  font-size: 1.15rem;
  color: var(--text-hi);
  font-family: var(--ff-display);
  font-weight: 700;
  letter-spacing: 0.01em;
  text-align: left;
}
.kcm-msg {
  font-size: var(--fs-md);
  color: var(--cream);
  text-align: left;
  line-height: 1.45;
  word-break: break-word;
}
.kcm-btns {
  display: flex;
  gap: var(--sp-4);
  width: 100%;
  margin-top: 4px;
}
.kcm-cancel,
.kcm-confirm {
  flex: 1;
  padding: 10px 12px;
  border-radius: var(--r-md);
  font-family: var(--ff-display);
  font-size: var(--fs-base);
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.kcm-cancel {
  background: transparent;
  border: 1px solid var(--border-hi);
  color: var(--cream);
}
.kcm-cancel:hover  { background: var(--inset); }
.kcm-cancel:active { transform: scale(0.98); }
.kcm-confirm {
  background: transparent;
  border: 1px solid var(--border-hi);
  color: var(--cream);
}
.kcm-confirm:hover  { background: var(--inset); }
.kcm-confirm:active { transform: scale(0.98); }


/* ── Waiting-panel start buttons (2-button variant) ──
   The .wp-ready-row used to host a single LANCER MAINTENANT button.
   With the introduction of startNoBots() the row now offers two:
   "▶ Démarrer" (humans only) + "▶ + Bots" (fill with bots).
   They sit side by side and wrap to two lines on very narrow widths. */
.wp-ready-btn-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3);
  width: 100%;
}
.wp-ready-btn-row .wp-ready-btn {
  flex: 1 1 auto;
  min-width: 110px;
  max-width: 220px;
}
/* "+ Bots" variant: same green family but slightly darker tint so
   the user can tell the two apart without having to read the labels. */
.wp-ready-btn.wp-ready-btn-bots {
  background: linear-gradient(180deg, rgba(var(--green2-rgb), 0.22), rgba(var(--green2-rgb), 0.10));
  border-color: rgba(var(--green2-rgb), 0.65);
  /* Slightly faded — "start" is the primary action, "+ bots" the secondary. */
  opacity: 0.94;
}
.wp-ready-btn.wp-ready-btn-bots:hover {
  background: linear-gradient(180deg, rgba(var(--green2-rgb), 0.4), rgba(var(--green2-rgb), 0.2));
  opacity: 1;
}
/* On very small phones, give the buttons a touch more vertical room
   so the labels don't wrap awkwardly inside a single button. */
@media (max-width: 380px) {
  .wp-ready-btn-row .wp-ready-btn {
    flex: 1 1 100%;
    max-width: 280px;
  }
}


/* ── Spectators section in #game-info-modal ──
   Shown only when there's at least one spectator watching the table.
   The list reuses the same row pattern as the kick modal (.km-row)
   but with smaller avatars (28px) since this is informational, not
   actionable. */
.gim-section-count {
  color: var(--gold-dim);
  font-size: var(--fs-xs);
  font-weight: normal;
  letter-spacing: 0.05em;
}
.gim-spec-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin-top: 6px;
}
.gim-spec-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 5px 8px;
  background: var(--inset);
  border: 1px solid var(--inset);
  border-radius: var(--r-xs);
}
.gim-spec-row .gim-spec-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--inset);
  font-size: 1.2rem;
  line-height: 1;
}
.gim-spec-row .gim-spec-av.letter {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--gold);
}
.gim-spec-row .gim-spec-av.has-pth-avatar {
  background: rgba(0,0,0,0.2);
  padding: 0;
  overflow: visible;
}
.gim-spec-row .gim-spec-name {
  flex: 1;
  color: var(--cream);
  font-family: var(--ff-mono);
  font-size: var(--fs-base);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gim-spec-me {
  color: var(--gold-dim);
  font-size: var(--fs-xs);
  font-style: italic;
  margin-left: 4px;
}
.gim-badge.gim-badge-spec {
  background: rgba(var(--blue-rgb), 0.15);
  border-color: rgba(var(--blue-rgb), 0.4);
  color: var(--info);
}


/* ── Ghost seat — player has LEFT the table (not just eliminated) ──
   A player who left during a game stays in seats[] to preserve the
   pixel positions of every other seat around the felt (re-shuffling
   them is disorienting; see the seat-out commentary). But unlike a
   merely-eliminated player they should look essentially gone:
   no name, no money, no actions, no OUT badge. The avatar fades to
   ~15% opacity so the position is still discoverable on close
   inspection but doesn't compete for the player's attention.

   Difference at a glance:
     .seat-out   = eliminated, still at the table → opacity 0.35 + OUT badge
     .seat-ghost = left the table → opacity 0.15, no text, no badge */
.seat.seat-ghost {
  opacity: 0.15;
  filter: grayscale(1);
  pointer-events: none;
}
.seat.seat-ghost .seat-name,
.seat.seat-ghost .seat-money,
.seat.seat-ghost .seat-bet,
.seat.seat-ghost .seat-action,
.seat.seat-ghost .blind-chip,
.seat.seat-ghost .dealer-chip,
.seat.seat-ghost .seat-flag {
  display: none !important;
}
/* Suppress the OUT pseudo-element specifically: .seat-ghost wins over
   .seat-out (we made them mutually exclusive in the class string, but
   this is defence-in-depth in case something else adds .seat-out). */
.seat.seat-ghost::after {
  content: none !important;
}


/* ── Copy invite-link button in #game-info-modal ── */
.gim-share-section {
  text-align: center;
}
.gim-copy-link-btn {
  width: 100%;
  padding: 10px 14px;
  background: linear-gradient(180deg, rgba(var(--gold-rgb), 0.2), rgba(var(--gold-rgb), 0.1));
  border: 1px solid var(--border-hi);
  border-radius: 5px;
  color: var(--gold-hi);
  font-family: var(--ff-display);
  font-size: var(--fs-base);
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
.gim-copy-link-btn:hover {
  background: linear-gradient(180deg, rgba(var(--gold-rgb), 0.35), rgba(var(--gold-rgb), 0.18));
  border-color: var(--gold);
}
.gim-copy-link-btn:active { transform: scale(0.98); }
.gim-share-hint {
  margin-top: 6px;
  font-size: var(--fs-xs);
  color: var(--gold-dim);
  font-style: italic;
  letter-spacing: 0.03em;
}


/* ── Poker-hands help button (inline SVG, replaces the 🂡 glyph) ── */
.btn-hands { color: var(--gold); }
.btn-hands:hover { color: var(--gold-hi); border-color: var(--border-hi); }
.btn-hands svg { display: block; }


/* ── 4-aces SVG inside the end-game overlay (replaces 🎲) ──
   .eg-trophy already provides the bob animation + gold drop-shadow;
   we just need the inline SVG to center and sit inline-block so the
   text-align:center on the parent applies. */
.eg-trophy .eg-aces {
  display: inline-block;
  vertical-align: middle;
}


/* ── Player bar when locally eliminated (.pb-out) ──
   Mirror the .seat-out look on the seats: grey out the avatar/name/stack,
   show clearly that the player has busted out of the tournament. The
   "OUT" prefix is added inline by JS in the money line. */
.player-bar.pb-out .pb-avatar,
.player-bar.pb-out .pb-name,
.player-bar.pb-out .pb-action {
  opacity: 0.45;
  filter: grayscale(0.55);
}
.player-bar.pb-out .pb-cards .pk { opacity: 0.5; }
/* Tag OUT net + suit le theme (meme logique que .seat-out::after). */
.pb-out-tag {
  display: inline-block;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: #fff;
  background: var(--red);
  padding: 0 6px;
  border-radius: 4px;
  border: 1px solid rgba(255,255,255,0.22);
  box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}

/* ═══════════════════════════════════════════════════════════════════
   LOBBY REDESIGN — création (repliable) au-dessus des tables,
   cartes de tables détaillées, et mise en page responsive
   (téléphone : 1 colonne · tablette : tables en grille 2 col ·
    ordinateur : création en colonne latérale + tables en grille).
   ═══════════════════════════════════════════════════════════════════ */
.lobby-body { display: block; overflow-y: auto; padding: 16px 14px 32px; }
.lobby-grid { display: grid; gap: 18px; grid-template-columns: 1fr; max-width: none; align-items: start; }

/* Bouton repliable "Créer une table" */
.create-toggle {
  width: 100%; display: flex; align-items: center; gap: var(--sp-5);
  background: rgba(var(--gold-rgb), 0.07); border: 1px solid var(--border); border-radius: var(--r-bar);
  color: var(--gold); cursor: pointer; padding: 13px 16px;
  font-family: var(--ff-display); font-size: var(--fs-lg); font-weight: 600; transition: background 0.2s;
}
.create-toggle:hover { background: rgba(var(--gold-rgb), 0.13); }
.create-toggle .ct-ico { font-size: 1.25rem; }
.create-toggle .ct-arrow { margin-left: auto; width: 0; height: 0; border-style: solid; border-width: 6px 0 6px 9px; border-color: transparent transparent transparent var(--gold-dim); transition: transform 0.25s; }
.create-toggle.open { border-radius: 10px 10px 0 0; }
.create-toggle.open .ct-arrow { transform: rotate(90deg); }

#create-form {
  /* Échelle typographique du formulaire — harmonisée (police Inter/QML) */
  /* Aliasés sur la couche générique (:root) — valeurs strictement identiques. */
  --cf-fs-xs: var(--fs-xs); --cf-fs-body: var(--fs-base); --cf-fs-value: var(--fs-md); --cf-fs-ico: var(--fs-xl); --cf-fs-ico-sm: var(--fs-lg);
  padding: 14px; background: rgba(8,18,10,0.6); border: 1px solid var(--border); border-top: none; border-radius: 0 0 10px 10px; }
/* PokerTH clair : le fond du formulaire est code en dur (vert sombre translucide)
   et ne suit pas la palette -> en clair il vire au gris et masque le texte
   var(--text) (noms de presets non actifs, libelle mot de passe). Fond clair force. */
:root[data-theme="pokerth-light"] #create-form { background: rgba(255,255,255,0.62); }

/* En page pleine « Creer une table » (#s-create), le formulaire n'est plus
   colle sous le bouton toggle accordeon de la colonne lobby : on referme donc
   le cadre en haut (contour complet + coins arrondis), sinon le bord superieur
   apparait coupe juste sous le header. Deux ids => bat la regle de base. */
#s-create #create-form { border-top: 1px solid var(--border); border-radius: var(--r-bar); }

/* ── PokerTH clair : corrections de contraste (clair uniquement) ──
   Plusieurs elements gardent des couleurs CLAIRES codees en dur (pensees pour le
   fond sombre) -> illisibles sur fond clair. On corrige ici, sans toucher au JS. */
/* Assistance (force de la main) : le texte est colore inline par le JS selon la force
   (teintes claires). On garde un fond SOMBRE pour cette pastille en clair -> le code
   couleur (gris faible -> vert/rouge fort) reste lisible tel quel. */
/* Ecran d'attente : wp-ready-label/btn (pas de couleur de base) corriges ici ;
   ld-quit/ld-create/wp-ok/wp-hint-admin/wp-need pilotes par variables de theme. */
:root[data-theme="pokerth-light"] .wp-ready-label,
:root[data-theme="pokerth-light"] .wp-ready-btn { color: var(--green); }
/* Siege actif (a parler) : nom/stack attenues a 0.35 (concu pour texte clair sur fond
   sombre). En clair le texte est SOMBRE -> 0.35 = invisible. On remonte l'opacite en
   clair uniquement : leger estompage conserve, mais lisible. */
:root[data-theme="pokerth-light"] .seat.active .seat-name,
:root[data-theme="pokerth-light"] .seat.active .seat-money { opacity: 0.7; }

/* Préréglages */
.cf-presets-label { font-size: var(--cf-fs-xs); letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold-dim); font-weight: 600; margin: 0 2px 8px; }
/* Rangée label + bouton Développer/Réduire du bloc « Style de partie ». */
.cf-style-label-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.cf-style-toggle {
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--gold-dim);
  font-family: inherit; font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 3px 8px; cursor: pointer;
}
.cf-style-toggle:hover { border-color: var(--gold-dim); color: var(--gold); }
.cf-style-toggle .cfs-arr { font-size: var(--cf-fs-xs); line-height: 1; }
.cf-presets { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: 16px; }
.cf-preset {
  flex: 1 1 104px; border: 1.5px solid var(--border); border-radius: var(--r-md); background: var(--inset);
  color: var(--text); cursor: pointer; padding: 11px 6px; text-align: center;
  transition: border-color 0.2s, background 0.2s; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 3px;
}
.cf-preset:hover { border-color: var(--gold-dim); }
.cf-preset.active { border-color: var(--sel,var(--gold)); background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.14); color: var(--cream); box-shadow: 0 0 12px rgba(var(--sel-rgb,var(--gold-rgb)), 0.18); }
.cf-preset .cfp-ico { font-size: var(--cf-fs-ico); line-height: 1.1; }
.cf-preset .cfp-n { font-family: var(--ff-display); font-size: var(--cf-fs-body); font-weight: 600; }
.cf-preset .cfp-d { font-size: var(--cf-fs-xs); color: var(--gold-dim); }

/* ── Rangée Style de partie : grille fixe 3 colonnes (2 rangées logiques :
   rythmes libres / formats pokerth.net), cartes allégées — esprit QML :
   plat, radius 9, bordures discrètes. ⭐ Perso devient une barre fine
   horizontale sous la grille (action de chargement, pas un style). ── */
.cf-presets-style { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 8px; }
.cf-presets-style .cf-preset { padding: 8px 4px; gap: var(--sp-0); }
.cf-presets-style .cf-preset .cfp-ico { font-size: var(--cf-fs-ico); }
.cf-presets-style .cf-preset .cfp-n { font-size: var(--cf-fs-body); }
.cf-presets-style .cf-preset .cfp-d { font-size: var(--cf-fs-xs); }
.cf-preset.cfp-bar { flex-direction: row; align-items: center; justify-content: center; width: 100%; padding: 8px 10px; gap: var(--sp-3); margin-bottom: 16px; }
.cf-preset.cfp-bar .cfp-ico { font-size: var(--cf-fs-ico-sm); line-height: 1; }
.cf-preset.cfp-bar .cfp-n { font-size: var(--cf-fs-body); }
.cf-preset.cfp-bar .cfp-d { font-size: var(--cf-fs-xs); }
.cf-preset.cfp-bar .cfp-d::before { content: '— '; }

/* Curseurs (sliders) Joueurs max / Stack */
.cf-sliders { display: grid; gap: 14px; margin-top: 14px; }
.cf-slider label { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--cf-fs-xs); color: var(--gold-dim); letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: 8px; }
.cf-range-val { font-family: var(--ff-mono); font-size: var(--cf-fs-value); font-weight: 700; color: var(--cream); letter-spacing: 0; }
.cf-num-wrap { display: inline-flex; align-items: center; gap: 5px; }
.cf-range-num {
  width: 6.5em; background: var(--field-bg); border: 1px solid var(--border); border-radius: 4px;
  color: var(--cream); font-family: var(--ff-mono); font-size: var(--fs-md); font-weight: 700;
  padding: 3px 7px; text-align: right; outline: none; letter-spacing: 0; text-transform: none;
  -moz-appearance: textfield;
}
.cf-range-num::-webkit-outer-spin-button, .cf-range-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cf-range-num:focus { border-color: var(--gold); }
.cf-slider label .cf-range-num { width: 4em; }
.cf-slider label .cf-num-wrap .cf-range-num { width: 6.5em; }
.cf-money { color: var(--gold); font-size: var(--cf-fs-value); font-weight: 700; }
.cf-unit { color: var(--gold-dim); font-size: var(--cf-fs-body); font-weight: 600; }
.cf-unit-ico { font-size: var(--cf-fs-ico-sm); }
#cf-players.cf-range-num { width: 4.2em; }
.cf-range { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: var(--r-xs); background: var(--inset); outline: none; cursor: pointer; }
.cf-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--gold); border: 2px solid #1a1408; cursor: pointer; box-shadow: 0 0 7px rgba(var(--gold-rgb), 0.5); transition: transform 0.1s; }
.cf-range::-webkit-slider-thumb:active { transform: scale(1.12); }
.cf-range::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: var(--gold); border: 2px solid #1a1408; cursor: pointer; box-shadow: 0 0 7px rgba(var(--gold-rgb), 0.5); }
.cf-range::-moz-range-track { height: 6px; border-radius: var(--r-xs); background: var(--inset); }
.cf-range:hover::-webkit-slider-thumb { background: var(--gold-hi); }
.cf-range:hover::-moz-range-thumb { background: var(--gold-hi); }

/* Liste des tables : grille + cartes détaillées */
/* Entête « Tables disponibles » : mêmes attributs que les autres entêtes de
   panneau (.g-chat-panel-header) — fond chrome, bordure basse, padding et
   typo identiques. */
.games-col .pane-header {
  padding: 4px 10px;
  background: var(--chrome-tint);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-2xs);
  letter-spacing: 0.15em;
}
.games-scroll { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; overflow: visible; }
/* Barre de filtre des tables (design A : puces arrondies) */
.filter-bar { display: flex; gap: var(--sp-2); flex-wrap: wrap; padding: 0 2px 12px; }
.filter-chip {
  font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 500; letter-spacing: 0.02em;
  background: var(--inset); border: 1px solid var(--border); border-radius: 20px;
  color: var(--text); padding: 6px 13px; cursor: pointer; transition: all 0.15s; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
}
.filter-chip:hover { border-color: var(--gold-dim); color: var(--cream); }
.filter-chip.active { background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.14); border-color: var(--sel,var(--gold)); color: var(--sel,var(--gold)); font-weight: 700; }
.filter-chip .cnt { font-size: var(--fs-2xs); opacity: 0.65; }
/* Compact icon, hidden on desktop (the i18n label already carries the emoji). */
.filter-chip .fc-ic { display: none; }
/* ── Mobile only: V4 compact — one row, equal chips, icons replace labels ── */
@media (max-width: 600px) {
  .filter-bar { flex-wrap: nowrap; gap: var(--sp-2); }
  .filter-chip { flex: 1; min-width: 0; justify-content: center; padding: 7px 6px; gap: var(--sp-1); border-radius: 16px; }
  .filter-chip .fc-ic { display: inline; }      /* show the icon… */
  .filter-chip .fc-ic + .fc-label { display: none; } /* …and hide the word (but not on 'All', which has no icon) */
}
.games-scroll .empty { grid-column: 1 / -1; padding: 32px 10px; }
.game-row.gcard {
  border: 1px solid var(--border); border-radius: 11px; background: var(--inset);
  align-items: stretch; flex-direction: column; gap: 9px; padding: 13px 14px;
}
.game-row.gcard:hover { border-color: var(--gold-dim); background: var(--inset-hi); }
.gcard-main { min-width: 0; }
.game-row.gcard .game-name { white-space: normal; display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; font-size: var(--fs-md); }
.game-row.gcard .game-meta { flex-wrap: wrap; gap: 4px 10px; font-size: var(--fs-xs); }
.game-badge { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.05em; padding: 2px 7px; border-radius: 20px; text-transform: uppercase; white-space: nowrap; }
.game-badge.live   { color: var(--red,#e05050); background: rgba(var(--red-rgb), 0.14); border: 1px solid rgba(var(--red-rgb), 0.4); }
.game-badge.wait   { color: var(--green); background: rgba(var(--green-rgb), 0.15); border: 1px solid rgba(var(--green-rgb), 0.4); }
.game-badge.closed { color: #999; background: var(--inset); border: 1px solid var(--border); }
/* Palettes PokerTH officielles : etat en texte simple colore, dans la ligne meta
   (parite QML — pas de pilule) : running #FF6D00/#BF360C · open #4CAF50/#2E7D32. */
:root[data-theme^="pokerth"] .game-badge {
  background:none; border:none; padding:0; border-radius:0;
  font-size:inherit; text-transform:none; letter-spacing:0; font-weight:600;
}
:root[data-theme="pokerth"] .game-badge.live { color:#FF6D00; }
:root[data-theme="pokerth"] .game-badge.wait { color:#4CAF50; }
:root[data-theme="pokerth"] .game-badge.closed { color:#EF5350; }
:root[data-theme="pokerth-light"] .game-badge.live { color:#BF360C; }
:root[data-theme="pokerth-light"] .game-badge.wait { color:#2E7D32; }
:root[data-theme="pokerth-light"] .game-badge.closed { color:#C62828; }
.game-seats { display: flex; gap: 3px; margin-top: 8px; flex-wrap: wrap; }
.seat-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--inset); border: 1px solid var(--border); }
.seat-dot.on { background: var(--gold); border-color: var(--gold); box-shadow: 0 0 5px rgba(var(--gold-rgb), 0.5); }
.gcard-btns { display: flex; gap: var(--sp-3); align-items: center; }
.gcard-caret { flex:0 0 auto; background:none; border:none; cursor:pointer; color:var(--gold-dim);
  font-size:var(--fs-md); line-height:1; padding:4px 6px; border-radius:var(--r-sm); transition:color .12s, background .12s; }
.gcard-caret:hover { color:var(--gold); background:var(--inset-hi); }
/* Flèche « voir les joueurs » sur les lignes de partie : redondante avec le
   panneau INFOS DE PARTIE dans le lobby normal → masquée. Réaffichée uniquement
   quand je suis connecté à une table en attente du démarrage (#s-lobby.lobby-waiting),
   où le panneau Infos n'est plus au premier plan et où j'ai besoin de voir qui a rejoint. */
#s-lobby:not(.lobby-waiting) .gcard-caret { display: none; }
#s-lobby:not(.lobby-waiting) .game-players { display: none; }
/* Boutons façon maquette v3 : Rejoindre en vert (extensible) + œil compact */
.game-row.gcard .btn-join {
  flex: 1;
  border: 1.5px solid var(--green);
  background: rgba(var(--green-rgb), 0.12);
  color: var(--green);
  border-radius: 8px;
  padding: var(--sp-4);
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: var(--fs-base);
}
.game-row.gcard .btn-join:hover { background: rgba(var(--green-rgb), 0.28); }

/* Liste dépliable des joueurs d'une table (clic sur la carte) */
.game-players {
  margin: -7px 0 10px;
  padding: 9px 12px 11px;
  background: var(--inset);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 12px 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  animation: gpReveal 0.18s ease;
}
.game-players[hidden] { display: none; }
.gp-player {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  max-width: 100%;
  padding: 4px 9px;
  background: var(--inset-hi);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  line-height: 1.2;
}
.gp-player .gp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gp-player.gp-pending { opacity: 0.55; }
.cc-flag.gp-flag { width: 18px; height: auto; border-radius: 2px; flex: 0 0 auto; }
.gp-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--inset);
  font-size: var(--fs-lg);
  line-height: 1;
}
.gp-av.letter { font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }
.gp-av.has-pth-avatar { background: rgba(0,0,0,0.2); padding: 0; overflow: visible; }
.gp-empty { opacity: 0.6; font-size: var(--fs-sm); padding: 2px 0; }
@keyframes gpReveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.game-row.gcard .btn-watch {
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--inset);
  color: var(--text);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
}
.game-row.gcard .btn-watch:hover { border-color: var(--gold-dim); color: var(--gold); background: var(--inset-hi); }

/* Mobile (cards stacked): make the Rejoindre / Regarder buttons shorter. */
@media (max-width: 599.98px) {
  .game-row.gcard .btn-join  { padding: 5px 10px; font-size: var(--fs-sm); }
  .game-row.gcard .btn-watch { padding: 5px 12px; font-size: var(--fs-md); }
}

/* ── Téléphone (base) : boutons SOUS la carte, texte lisible ──
   ── Tablette (≥640) : boutons sur le FLANC DROIT, texte un cran plus grand ──
   ── Ordinateur (≥1024) : texte plus grand encore ── */
@media (min-width: 600px) {
  .game-row.gcard { flex-direction: row; align-items: center; gap: 14px; }
  .gcard-main { flex: 1 1 auto; }
  .gcard-btns { flex: 0 0 auto; align-self: center; }
  .game-row.gcard .btn-join { flex: 0 0 auto; font-size: var(--fs-md); }
  .game-row.gcard .game-name { font-size: var(--fs-lg); }
  .game-row.gcard .game-meta { font-size: var(--fs-sm); }
  .create-toggle { font-size: 1.15rem; }
}
@media (min-width: 900px) {
  .game-row.gcard .game-name { font-size: 1.16rem; }
  .game-row.gcard .game-meta { font-size: var(--fs-base); }
  .game-badge { font-size: var(--fs-xs); }
  .game-row.gcard .btn-join { font-size: var(--fs-md); padding: 11px 20px; }
  .game-row.gcard .btn-watch { font-size: 1.2rem; padding: 11px 16px; }
  .create-toggle { font-size: var(--fs-xl); padding: 16px 18px; }
  .seat-dot { width: 10px; height: 10px; }
  #create-form .cf label { font-size: var(--fs-2xs); }
  #create-form .cf input, #create-form .cf select { font-size: var(--fs-md); padding: 7px 9px; }
}

/* ── PWA edge-to-edge: respect notch / status-bar in fullscreen mode ──
   display_override lists "fullscreen" first, so an installed PWA on Android
   may draw under the system status bar. These insets keep the game & lobby
   headers clear of the notch and landscape camera cut-outs. Appended last so
   the longhand padding-* wins over the mobile shorthand `padding:` rules. */
@media (display-mode: fullscreen), (display-mode: standalone) {
  /* standalone ajoute : iOS PWA (apple-mobile-web-app-status-bar-style
     black-translucent) dessine SOUS la barre d'etat -> memes insets.
     Android standalone sans notch : env() = 0, no-op. */
  #s-game .header,
  #s-lobby .header {
    padding-top: max(4px, env(safe-area-inset-top));
    padding-left: max(8px, env(safe-area-inset-left));
    padding-right: max(8px, env(safe-area-inset-right));
  }
}

/* ── Reset button in the create-table form (secondary, paired with Create) ── */
.btn-cf-reset {
  background: transparent;
  color: var(--text-hi);
  border: 1px solid var(--gold-dim);
  border-radius: 2px;
  font-family: var(--ff-display);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  padding: 10px 14px;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: border-color 0.15s, color 0.15s, transform 0.1s;
}
.btn-cf-reset:hover  { border-color: var(--border-hi); color: var(--gold); }
.btn-cf-reset:active { transform: scale(0.98); }

/* ── Barre d'actions du formulaire « Créer une table » ──
   Même forme que les boutons de la barre du bas du lobby (.lobby-footbar .lfb-*) :
   coins arrondis 8 px, ff-display 600. Trois actions alignées :
   Réinitialiser (neutre) · Annuler (retour lobby, rouge doux) · Créer (or, primaire). */
.cf-actions {
  display: flex;
  align-items: stretch;
  gap: var(--sp-4);
  margin-top: 4px;
}
.cf-actions > button {
  flex: 1 1 0; min-width: 0; text-align: center;
  border: 1px solid transparent; border-radius: 8px; padding: 9px 14px;
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--ff-display); font-weight: 600; font-size: var(--fs-md); letter-spacing: 0.02em;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.1s, box-shadow 0.15s;
}
.cf-actions > button:active { transform: scale(0.98); }
/* Réinitialiser — neutre (bordure or atténuée) ; ne s'étire pas (icône seule sur mobile) */
.cf-actions .btn-cf-reset { flex: 0 0 auto; background: transparent; color: var(--text-hi); border-color: var(--gold-dim); }
.cf-actions .btn-cf-reset:hover { border-color: var(--border-hi); color: var(--gold); }
/* Annuler — retour au lobby sans créer ; neutre (palette QML), comme les autres boutons secondaires. */
.cf-actions .btn-cf-cancel { background: transparent; color: var(--text-hi); border-color: var(--gold-dim); }
.cf-actions .btn-cf-cancel:hover { background: var(--inset); border-color: var(--border-hi); }
/* Créer — couleur identique au bouton Créer du lobby (.lfb-create : or/neutre teinté), un peu plus large */
.cf-actions .cf-create-btn { flex-grow: 1.6; background: #2b3444; color: #ffffff; border-color: transparent; }
.cf-actions .cf-create-btn:hover { background: #384252; }
/* Mobile (<600px, canon QML) : la barre passe sur deux lignes. Reset (icône) + Annuler
   restent en haut ; « Créer » — l'action primaire — descend pleine largeur sur
   sa propre ligne, donc jamais tronquée quelle que soit la langue (fr « ＋ Créer
   cette table », de…), et devient une plus grande cible tactile. */
@media (max-width: 599.98px) {
  .cf-actions { flex-wrap: wrap; }
  .cf-actions .cf-create-btn { flex: 1 0 100%; }
}

/* ── Reusable toast (showToast in pokerth.js) ──
   Styled to match the header ••• overflow menu: dark panel, gold-hi hairline
   border, soft drop shadow, Inconsolata. */
.app-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 20px);
  z-index: 950;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  max-width: min(90vw, 360px);
  padding: 8px 16px;
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-sm);
  box-shadow: 0 12px 32px rgba(0,0,0,0.7);
  color: var(--text-hi);
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.app-toast.show { opacity: 1; transform: translate(-50%, 0); }
.app-toast-tick { color: #3fb950; font-weight: 700; }

/* Reset button: full "↺ Réinitialiser" label on tablet/desktop, icon-only on
   phones (<600px, the QML-canon phone/tablet boundary) to leave room for Create.
   The label stays in the DOM (visually hidden) so it remains translated and
   reachable by screen readers; the standalone ↺ is aria-hidden. */
.btn-cf-reset .cf-reset-ico { display: none; }
@media (max-width: 599.98px) {
  .btn-cf-reset { padding: 10px 13px; }
  .btn-cf-reset .cf-reset-ico { display: inline; font-size: var(--cf-fs-ico-sm); line-height: 1; }
  .btn-cf-reset .cf-reset-lbl {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}

/* Error variant of the reusable toast (showToast(msg,{tone:'error'})) —
   orange hairline + icon, e.g. the "game name too long" guard. */
.app-toast--error { border-color: var(--orange); }
.app-toast--error .app-toast-tick { color: var(--orange); }

/* ─── Mobile : confort tactile (v0.2.329) ─── */

/* iOS : pas de menu long-press (save image / loupe / sélection) sur les cartes
   de jeu et les boutons. Le chat et les champs restent sélectionnables. */
.pk-flip, .pk-fold, button, .cf-preset {
  -webkit-touch-callout: none;
}

/* Respecte « réduire les animations » du système (accessibilité + téléphones
   faibles). Les anims en forwards/both atteignent leur état final instantanément
   (cartes distribuées/retournées, jetons posés) ; le timer SVG, piloté en JS,
   n'est pas affecté. Durée ~0 (pas 0) pour que animationend/transitionend
   continuent de se déclencher. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ─── theme-color du navigateur, suivant le thème actif (lue par JS) ─── */
:root { --theme-color: #1d222b; color-scheme: dark; }                             /* thèmes sombres */
:root[data-theme="pokerth-light"] { --theme-color: #eef1f6; color-scheme: light; } /* thème clair    */

/* ─── Téléphones faibles / Linux + accessibilité : couper le backdrop-filter ───
   Le flou de fond (backdrop-filter) est coûteux en GPU. Ici ses seuls usages
   sont des voiles sombres de modale (rgba noir 0.65–0.85), purement décoratifs :
   aucun texte n'en dépend, donc les retirer ne nuit pas à la lisibilité. On les
   coupe quand l'utilisateur demande moins de transparence OU moins d'animations
   (signaux fiables, supportés y compris Firefox/WebKit des téléphones Linux). */
@media (prefers-reduced-transparency: reduce), (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
}


/* ===== Sieges : base neutre =============================================
   DOM neutre (display:contents) = repli « classique » quand aucun pack
   structurel ne s'applique (pack importé avec qmlStruct:false). */
.seat-plate, .seat-info, .seat-foot { display: contents; }

/* (packs web Classic/Chip/Plate/Card/Compact/Bar retirés en 0.3.698 —
   page blanche : les prochains sièges = packs importés style.css + traits.) */


/* ===== Sieges : STRUCTURE COMMUNE QML (html[data-seat-struct="qml"]) ======
   Depuis 0.3.695, TOUS les packs (integres + galerie) partagent cette
   structure — placement, gabarit de boite, self-box — sauf opt-out via le
   trait qmlStruct:false. Chaque pack n'apporte plus que son habillage
   (couleurs, avatar, cadre). Historique :
   Replique du client officiel : boite par joueur, GRILLE 2 colonnes :
   [avatar | 2 cartes] en LIGNE 1, nom + tapis (span 2 col) en LIGNE 2.
   max-width:none !important bat les caps .seat {max-width !important} des
   media-queries (sinon les cartes retombent sous l'avatar -> vertical).
   COULEURS : tokens de palette. Boite = var(--panel) et NON var(--field-bg) :
   --panel est dans PALETTE_TOKENS donc defini par TOUTES les palettes (y
   compris les paquets importes) ; --field-bg n'y est pas et retombait sur le
   vert de :root ("style green casino"). Bordure var(--border), nom var(--text-hi),
   tapis var(--gold)
   herites de la BASE (plus aucune surcharge en dur). La boite suit donc le
   theme PokerTH (claire en PokerTH Light, sombre ailleurs). Cartes injectees
   dans .seat-plate par renderSeats si pack actif : dos adversaires, faces moi. */
html[data-seat-struct="qml"] .seat { max-width: none !important; }
/* GamePlayerBox.qml : dégradé lighter(panel,~18%)→panel (QML : #434c5e→#1d222b),
   radius 6, bordure blanche 6 %, ombre 0 3px (opacité .42), opacity .9.
   color-mix garde la fidélité QML en PokerTH Dark ET suit les autres thèmes. */
html[data-seat-struct="qml"] .seat-plate {
  display: grid; grid-template-columns: auto auto;
  align-items: center; justify-content: center;
  column-gap: 4px; row-gap: 3px; position: relative;
  padding: var(--sp-1); border-radius: var(--r-sm);   /* 4px symétrique : budget hauteur QML */
  /* Degrade EXACT du QML (GamePlayerBox : col600 #394150 eclairci x1.18
     -> col700 #1d222b), FIXE — la plaque ne suit pas le --panel du theme
     de table (le client officiel garde sa plaque ardoise sur tous les
     feutres). */
  background: linear-gradient(180deg, #434c5f, #1d222b);
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.42);
  opacity: 0.9;
  transition: transform 0.18s ease-out;
}
/* AvatarCardRow QML : avatar CARRÉ = hauteur de rangée (box 84 → rangée 40 en
   wide ; box 71 → rangée 43 en narrow/portrait), radius 2, bord 1px col200,
   fond col700 opacité 0.9. Cartes : cardH == hauteur d'avatar, ratio 120:168
   (wide 29×40, narrow 31×43 ≈ largeur totale QML ~121). !important : bat les
   tailles d'avatar des media queries. Tokens surchargeables par thème. */
html[data-seat-struct="qml"] .seat-avatar {
  grid-column: 1; grid-row: 1;
  width: 40px !important; height: 40px !important;
  border-radius: 2px;
  background: var(--seat-avatar-bg, rgba(29, 34, 43, 0.9));
  border: 1px solid var(--seat-avatar-border, rgba(205, 211, 224, 0.9));
}
html[data-seat-struct="qml"] .seat-holecards .pk { width: 29px; height: 40px; font-size: var(--fs-2xs); }
html[data-seat-struct="qml"] .seat-narrow .seat-avatar { width: 43px !important; height: 43px !important; }
html[data-seat-struct="qml"] .seat-narrow .seat-holecards .pk { width: 31px; height: 43px; }
/* QML : pas de bord vert (self) ni or (au tour) sur l'avatar — le tour est
   signalé par le PlayerTurnGlow de la boîte. Halo/anneau neutralisés. */
html[data-seat-struct="qml"] .seat.me .seat-avatar,
html[data-seat-struct="qml"] .seat.active .seat-avatar {
  border-color: var(--seat-avatar-border, rgba(205, 211, 224, 0.9));
  box-shadow: none;
  animation: none !important;
}
html[data-seat-struct="qml"] .seat-holecards { grid-column: 2; grid-row: 1; display: flex; gap: var(--sp-1); flex: none; }
/* PlayerActionBadge QML : centré sur la rangée de hole-cards (x/y = cardsCenter),
   hauteur 18, radius 9, padding H 7, texte #eaf1ff 12px bold, pop à l'apparition
   (0.6→1.12→1.0). Le badge est injecté DANS .seat-holecards par renderSeats. */
html[data-seat-struct="qml"] .seat-holecards { position: relative; }
html[data-seat-struct="qml"] .seat-holecards .seat-action-badge {
  position: absolute; top: 50%; left: 50%;
  height: 18px; box-sizing: border-box;
  display: inline-flex; align-items: center;
  padding: 0 7px; border-radius: var(--r-md);
  font-size: 12px; font-weight: 700; letter-spacing: 0;
  color: #eaf1ff;
  box-shadow: none;
  z-index: 18;
  transform: translate(-50%, -50%);
  animation: seatBadgePop 0.23s ease-out;
}
@keyframes seatBadgePop {
  0%   { transform: translate(-50%, -50%) scale(0.6); }
  48%  { transform: translate(-50%, -50%) scale(1.12); }
  100% { transform: translate(-50%, -50%) scale(1); }
}
/* Wide (par défaut) : nom à GAUCHE ligne 1, tapis accent à DROITE ligne 2
   (infoBar 2 lignes du QML : nom 15px DemiBold #eff1f5 ls .3 / $stack bold). */
html[data-seat-struct="qml"] .seat-info {
  grid-column: 1 / -1; grid-row: 2;
  display: flex; flex-direction: column; gap: 0;
  align-items: stretch; min-width: 0;
}
html[data-seat-struct="qml"] .seat-name {
  max-width: 106px; text-align: left;
  font-size: 15px !important;               /* QML wide : 15px DemiBold */
  font-weight: 600; letter-spacing: 0.3px;
  line-height: 16px;   /* serré : hauteur de boîte QML (wide 84) */
  color: #eff1f5; /* col100 QML */
}
html[data-seat-struct="qml"] .seat-money { text-align: right; font-size: 15px !important; font-weight: 700; line-height: 16px; color: #E3C800; font-family: var(--ff-display); } /* accent or QML, 15px bold */
/* Wide (infoBar QML) : ligne 2 = drapeau 22×15 en bas-GAUCHE + stack à droite. */
html[data-seat-struct="qml"] .seat-info-row2 {
  display: flex; align-items: flex-end; gap: var(--sp-2); min-width: 0;
}
html[data-seat-struct="qml"] .seat-info-row2 .seat-money { margin-left: auto; }
html[data-seat-struct="qml"] .seat-info-row2 .seat-flag {
  position: static; filter: none; animation: none; line-height: 0; pointer-events: none;
}
html[data-seat-struct="qml"] .seat-info-row2 .seat-flag .cc-flag { width: 22px !important; height: 15px !important; }
/* Non-wide (hauteur scalée < 76 ou portrait) : « nom · tapis » sur UNE ligne. */
html[data-seat-struct="qml"] .seat-narrow .seat-info { flex-direction: row; align-items: baseline; justify-content: space-between; gap: var(--sp-2); }
html[data-seat-struct="qml"] .seat-narrow .seat-name { max-width: 62px; font-size: 12px !important; line-height: 13px; }
html[data-seat-struct="qml"] .seat-narrow .seat-money { font-size: 12px !important; line-height: 13px; }
/* Desktop : texte des sieges un peu plus discret (les boites sont deja scalees par boxScale). */
@media (min-width: 900px) and (hover: hover) and (pointer: fine) {
  /* Nom/tapis : tailles QML fixes (15/12 px) définies dans la base — plus
     d'override desktop, le boxScale de l'ellipse fait la mise à l'échelle. */
  html[data-seat-struct="qml"] .seat-action-label { font-size: var(--fs-2xs) !important; }
}
/* Joueur au tour : boîte « soulevée » scale 1.04 (playerBox.scale QML). Le
   cadre or est porté par ::after (PlayerTurnGlow) — la bordure blanche 6 % de
   la boîte reste visible dessous, comme dans le client officiel. */
html[data-seat-struct="qml"] .seat.active .seat-plate {
  transform: scale(1.04);
  opacity: 1;
}
/* PlayerTurnGlow QML, pour TOUTES les boîtes au tour (self inclus — le QML
   partage le même composant) : cadre or #FFD54A 1 px à −2 px du bord
   (anchors.margins -2, radius 6) + halo doux, pulsation 0.65↔1.0 en 1.5 s.
   iOS-safe : box-shadow STATIQUE sur le pseudo-élément, seule l'OPACITÉ est
   animée (mémo thermique). Tokens surchargeables par thème :
   --turn-glow (cadre) et --turn-glow-halo (halo). */
html[data-seat-struct="qml"] .seat.active .seat-plate::after {
  /* FORMULE de surbrillance adaptative : le cadre suit la FORME de la plate
     du pack actif (border-radius: inherit) et chaque pack peut ajuster
     l'écart (--turn-glow-inset), le rayon (--turn-glow-radius) et le plan
     (--turn-glow-z : passer sous un avatar débordant, qui porte alors son
     propre anneau). Défauts = comportement QML historique. */
  content: ""; position: absolute;
  inset: var(--turn-glow-inset, -2px);
  border-radius: var(--turn-glow-radius, inherit);
  border: 1px solid var(--turn-glow, #FFD54A);
  box-shadow: 0 0 14px 2px var(--turn-glow-halo, rgba(255, 213, 74, 0.55));
  pointer-events: none; z-index: var(--turn-glow-z, 10); will-change: opacity;
  animation: turnGlowPulse 1.5s ease-in-out infinite;
}
@keyframes turnGlowPulse { 0%, 100% { opacity: 0.65; } 50% { opacity: 1; } }
/* PlayerWinnerOverlay QML : cadre or #FFD700 3px + halo autour de la boîte du
   gagnant (ne couvre pas les cartes), badge « WINNER » pilule (h 16, radius 8,
   fond #0d3d0d, bord/texte or 9px bold) à 6px AU-DESSUS de la boîte —
   au-dessous (.winner-below) pour la boîte la plus haute (TC portrait).
   Défini APRÈS le turn glow : à showdown, la règle winner l'emporte sur
   ::after. Tokens thème : --winner-frame / --winner-halo / --winner-badge-bg. */
html[data-seat-struct="qml"] .seat.winner .seat-plate { opacity: 1; }
html[data-seat-struct="qml"] .seat.winner .seat-plate::after {
  content: ""; position: absolute;
  inset: var(--winner-frame-inset, var(--turn-glow-inset, -2px));
  border-radius: var(--winner-frame-radius, inherit); /* forme du pack */
  border: 3px solid var(--winner-frame, #FFD700);
  box-shadow: 0 0 16px 2px var(--winner-halo, rgba(255, 215, 0, 0.6));
  pointer-events: none; z-index: var(--winner-frame-z, 19);
  animation: none; opacity: 1;
}
html[data-seat-struct="qml"] .seat-winner-badge {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(100% + 6px);
  height: 16px; box-sizing: border-box;
  display: inline-flex; align-items: center;
  padding: 0 6px; border-radius: 8px;
  background: var(--winner-badge-bg, #0d3d0d);
  border: 1px solid var(--winner-frame, #FFD700);
  color: var(--winner-frame, #FFD700);
  font-family: var(--ff-display); font-size: 9px; font-weight: 700;
  letter-spacing: 0.04em; white-space: nowrap;
  z-index: 30; pointer-events: none;
}
html[data-seat-struct="qml"] .seat.winner-below .seat-winner-badge { bottom: auto; top: calc(100% + 6px); }
/* QML : le badge d'action est masqué pendant l'état gagnant (visible: !isWinner). */
html[data-seat-struct="qml"] .seat.winner .seat-action-badge,
html[data-seat-struct="qml"] .seat.winner .seat-action-label { display: none; }
/* PlayerTimeoutBar QML (bloc F) : 44×9, track #0e1a30 bordé blanc 55 %,
   remplissage #4070D0 (self #6E9CEC), radius pilule, centrée sur les cartes à
   l'emplacement du badge d'action. S'AJOUTE au cadre rectangulaire décomptant
   (conservé). Tokens thème : --timeout-track / --timeout-fill(-self). */
html[data-seat-struct="qml"] .seat-timeout-bar {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 9px; box-sizing: border-box;
  border-radius: 5px;
  background: var(--timeout-track, #0e1a30);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  overflow: hidden;
  z-index: 18; pointer-events: none;
}
html[data-seat-struct="qml"] .seat-timeout-bar .stb-fill {
  height: 100%;
  border-radius: 4px;
  background: var(--timeout-fill, #4070D0);
  transition: width 0.9s linear;
}
html[data-seat-struct="qml"] .seat-timeout-bar.me .stb-fill { background: var(--timeout-fill-self, #6E9CEC); }
/* ── Bandeau self QML (GamePlayerSelfBox.topStrip) ─────────────────────────
   Strip 18 px à 6 px AU-DESSUS de la self-box : badge d'action aligné à
   DROITE (hPadding 16 → padding 0 8px), barre de timeout 56×7 centrée
   horizontalement, mise (BetChip) à gauche de l'indicateur visible —
   badge : bord à bord + 8 px ; barre : 50 % + 28 + 8 px du bord droit. */
html[data-seat-struct="qml"] .seat.me .seat-self-strip {
  position: absolute; left: 0; right: 0;
  bottom: calc(100% + 6px);
  height: 18px;
  display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-3);
  pointer-events: none; z-index: 26;
}
html[data-seat-struct="qml"] .seat.me .seat-self-strip .seat-action-badge {
  position: static; top: auto; left: auto; transform: none;
  height: 18px; box-sizing: border-box;
  display: inline-flex; align-items: center;
  padding: 0 8px; border-radius: var(--r-md);
  font-size: 12px; font-weight: 700; letter-spacing: 0;
  color: #eaf1ff; box-shadow: none;
  animation: stripPop 0.23s ease-out;
}
@keyframes stripPop { 0% { scale: 0.6; } 48% { scale: 1.12; } 100% { scale: 1; } }
/* Barre self : 56×7 (QML), centrée horizontalement dans le strip. */
html[data-seat-struct="qml"] .seat.me .seat-self-strip .seat-timeout-bar {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 56px; height: 7px; border-radius: 4px;
}
/* Mise self : visible dans le strip (annule le display:none du siège self),
   en flux, sans positionnement betside. Quand seule la barre est visible,
   elle se cale à gauche de celle-ci (betRightMargin QML). */
html[data-seat-struct="qml"] .seat.me .seat-self-strip .seat-bet {
  display: inline-flex; position: static; transform: none; margin: 0;
}
html[data-seat-struct="qml"] .seat.me .seat-self-strip.has-tb .seat-bet {
  margin-right: calc(50% + 36px);
}
/* ── Bandeau « cartes a decouvert » (.seat-open-strip) ─────────────────────
   Des que les hole-cards d'un siege sont face visible (showdown, spectateur,
   entrainement offline), le badge d'action et la barre de decompte quittent
   la rangee de cartes pour ce bandeau, 4 px AU-DESSUS de la box — ou 4 px en
   DESSOUS (.below) pour les sieges hauts, comme le badge winner. Aucune
   surcouche ne recouvre donc jamais une carte lisible.
   Regles posees APRES le bloc timeout-bar : specificite egale, on gagne. */
.seat-open-strip {
  position: absolute; left: 0; right: 0;
  bottom: calc(100% + 4px);
  height: 16px;
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  pointer-events: none; z-index: 26;
}
.seat-open-strip.below { bottom: auto; top: calc(100% + 4px); }
.seat-open-strip .seat-action-badge {
  position: static; top: auto; left: auto; transform: none;
  height: 16px; box-sizing: border-box;
  display: inline-flex; align-items: center;
  padding: 0 7px; border-radius: var(--r-md);
  font-size: 11px; font-weight: 700; letter-spacing: 0;
  color: #eaf1ff; box-shadow: none;
  animation: stripPop 0.23s ease-out;
}
.seat-open-strip .seat-timeout-bar {
  position: static; top: auto; left: auto; transform: none;
  width: 44px; height: 7px; border-radius: 4px;
}
/* Puck self : HORS du siège — ancre QML exacte du GamePlayerSelfBox
   (anchors.left = bord droit de la box + 6, aligné au haut). !important
   requis : les règles betside-* arrivent PLUS BAS dans le fichier à
   spécificité égale et remettaient le puck SUR les cartes du self. */
html[data-seat-struct="qml"] .seat.me .seat-pucks {
  left: calc(100% + 6px) !important; right: auto !important;
  top: 0 !important; bottom: auto !important; transform: none !important;
}
/* Self au tour : cadre du PlayerTurnGlow un peu plus épais (borderWidth 2 QML). */
html[data-seat-struct="qml"] .seat.me.active .seat-plate::after { border-width: 2px; }
/* Couché : 0.72 ; éliminé : la base gère déjà l'estompe (transition QML 250ms). */
html[data-seat-struct="qml"] .seat { transition: opacity 0.25s ease-out; }
html[data-seat-struct="qml"] .seat.folded { opacity: 0.72; }
/* Mise (pack PokerTH) : icône jeton à gauche du montant, comme le BetChip du
   client officiel (chipStack.svg). On garde la pastille de base (fond sombre,
   montant crème) et on préfixe juste le jeton PokerTH. */
/* BetChip QML : icône chipStack.svg 20×20 + « $X » 14px bold #f0f0f0,
   espacement 2, SANS pastille de fond (le composant officiel n'en a pas).
   Pop 0.5→1.15→1.0 via la propriété `scale` (indépendante du transform de
   positionnement betside-*). Icône surchargeable par thème (--bet-chip-img). */
html[data-seat-struct="qml"] .seat-bet {
  display: inline-flex; align-items: center; gap: var(--sp-0);
  padding: 0; background: none; border: none;
  color: #f0f0f0; font-family: var(--ff-display);
  font-size: 14px !important; font-weight: 700;
  animation: betChipPop 0.24s ease-out;
}
html[data-seat-struct="qml"] .seat-bet::before {
  content: ""; width: 20px; height: 20px; flex: none;
  background: var(--bet-chip-img, url('/pucks/chipStack.svg')) center / contain no-repeat;
}
@keyframes betChipPop { 0% { scale: 0.5; } 46% { scale: 1.15; } 100% { scale: 1; } }
/* Mise HORS de la boîte (packs PokerTH) : la pastille jeton+montant est posée
   sur le côté de la box, côté calculé en JS (classe betside-* sur .seat).
   .seat-bet devient absolu (ancré à .seat = la box), sorti du flux colonne. */
html[data-seat-struct="qml"] .seat[class*="betside-"] .seat-bet {
  position: absolute; z-index: 6; margin: 0;
}
html[data-seat-struct="qml"] .seat.betside-r .seat-bet { left: calc(100% + var(--seat-bet-gap-r, 8px)); top: 50%; transform: translateY(-50%); }
html[data-seat-struct="qml"] .seat.betside-l .seat-bet { right: calc(100% + var(--seat-bet-gap-l, 8px)); top: 50%; transform: translateY(-50%); }
html[data-seat-struct="qml"] .seat.betside-t .seat-bet { bottom: calc(100% + var(--seat-bet-gap-t, 7px)); left: 50%; transform: translateX(-50%); }
html[data-seat-struct="qml"] .seat.betside-b .seat-bet { top: calc(100% + var(--seat-bet-gap-b, 7px)); left: 50%; transform: translateX(-50%); }
/* Self : sa mise est dans la barre d'action -> pas de jeton de siège (officiel). */
html[data-seat-struct="qml"] .seat.me .seat-bet { display: none; }

/* Pucks D/SB/BB (packs PokerTH) : sortis de l'avatar (JS), posés sur le CÔTÉ de
   la boîte (même betSide que le jeton), un peu plus bas pour ne pas chevaucher la
   mise. On remet à plat le positionnement coin-avatar des chips (qui utilise
   !important dans les media-queries) et on les met en ligne. */
html[data-seat-struct="qml"] .seat-pucks {
  position: absolute; z-index: 6; display: flex; gap: var(--sp-0); align-items: center;
  pointer-events: none;
}
html[data-seat-struct="qml"] .seat-pucks .dealer-chip,
html[data-seat-struct="qml"] .seat-pucks .blind-chip {
  position: static !important; top: auto !important; right: auto !important;
  bottom: auto !important; left: auto !important; margin: 0 !important;
  width: 32px !important; height: 32px !important;   /* BlindButtonImage QML 32×32 */
}
/* Côtés (betSide left/right) : puck SOUS la mise. Formule universelle :
   ancré sur le CENTRE DE LA MISE (50%) + dégagement (--seat-bet-clearance,
   36px = demi-mise + demi-puck + marge) -> aucun chevauchement quelle que
   soit la hauteur de la boîte (gabarit QML 84px, pilule 44px, etc.).
   Surcharge possible par pack : --seat-pucks-top. */
html[data-seat-struct="qml"] .seat.betside-r .seat-pucks { left: calc(100% + var(--seat-bet-gap-r, 8px)); top: var(--seat-pucks-top, calc(50% + var(--seat-bet-clearance, 36px))); transform: translateY(-50%); }
html[data-seat-struct="qml"] .seat.betside-l .seat-pucks { right: calc(100% + var(--seat-bet-gap-l, 8px)); top: var(--seat-pucks-top, calc(50% + var(--seat-bet-clearance, 36px))); transform: translateY(-50%); }
/* Haut/bas : puck aligné à DROITE, 6px du bord de la boîte (QML), même bande
   verticale que la mise (centre puck 32 ≈ centre mise 20 posée à 7px). */
html[data-seat-struct="qml"] .seat.betside-t .seat-pucks { bottom: calc(100% + 1px); right: 6px; left: auto; }
html[data-seat-struct="qml"] .seat.betside-b .seat-pucks { top: calc(100% + 1px); right: 6px; left: auto; }
html[data-seat-struct="qml"] .seat-timer-badge { display: none; }
/* Countdown RECTANGULAIRE (style pokerth) : cadre depletif autour de la boite,
   remplace l'anneau rond .seat-timer. Couleurs officielles 2.1.1. */
html[data-seat-struct="qml"] .seat-avatar .seat-timer { display: none; }
html[data-seat-struct="qml"] .seat-timer-rect {
  position: absolute; inset: -3px;
  width: calc(100% + 6px); height: calc(100% + 6px);
  pointer-events: none; overflow: visible; z-index: 3;
}
html[data-seat-struct="qml"] .seat-timer-rect .rt-bg  { fill: none; stroke: #0e1a30; stroke-width: 3; vector-effect: non-scaling-stroke; }
html[data-seat-struct="qml"] .seat-timer-rect .rt-arc { fill: none; stroke-width: 3; stroke-linecap: round; vector-effect: non-scaling-stroke; transition: stroke-dashoffset 0.9s linear; }


/* ===== Sieges : packs IMAGE importes (galerie, html[data-seat-img]) =======
   Un pack image = une plaque 9-slice (border-image ; le mot-cle `fill` fait que
   l'image peint AUSSI le fond de la boite) posee sur .seat-plate. Variables
   injectees par theme.mjs (_injectSeatPkg) ; restituees zero-flash par le
   snippet <head>. Meme boite que le pack « Plaque » integre, mais cadre
   graphique au lieu de background/bordure CSS. id non liste = repli Classique.
   Variante « moi » optionnelle (self.*) -> cadre aussi la barre du heros. */
html[data-seat-img] .seat { max-width: none; }
html[data-seat-img] .seat-plate {
  /* structure = grille QML (data-seat-struct) ; ici seulement le CADRE 9-slice */
  position: relative;
  padding: var(--seat-pkg-pad, 6px 12px);
  border-style: solid; border-color: transparent;
  border-width: var(--seat-pkg-width, 15px);
  border-image-source: var(--seat-pkg-img);
  border-image-slice: var(--seat-pkg-slice, 34%) fill;
  border-image-width: var(--seat-pkg-width, 15px);
  border-image-repeat: stretch;
}
html[data-seat-img] .seat-name { text-align: left; max-width: 88px; }
html[data-seat-img] .seat-foot {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: 3px;
}
html[data-seat-img] .seat.active .seat-plate {
  box-shadow: 0 0 0 1px var(--gold), 0 0 16px rgba(var(--gold-rgb), 0.45);
}
html[data-seat-img] .seat-timer-badge { display: none; }
/* Variante « moi » : la barre du heros recoit le meme cadre (self.* fourni). */
html[data-seat-img-self] .player-bar {
  border-style: solid; border-color: transparent;
  border-width: var(--seat-pkg-self-width, 15px);
  border-image-source: var(--seat-pkg-self-img);
  border-image-slice: var(--seat-pkg-self-slice, 34%) fill;
  border-image-width: var(--seat-pkg-self-width, 15px);
  border-image-repeat: stretch;
}
@media (max-width: 600px) {
  html[data-seat-img] .seat-name { max-width: 46px; font-size: var(--fs-2xs); }
  html[data-seat-img] .seat-money { font-size: var(--fs-2xs); }
  html[data-seat-img] .seat-foot { gap: var(--sp-1); margin-top: 2px; }
}


/* ════════════════════════════════════════════════════════════════════════
   FENETRES FLOTTANTES — chat / journal / reactions deplacables & redimension-
   nables. La classe .floating-win est posee par le JS UNIQUEMENT au-dessus du
   seuil (>= 900 px ; chat = souris/pointer:fine en plus). En dessous, aucun de
   ces styles ne s'applique : les panneaux restent en bandeau pleine largeur.
   Position/taille pilotees en inline par le JS (left/top/width/height).
   ════════════════════════════════════════════════════════════════════════ */
#g-chat-panel.floating-win,
#lobby-chat-panel.floating-win,
#g-log-panel.floating-win,
#g-reaction-panel.floating-win,
#hands-card-inner.floating-win {
  border: 1px solid var(--gold-dim);
  border-radius: var(--r-bar);
  box-shadow: 0 14px 36px rgba(0,0,0,0.62);
  overflow: hidden;            /* coins arrondis nets + borne les poignees */
}
/* Fenêtre Combinaisons alignée sur les autres fenêtres flottantes */
#hands-card-inner.floating-win {
  position: fixed !important;   /* indispensable pour _placeWin/drag (l'overlay ne le centre plus) */
  padding: 0; border-top-width: 1px; max-width: none; max-height: none;
  display: flex; flex-direction: column; background: var(--modal-bg);
  z-index: 201;
}
/* Aucun palier de taille ici : l'echelle du contenu est assuree UNIQUEMENT par
   le zoom generique des fenetres flottantes (.win-zoom / --wz), continu et
   recalcule a chaque mouvement du redimensionnement — comme le chat, le journal
   et les reactions. Empiler des paliers discrets par-dessus ce zoom produisait
   une « marche d'escalier » : les seuils se comparaient a offsetWidth (largeur
   EXTERIEURE) alors que le contenu est rendu en coordonnees locales divisees
   par z, si bien qu'un redimensionnement diagonal laissait la place locale
   quasi constante (~380 px) tout en faisant sauter la typo trois fois. */
#hands-card-inner.floating-win .hands-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch; padding: 10px 12px;   /* = .chat-msgs */
}
/* Chat du lobby flottant : la zone messages remplit la fenetre (annule le
   max-height:120px inline du mode accroche). */
#lobby-chat-panel.floating-win .chat-msgs { max-height: none !important; flex: 1 1 auto; min-height: 0; }
/* La barre de titre devient la poignee de deplacement. */
.floating-win .g-chat-panel-header,
.floating-win .react-panel-title { cursor: move; touch-action: none; -webkit-user-select: none; user-select: none; }
.floating-win .g-chat-panel-header.win-dragging,
.floating-win .react-panel-title.win-dragging { cursor: grabbing; }
/* Le resize vertical historique (bandeau) ne sert plus en mode flottant. */
.floating-win .chat-resize-handle { display: none !important; }
/* Reactions : la grille remplit la fenetre, defile, et s'adapte a SA largeur
   (et non plus a celle de l'ecran) via auto-fit. */
#g-reaction-panel.floating-win { display: flex; flex-direction: column; }
#g-reaction-panel.floating-win .react-grid {
  grid-template-columns: repeat(auto-fit, minmax(44px, 1fr));
  max-width: none; margin: 0;
  flex: 1 1 auto; min-height: 0; overflow: auto;
  /* Téléphone (<600px) : le média impose max-height:88px (~2 lignes) à .react-grid.
     En fenêtre flottante on l'annule pour que la grille remplisse la fenêtre et
     défile normalement (comme desktop/tablette où ce plafond n'existe pas). */
  max-height: none;
}
/* Taille des émojis (et du compteur) pilotée par la case calculée en JS
   (_fitReactGrid, variable --react-cell) : les glyphes grossissent/rétrécissent
   avec la fenêtre. Repli 44px si la variable n'est pas encore posée. */
#g-reaction-panel.floating-win .react-grid .react-btn {
  font-size: calc(var(--react-cell, 44px) * 0.55);
}
#g-reaction-panel.floating-win .react-grid .react-btn .rc {
  font-size: calc(var(--react-cell, 44px) * 0.17);
}
/* 8 poignees de redimensionnement (bords + coins), injectees en JS.
   Transparentes : seul le curseur signale la zone. Placees sur les bords
   interieurs car le panneau est en overflow:hidden. */
.win-rsz { position: absolute; z-index: 6; touch-action: none; }
.win-rsz-n  { top: 0; left: 12px; right: 12px; height: 6px;  cursor: ns-resize; }
.win-rsz-s  { bottom: 0; left: 12px; right: 12px; height: 6px;  cursor: ns-resize; }
.win-rsz-e  { right: 0; top: 12px; bottom: 12px; width: 6px;  cursor: ew-resize; }
.win-rsz-w  { left: 0; top: 12px; bottom: 12px; width: 6px;  cursor: ew-resize; }
.win-rsz-ne { top: 0; right: 0; width: 13px; height: 13px; cursor: nesw-resize; }
.win-rsz-nw { top: 0; left: 0; width: 13px; height: 13px; cursor: nwse-resize; }
.win-rsz-se { bottom: 0; right: 0; width: 18px; height: 18px; cursor: nwse-resize; }
/* Grip visible du coin bas-droit (demande narmod 2026-07-19) : hachures
   diagonales classiques dans un triangle, or discret, plus frappe au survol.
   La zone SE passe de 13 a 18 px (plus facile a attraper). Les autres bords
   restent des zones invisibles (comportement OS standard). */
.win-rsz-se::after { content: ''; position: absolute; right: 3px; bottom: 3px; width: 13px; height: 13px;
  background: repeating-linear-gradient(-45deg, transparent 0 3px, var(--gold-dim, #b09a00) 3px 5px);
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  opacity: .8; pointer-events: none; transition: opacity .12s; } /* .55->.8 + 11->13 px : plus lisible sur fond clair (demande narmod 2026-07-19) */
.win-rsz-se:hover::after, .win-rsz-se:active::after { opacity: 1; }
.win-rsz-sw { bottom: 0; left: 0; width: 13px; height: 13px; cursor: nwse-resize; }
.win-resizing, .win-resizing * { -webkit-user-select: none; user-select: none; }


/* ════════════════════════════════════════════════════════════════════════
   Ouverture EN BANDEAU + detachement au 1er drag/resize : geree cote JS
   (_attachFloatControls / _ensureFloating). Les styles .floating-win et
   .win-rsz sont definis plus haut (v0.2.385) et s'appliquent au detachement.
   ════════════════════════════════════════════════════════════════════════ */

/* Bouton "reset des fenetres" du header : visible seulement tablette + desktop.
   Selecteur sur-specifie (#s-game .header .btn-sm.win-reset-only) pour battre
   `.header .btn-sm` (base) et `#s-game .header .btn-sm` (@media max-740) qui
   forcaient sinon display:inline-flex partout, mobile compris. */
#s-game .header .btn-sm.win-reset-only { display: none; }
@media (min-width: 900px) and (min-height: 600px) { #s-game .header .btn-sm.win-reset-only { display: inline-flex; } }

/* Bouton reset des fenetres dans le LOBBY : desktop SOURIS uniquement
   (exclu tablette/mobile via hover + pointer:fine), comme le gate du chat lobby. */
#s-lobby .header .btn-sm.win-reset-lobby { display: none; }
@media (min-width: 900px) and (hover: hover) and (pointer: fine) { #s-lobby .header .btn-sm.win-reset-lobby { display: inline-flex; } }






/* ════════════════════════════════════════════════════════════════════════
   Raccourcis clavier discrets dans les boutons d'action — DESKTOP UNIQUEMENT
   (souris : hover + pointeur fin) ; masques sur tablette/telephone tactiles.
   Les touches F / C / R / A (+ Espace pour Call/Check) sont DEJA actives ;
   ceci ne fait que les afficher. Pave encadre en haut a droite, dessine en
   currentColor (s'adapte a la couleur de chaque bouton) et attenue.
   ════════════════════════════════════════════════════════════════════════ */
.act-key {
  display: none;
  position: absolute; top: 3px; right: 4px;
  font-family: var(--ff-mono); font-size: var(--fs-2xs); line-height: 1;
  font-weight: 600; letter-spacing: 0;
  padding: 1px 4px; border: 1px solid currentColor; border-radius: var(--r-xs);
  opacity: 0.4; pointer-events: none;
}
/* Revele : (a) desktop a la souris (hover + pointeur fin), tout de suite */
@media (hover: hover) and (pointer: fine) {
  .btn-action, .btn-pct { position: relative; }
  .act-key { display: inline-block; }
}
/* (b) ou des qu'un clavier physique est detecte (classe posee par le JS) */
body.has-keyboard .btn-action, body.has-keyboard .btn-pct { position: relative; }
body.has-keyboard .act-key { display: inline-block; }
/* Le bouton Tapis est etroit : le badge de touche « A » chevauchait le texte
   (« Tapís »). Le QML n'affiche aucun badge sur les boutons -> on le retire ici. */
.btn-allin .act-key,
.btn-pct .act-key { display: none !important; } /* pas de badge de touche sur Tapis ni bets rapides (parite QML) */

/* iOS Safari : empeche le zoom auto au focus d'un champ (declenche quand
   font-size < 16px). Force a 16px sur tactile uniquement ; le pinch-zoom
   reste actif (viewport intact). .raise-input exclu pour preserver la
   table compacte (slider + boutons 1/3.1/2.Pot disponibles). */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not(.raise-input),
  textarea,
  select { font-size: 16px !important; }
}


/* ── Zoom de la table (boutons +/- en haut a droite) ──────────────────────
   Visible uniquement tablette/desktop. Reduit/re-agrandit #g-table-zone
   (feutre + cartes communes + adversaires) ; max = taille actuelle (1.0). */
.zoom-ctrl {
  position: absolute; top: 8px; right: 8px; z-index: 30;
  display: flex; flex-direction: column; gap: var(--sp-2); /* visible sur tous les appareils */
}
@media (min-width: 900px) and (min-height: 600px) {
  .zoom-ctrl { display: flex; }
}
.zoom-btn {
  width: 30px; height: 30px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; cursor: pointer;
  background: rgba(20, 28, 24, 0.72); color: #e8e8e8;
  border: 1px solid rgba(255, 255, 255, 0.18);
  font-size: 1.2rem; font-weight: 600; line-height: 1;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  transition: background 0.15s, opacity 0.15s;
}
.zoom-btn:hover { background: rgba(40, 52, 46, 0.9); }
.zoom-btn:active { transform: scale(0.94); }
.zoom-btn:disabled { opacity: 0.35; cursor: default; }
/* Boutons ronds posés sur le tapis (chat+emoji haut-gauche, journal haut-droite) */
.g-felt-corner { position:absolute; z-index:30; display:flex; gap:var(--sp-2); }
.g-felt-tl { top:8px; left:8px; }
.g-felt-tr { top:8px; right:8px; }
.g-felt-btn { position:relative; width:34px; height:34px; padding:0; border-radius:50%;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  background:rgba(20,28,24,0.72); color:#e8e8e8; border:1px solid rgba(255,255,255,0.18);
  font-size:var(--fs-lg); line-height:1; -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  transition:background .15s, transform .1s; }
.g-felt-btn:hover { background:rgba(40,52,46,0.9); }
.g-felt-btn:active { transform:scale(0.94); }
.g-felt-btn.active { background:var(--accent,#E3C800); color:#1a1205; border-color:var(--accent,#E3C800); }
/* Bouton emoji grisé quand les réactions sont désactivées (mute) */
.g-felt-btn.muted { opacity:0.4; filter:grayscale(1); }
/* Le zoom passe SOUS le journal (haut-droite) pour ne pas le chevaucher */
.zoom-ctrl { top:50px; }
/* Zoom de table RETIRÉ (demande narmod) : rendu incohérent selon
   navigateur/OS — le placement redevient strictement QML partout.
   🔍/+/↺/− masqués ; ✎ (édition custom, régi par ses propres règles #id)
   et le zoom de cartes restent visibles en permanence. */
/* 🔍 = LOUPE QML (zoomLayer ×2, pan, follow) — visibilité STRICTE 2.1.3 :
   mobile (pointer:coarse) + compact + option tableZoomEnabled, gérée par
   _loupeBtnSync (classe .loupe-avail). Pastille ronde 36 px en bas-droite,
   or quand active (GamePage 2.1.3:2283-2325). +/↺/− restent retirés. */
#g-zoom-in, #g-zoom-reset, #g-zoom-out { display:none !important; }
#g-zoom-toggle { display: none !important; }
#g-zoom-toggle.loupe-avail {
  display: flex !important;
  position: fixed; right: 8px; bottom: 8px; z-index: 200;
  width: 36px; height: 36px; border-radius: 18px;
  background: rgba(0, 0, 0, 0.5); color: #fff;
  border: none; font-size: var(--fs-lg);
}
#g-zoom-toggle.loupe-avail.active {
  background: var(--accent, #E3C800); color: #101010;
}
/* Couche zoomable (parité zoomLayer QML) : mêmes règles de centrage que
   .table-zone ; le transform est posé par _loupeApply (transition 220ms
   OutCubic hors drag). */
#g-zoom-layer { position:absolute; inset:0; display:flex; align-items:center;
  justify-content:center; overflow:visible; will-change:transform; }
.zoom-ctrl .zoom-btn:not(.zoom-toggle) { display:flex; }
.zoom-btn.active { background: var(--accent, #E3C800); color: #1a1205; border-color: var(--accent, #E3C800); }

/* ═══ État « fenêtre ouverte » — convention unique de toute l'app ═══════
   Tout bouton qui a ouvert une fenêtre, un panneau ou un menu reste en or
   tant que celle-ci est visible (registre + observers : _WIN_BTN dans
   pokerth.js). Trois rendus :
     · .win-open           frameless (en-têtes, ☰, ⛶, ⚙/⋮) → icône en or,
                           aucun cadre ajouté (demande narmod : lisible sur
                           les systèmes où l'icône neutre se voit mal)
     · .g-felt-btn/.zoom-btn.win-open  boutons ronds du feutre → aplat or,
                           même rendu que .active (💬 📋 😊 harmonisés)
   Désactivable : Options avancées → body.adv-no-winopen. */
.win-open { color: var(--sel, var(--gold, #E3C800)) !important; }
.g-felt-btn.win-open,
.zoom-btn.win-open {
  background: var(--sel, var(--gold, #E3C800)) !important;
  border-color: var(--sel, var(--gold, #E3C800)) !important;
  color: #1a1205 !important;
}
body.adv-no-winopen .win-open {
  color: inherit !important; background: none !important;
  border-color: transparent !important; box-shadow: none !important;
}

/* -- Bouton "editer le placement" (mode custom) + edition glisser-deposer -- */
#g-seat-edit { display: none; }
html[data-seat-layout="custom"] #g-seat-edit { display: flex; }
#g-seat-edit.active { background: #E3C800; color: #1d222b; border-color: #E3C800; }
html[data-seat-edit="1"] { -webkit-user-select: none; user-select: none; }
html[data-seat-edit="1"] #g-seats .seat[data-pid] { cursor: grab; touch-action: none; outline: 2px dashed rgba(227, 200, 0, 0.75); outline-offset: 2px; border-radius: var(--r-bar); }
html[data-seat-edit="1"] #g-seats .seat.seat-ghost { outline: none; cursor: default; }
#g-seats .seat.seat-dragging { cursor: grabbing; z-index: 50; }
.seat-edit-banner {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%);
  z-index: 60; display: flex; align-items: center; gap: var(--sp-4);
  padding: 8px 12px; border-radius: var(--r-lg); max-width: calc(100vw - 24px);
  background: rgba(20, 28, 24, 0.92); color: #eff1f5;
  border: 1px solid rgba(227, 200, 0, 0.55);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  font-size: var(--fs-md); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}
.seat-edit-banner .seb-hint { opacity: 0.92; }
.seat-edit-banner button {
  border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px;
  padding: 5px 10px; cursor: pointer; font-weight: 600; font-size: var(--fs-base);
  background: rgba(255, 255, 255, 0.08); color: #eff1f5;
}
.seat-edit-banner .seb-done { background: #E3C800; color: #1d222b; border-color: #E3C800; }


/* ── Selecteur d'emoji du chat (desktop / souris) ───────────────────
   Bouton dans la barre de saisie + grille repliable au-dessus. Un clic insere
   l'emoji dans #g-chat-in (envoye tel quel : texte unicode). Mobile -> masque
   (le clavier natif propose deja les emojis). */
.chat-emoji-toggle {
  display: none;            /* desktop (souris) uniquement -- voir media query */
  align-items: center; justify-content: center;
  background: var(--inset); color: var(--cream);
  border: 1px solid var(--border); border-radius: 2px;
  padding: 0 9px; font-size: var(--fs-md); line-height: 1; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .chat-emoji-toggle { display: flex; }
}
.chat-emoji-toggle:hover { background: rgba(var(--gold-rgb), 0.15); border-color: var(--gold-dim); }
.chat-emoji-toggle.active { background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.22); border-color: var(--gold-dim); }
.chat-emoji-panel {
  grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
  gap: var(--sp-0);
  max-height: 80px;
  overflow-y: auto;
  padding: 6px 8px;
  border-top: 1px solid var(--border);
  background: var(--panel);
  flex-shrink: 0;
}
.chat-emoji-btn {
  aspect-ratio: 1; width: 100%;
  background: none; border: none; border-radius: 5px;
  font-size: 1.25rem; line-height: 1; cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.1s ease, background 0.1s;
}
.chat-emoji-btn:hover { background: rgba(var(--gold-rgb), 0.15); transform: scale(1.18); }
.chat-emoji-btn:active { transform: scale(0.9); }

/* ════════════════════════════════════════════════════════════════════════
   PANNEAU MUSIQUE — fenetre flottante globale (accueil + lobby + jeu).
   Deplacable + redimensionnable >= 900px via le systeme de fenetres existant
   (_attachFloatControls + .floating-win). Sous le seuil : feuille fixe en bas
   d'ecran, non deplacable. z-index 900 : au-dessus du jeu, sous les modales
   (9999). Bloc purement additif — aucune regle partagee n'est modifiee.
   ════════════════════════════════════════════════════════════════════════ */
#music-panel {
  position: fixed;
  z-index: 100;
  top: 58px;
  right: 14px;
  width: min(340px, 92vw);
  max-height: min(72dvh, 560px);
  display: none;                 /* bascule en flex par le JS */
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--gold-dim);
  border-radius: var(--r-lg);
  box-shadow: 0 14px 36px rgba(0,0,0,0.62);
  overflow: hidden;              /* coins nets + borne les poignees de resize */
}
.music-panel-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 9px 12px;
  font-size: var(--fs-2xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-dim);
  background: var(--chrome-tint);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  -webkit-user-select: none;
  user-select: none;
}
.music-panel-title > span { display: inline-flex; align-items: center; gap: var(--sp-2); }
.music-panel-close {
  background: none; border: none; color: var(--text);
  cursor: pointer; font-size: var(--fs-md); line-height: 1; padding: 0 2px;
}
.music-body {
  padding: 12px 14px 14px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.music-foot { flex: 0 0 auto; border-top: 1px solid var(--gold-dim); padding: 11px 14px; }
.music-foot-row { display: flex; align-items: center; gap: var(--sp-4); cursor: pointer; color: var(--text); font-size: var(--fs-md); user-select: none; }
.music-foot-lbl { display: inline-flex; align-items: center; }
.music-foot-row input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--gold); cursor: pointer; flex: 0 0 auto; }
.music-empty { color: var(--gold-dim); font-size: var(--fs-base); text-align: center; padding: 18px 4px; }
.music-now { display: flex; flex-direction: column; gap: var(--sp-0); }
.music-now-label { font-size: var(--fs-3xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold-dim); }
.music-now-title { font-size: var(--fs-md); color: var(--text); font-weight: 600; }
.music-transport { display: flex; flex-direction: column; align-items: center; gap: var(--sp-4); }
.music-trow { display: flex; align-items: center; justify-content: center; gap: var(--sp-4); }
.music-tbtn {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1;
  background: var(--field-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 50%;
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, transform 90ms ease;
}
.music-tbtn:active:not([disabled]) { transform: scale(0.94); }
.music-tbtn svg { width: 19px; height: 19px; display: block; pointer-events: none; }
.music-tbtn:hover:not([disabled]) { border-color: var(--gold-dim); color: var(--gold); }
.music-tbtn[disabled] { opacity: 0.4; cursor: default; }
.music-tbtn-main { width: 52px; height: 52px; color: var(--gold); border-color: var(--gold-dim); background: rgba(var(--gold-rgb),0.10); }
.music-tbtn-main svg { width: 25px; height: 25px; }
.music-tbtn.is-active { color: var(--sel,var(--gold)); border-color: var(--sel,var(--gold)); background: rgba(var(--sel-rgb,var(--gold-rgb)),0.16); }
.music-div { width: 1px; align-self: stretch; background: var(--border); margin: 4px 2px; }
.music-vol { display: flex; align-items: center; gap: var(--sp-3); }
.music-vol-ic { flex: 0 0 auto; color: var(--gold-dim); display: inline-flex; }
.music-vol-ic svg { width: 18px; height: 18px; display: block; }
.music-vol-range { flex: 1 1 auto; min-width: 0; accent-color: var(--gold); }
.music-vol-val { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim); min-width: 34px; text-align: right; }
.music-seek-row { display: flex; align-items: center; gap: var(--sp-3); }
.music-seek { flex: 1 1 auto; min-width: 0; accent-color: var(--gold); cursor: pointer; }
.music-seek[disabled] { opacity: 0.45; cursor: default; }
.music-time { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim); min-width: 36px; font-variant-numeric: tabular-nums; }
.music-cur { text-align: right; }
.music-dur { text-align: left; }
/* ── Section « Sons du jeu » en haut du lecteur (visuellement distincte) ── */
.music-gamesnd { border: 1px solid var(--border-hi); background: rgba(var(--gold-rgb),0.06); border-radius: var(--r-bar); padding: 8px 10px; display: flex; flex-direction: column; gap: var(--sp-2); }
.music-gamesnd-hd { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-3xs); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-dim); }
.music-gamesnd-ic { font-size: var(--fs-base); }
.music-gamesnd-row { display: flex; align-items: center; gap: var(--sp-3); }
.music-gs-mute { flex: 0 0 auto; width: 32px; height: 32px; font-size: var(--fs-md); }
.music-gs-range { flex: 1 1 auto; min-width: 0; accent-color: var(--gold); cursor: pointer; }
.music-gs-val { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim); min-width: 34px; text-align: right; font-variant-numeric: tabular-nums; }
.music-gamesnd-row.is-off .music-gs-range { opacity: 0.4; }
.music-gamesnd-row.is-off .music-gs-val { opacity: 0.5; }
/* ── Box jumelle « Lecteur » qui regroupe les commandes musique ── */
.music-player-box { border: 1px solid var(--border-hi); background: rgba(var(--gold-rgb),0.06); border-radius: var(--r-bar); padding: 8px 10px 10px; display: flex; flex-direction: column; gap: var(--sp-4); }
.music-player-hd { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-3xs); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-dim); }
.music-player-ic { font-size: var(--fs-base); }

/* ══ Lecteur « esprit Winamp » — LCD, VU, marquee, playlist (palette de thème) ══ */
.music-lcd {
  border: 1px solid var(--border-hi);
  background: var(--field-bg);
  border-radius: 8px;
  padding: 7px 10px 8px;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.22);
  display: flex; flex-direction: column; gap: var(--sp-1);
}
.music-lcd-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); }
.music-lcd .music-cur {
  font-size: 1.15rem; font-weight: 700; color: var(--gold);
  cursor: pointer; text-align: left; min-width: 0; line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.music-lcd .music-cur:hover { color: var(--sel, var(--gold)); }
.music-vu { display: inline-flex; align-items: flex-end; gap: var(--sp-0); height: 16px; flex: 0 0 auto; }
.music-vu-bar {
  width: 3px; height: 3px; border-radius: 1px;
  background: var(--gold);
  transform-origin: bottom;
  transition: height 90ms linear;
}
.music-marquee { overflow: hidden; white-space: nowrap; }
.music-marquee-txt {
  display: inline-block; font-size: var(--fs-md); color: var(--text); font-weight: 600;
  will-change: transform;
}
.music-marquee.is-scroll .music-marquee-txt { animation: music-mq 9s ease-in-out infinite; }
@keyframes music-mq {
  0%, 12%   { transform: translateX(0); }
  50%, 62%  { transform: translateX(var(--mq-shift, 0)); }
  100%      { transform: translateX(0); }
}
/* Playlist dépliable */
.music-pl-toggle {
  display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  background: var(--field-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 7px 10px; font-size: var(--fs-base); cursor: pointer; text-align: left;
}
.music-pl-toggle:hover { border-color: var(--gold-dim); }
.music-pl-caret { flex: 0 0 auto; color: var(--gold-dim); font-size: var(--fs-xs); }
.music-pl-toggle > span[data-i18n] { flex: 1 1 auto; }
.music-pl-count {
  flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim);
  border: 1px solid var(--border); border-radius: var(--r-pill); padding: 1px 7px;
  font-variant-numeric: tabular-nums;
}
.music-pl {
  list-style: none; margin: 0; padding: var(--sp-1);
  border: 1px solid var(--border); border-radius: var(--r-md);
  max-height: 168px; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-0);
}
.music-pl-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 6px 8px; border-radius: 7px; cursor: pointer;
  color: var(--text); font-size: var(--fs-base);
}
.music-pl-item:hover { background: rgba(var(--gold-rgb), 0.10); }
.music-pl-item.is-cur {
  background: rgba(var(--sel-rgb, var(--gold-rgb)), 0.16);
  color: var(--sel, var(--gold));
}
.music-pl-num { flex: 0 0 auto; width: 1.4em; text-align: right; color: var(--gold-dim); font-variant-numeric: tabular-nums; font-size: var(--fs-sm); }
.music-pl-ttl { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.music-pl-eq { flex: 0 0 auto; color: var(--sel, var(--gold)); font-size: var(--fs-sm); }
.music-pl-move { flex: 0 0 auto; display: inline-flex; flex-direction: column; margin-left: 2px; }
.music-pl-mv { background: none; border: none; color: var(--gold-dim); cursor: pointer; padding: 0; display: inline-flex; line-height: 0.5; }
.music-pl-mv:hover:not([disabled]) { color: var(--gold); }
.music-pl-mv[disabled] { opacity: 0.25; cursor: default; }
.music-pl-mv svg { width: 15px; height: 15px; display: block; }
.music-credit { font-size: var(--fs-xs); color: var(--gold-dim); text-align: center; }
.music-credit a { color: var(--gold-dim); }

/* Balance G/D (lot 2) */
.music-bal { display: flex; align-items: center; gap: var(--sp-3); }
.music-bal-end { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim); width: 12px; text-align: center; font-weight: 700; }
.music-bal-range { flex: 1 1 auto; min-width: 0; accent-color: var(--gold); cursor: pointer; }
/* Mode compact « windowshade » */
.music-shade-row { display: none; }
#music-panel.music-shade .music-player-box { display: none; }
#music-panel.music-shade .music-shade-row { display: flex; align-items: center; gap: var(--sp-3); padding: 2px 0; }
.music-shade-row .music-tbtn { width: 34px; height: 34px; }
.music-shade-row .music-tbtn svg { width: 17px; height: 17px; }
.music-shade-row .music-tbtn-main { width: 40px; height: 40px; }
.music-shade-row .music-tbtn-main svg { width: 21px; height: 21px; }
.music-shade-row .music-marquee { flex: 1 1 auto; min-width: 0; }
.music-shade-btn { margin-left: auto; background: none; border: none; color: var(--text); cursor: pointer; padding: 0 2px; display: inline-flex; align-items: center; line-height: 1; }
.music-shade-btn:hover { color: var(--gold); }
.music-shade-btn svg { width: 16px; height: 16px; display: block; }

/* ── Popover de réglage du son (bouton son du header) ── */
.sound-pop {
  position: fixed; z-index: 1200;
  display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-3);
  width: 210px; box-sizing: border-box;
  padding: 8px 10px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border-hi); border-radius: var(--r-bar);
  box-shadow: 0 8px 26px rgba(0,0,0,0.45);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.sound-pop-mute {
  flex: 0 0 auto; width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); line-height: 1;
  background: var(--field-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; cursor: pointer;
}
.sound-pop-mute:hover { border-color: var(--gold-dim); }
.sound-pop-range { flex: 1 1 auto; min-width: 0; accent-color: var(--gold); cursor: pointer; }
.sound-pop-val { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--gold-dim); min-width: 34px; text-align: right; font-variant-numeric: tabular-nums; }
.sp-row { display: flex; align-items: center; gap: var(--sp-3); }
.sound-pop-ico { flex: 0 0 auto; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-md); opacity: 0.9; }
.sound-pop.is-off .sound-pop-range:not(.sp-music-range) { opacity: 0.4; }
.sound-pop.is-off .sound-pop-val:not(.sp-music-val) { opacity: 0.5; }
.sp-haptic-lbl { flex: 1 1 auto; min-width: 0; font-size: var(--fs-sm); color: var(--text); }
.sp-haptic-cb { flex: 0 0 auto; width: 18px; height: 18px; margin: 0; accent-color: var(--gold); cursor: pointer; }
.music-list { display: flex; flex-direction: column; gap: var(--sp-1); }
.music-row {
  display: flex; align-items: center; gap: var(--sp-4);
  width: 100%; text-align: left;
  padding: 8px 10px;
  background: var(--field-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-md);
  cursor: pointer;
}
.music-row:hover { border-color: var(--gold-dim); }
.music-row.is-current { border-color: var(--gold-dim); background: rgba(var(--gold-rgb),0.08); }
.music-row-ic { flex: 0 0 auto; width: 20px; text-align: center; color: var(--gold); font-size: var(--fs-md); }
.music-row-meta { display: flex; flex-direction: column; min-width: 0; }
.music-row-title { font-size: var(--fs-md); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-row-artist { font-size: var(--fs-xs); color: var(--gold-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-credit { font-size: var(--fs-2xs); line-height: 1.4; color: var(--gold-dim); opacity: 0.85; }
.music-credit a { color: var(--gold-dim); text-decoration: underline; }
.music-sel-label { display: block; font-size: var(--fs-3xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold-dim); margin-bottom: -4px; }
.music-sel-wrap { width: 100%; }
.music-sel-wrap select { width: 100%; }
/* Barre de titre = poignee de deplacement en mode flottant (makeWinDraggable
   pose deja cursor/touch-action inline ; on garde le curseur de prehension). */
.floating-win .music-panel-title { cursor: move; touch-action: none; }
.floating-win .music-panel-title.win-dragging { cursor: grabbing; }
/* En mode flottant, la fenetre pilote sa hauteur (resize) : on libere le plafond. */
#music-panel.floating-win { max-height: none; width: min(340px, 92vw) !important; height: auto !important; }
/* Telephone / petit ecran : feuille fixe en bas, non deplacable. Le JS
   (_winGate=false) n'ajoute jamais .floating-win ici et nettoie les inline. */
@media (max-width: 899px), (max-height: 599px) {
  #music-panel {
    top: auto; bottom: 8px; left: 8px; right: 8px;
    width: auto;
    max-height: min(70dvh, 460px);
    border-radius: 14px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Ranking modal (connect screen) — PokerTH / BBC / WEC.
   Entry: the 🏆 button in #s-connect .corner-links. Content via the
   same-origin /api/ranking relay (see proxy.js). Self-contained so it
   is easy to restyle or move later. All colours via palette tokens.
   ═══════════════════════════════════════════════════════════════════ */
#ranking-modal, #tableranking-modal { position: fixed; inset: 0; z-index: 1200; align-items: center; justify-content: center; pointer-events: none; }
.trk-sub { color: var(--text); opacity: 0.75; font-size: var(--fs-sm); margin-bottom: 10px; }
/* Parité avec les options avancées (#adv-modal) : aucun voile sombre — le jeu /
   le lobby restent visibles derrière et cliquables ; seule la carte capte les
   clics. La carte (fond --modal-bg opaque + ombre portée) reste parfaitement
   lisible sans backdrop. Fermeture par ✕ ou Échap (plus par clic extérieur,
   comme les options avancées). Voir #adv-modal .km-backdrop{display:none}. */
.rk-backdrop { display: none; }
#ranking-modal .rk-card, #tableranking-modal .rk-card { pointer-events: auto; }
#rk-awpop { pointer-events: auto; }
.rk-card {
  position: relative;
  width: min(440px, calc(100vw - 32px));
  max-height: min(80vh, 620px);
  display: flex;
  flex-direction: column;
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-sm);
  box-shadow: 0 16px 50px rgba(0,0,0,0.8);
  padding: 16px 18px 14px;
}
.rk-close { position: absolute; top: 8px; right: 10px; background: none; border: none; color: var(--text); font-size: var(--fs-lg); line-height: 1; cursor: pointer; transition: color 0.15s; }
.rk-close:hover { color: var(--gold); }
.rk-title { font-family: var(--ff-mono); font-size: var(--fs-md); font-weight: 600; letter-spacing: 0.04em; color: var(--text-hi); margin-bottom: 12px; }
.rk-tabs { display: flex; gap: var(--sp-2); margin-bottom: 12px; }
.rk-tab {
  flex: 1; padding: 7px 6px; cursor: pointer;
  background: var(--inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-xs);
  font-family: var(--ff-mono); font-size: var(--fs-sm); letter-spacing: 0.03em;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.rk-tab:hover { border-color: var(--border-hi); color: var(--text-hi); }
.rk-tab.active { background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.18); border-color: var(--sel,var(--gold)); color: var(--sel-hi,var(--gold-hi)); }
.rk-body { flex: 1; min-height: 120px; overflow-y: auto; }
.rk-msg { text-align: center; color: var(--text); opacity: 0.85; padding: 30px 8px; font-size: var(--fs-base); }
.rk-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); font-family: var(--ff-mono); }
.rk-table th { position: sticky; top: 0; background: var(--field-bg); text-align: left; color: var(--gold-dim); font-weight: 600; padding: 5px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.rk-table th.rk-th-sort { cursor: pointer; user-select: none; }
.rk-table th.rk-th-sort:hover { color: var(--gold); }
.rk-table td { padding: 4px 8px; border-bottom: 1px solid rgba(var(--gold-rgb), 0.08); color: var(--text-hi); }
.rk-table tbody tr:hover td { background: rgba(var(--gold-rgb), 0.06); }

/* Ranking search box (name filter) — see #rk-search in the ranking modal.
   16px font-size avoids the iOS focus-zoom on the connect screen. */
.rk-search-wrap { margin-bottom: 10px; }
.rk-search {
  width: 100%; box-sizing: border-box; padding: 8px 10px;
  background: var(--field-bg); color: var(--text-hi);
  border: 1px solid var(--border); border-radius: var(--r-xs);
  font-family: var(--ff-mono); font-size: 16px; outline: none;
  transition: border-color 0.15s;
}
.rk-search::placeholder { color: var(--text); opacity: 0.6; }
.rk-search:focus { border-color: var(--gold); }

/* Ranking season + All-Time controls — see #rk-controls in the ranking modal.
   16px <select> font-size avoids the iOS focus-zoom on the connect screen. */
.rk-controls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; font-family: var(--ff-mono); font-size: var(--fs-base); color: var(--text); }
.rk-season-lbl { display: inline-flex; align-items: center; gap: var(--sp-2); }
.rk-season { font-family: var(--ff-mono); font-size: 16px; padding: 5px 8px; background: var(--field-bg); color: var(--text-hi); border: 1px solid var(--border); border-radius: var(--r-xs); outline: none; }
.rk-season:focus { border-color: var(--gold); }
.rk-season:disabled { opacity: 0.45; }
.rk-alltime-lbl { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
.rk-alltime-lbl input { accent-color: var(--gold); width: 15px; height: 15px; cursor: pointer; }

/* ── Ranking card as a floating window (desktop/tablet, >=900x600) ────────
   Reuses the shared floating-win drag/resize system (makeWin* in pokerth.js).
   The card is position:relative inside the modal, so pin it fixed + drop the
   dark backdrop + let clicks through behind it. Mobile keeps the modal.
   Applies to BOTH the lobby ranking (#ranking-modal) and the in-game table
   ranking (#tableranking-modal) so they behave identically — draggable,
   resizable, no dimming overlay, integrated into the app. */
#ranking-modal.rk-floating,
#tableranking-modal.rk-floating { pointer-events: none; }
#ranking-modal.rk-floating .rk-backdrop,
#tableranking-modal.rk-floating .rk-backdrop { display: none; }
#ranking-modal.rk-floating .rk-card,
#tableranking-modal.rk-floating .rk-card { pointer-events: auto; }
#ranking-modal .rk-card.floating-win,
#tableranking-modal .rk-card.floating-win {
  position: fixed; margin: 0; max-height: none;
  border: 1px solid var(--gold-dim); border-radius: var(--r-bar);
  box-shadow: 0 14px 36px rgba(0,0,0,0.62); overflow: hidden;
}
#ranking-modal .rk-card.floating-win .rk-title,
#tableranking-modal .rk-card.floating-win .rk-title { cursor: move; touch-action: none; -webkit-user-select: none; user-select: none; }
#ranking-modal .rk-card.floating-win .rk-title.win-dragging,
#tableranking-modal .rk-card.floating-win .rk-title.win-dragging { cursor: grabbing; }

/* ── Player profile (clicking a name in the ranking) ─────────────────────── */
.rk-name { background: none; border: none; padding: 0; margin: 0; font: inherit; letter-spacing: inherit; color: var(--gold-hi); cursor: pointer; }
.rk-name:hover { color: var(--gold); }
#rk-profile { flex: 1; min-height: 120px; overflow-y: auto; }
.rk-back { background: var(--inset); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-xs); width: 32px; height: 28px; line-height: 1; font-size: var(--fs-lg); cursor: pointer; margin-bottom: 12px; transition: border-color 0.15s, color 0.15s; }
.rk-back:hover { border-color: var(--gold); color: var(--gold-hi); }
.rk-prof-head { margin-bottom: 14px; }
.rk-prof-name { font-family: var(--ff-mono); font-size: 1.15rem; font-weight: 600; letter-spacing: 0.02em; color: var(--gold-hi); word-break: break-word; }
.rk-prof-since { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--text); opacity: 0.8; margin-top: 2px; }
.rk-sec { margin-bottom: 14px; }
.rk-sec-h { font-family: var(--ff-mono); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--gold-dim); margin-bottom: 6px; }
.rk-awards { display: flex; flex-wrap: nowrap; gap: var(--sp-3); overflow-x: auto; overflow-y: hidden; padding-bottom: 6px; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--gold-dim) transparent; }
.rk-awards::-webkit-scrollbar { height: 6px; }
.rk-awards::-webkit-scrollbar-thumb { background: var(--gold-dim); border-radius: var(--r-xs); }
.rk-awards::-webkit-scrollbar-track { background: transparent; }
.rk-award { flex: 0 0 auto; width: 54px; height: 54px; object-fit: contain; border-radius: 4px; background: rgba(var(--gold-rgb), 0.05); cursor: pointer; }
#rk-awpop { display: none; position: fixed; inset: 0; z-index: 10000; background: rgba(0, 0, 0, 0.85); align-items: center; justify-content: center; padding: 24px; cursor: pointer; pointer-events: auto; }
#rk-awpop img { max-width: 90vw; max-height: 90vh; object-fit: contain; border-radius: var(--r-sm); box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6); }
.rk-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); gap: 6px; }
.rk-tile { background: var(--field-bg); border: 1px solid var(--border); border-radius: 4px; padding: 8px 4px; text-align: center; }
.rk-tile-v { font-family: var(--ff-mono); font-size: var(--fs-md); font-weight: 600; color: var(--text-hi); }
.rk-tile-l { font-family: var(--ff-mono); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text); opacity: 0.75; margin-top: 3px; }
/* Cups summary inside the player-info popup (#pim-cups) — reuses the ranking
   profile renderer (rkProfileBody); adds a top heading + one tab per cup. */
.pim-cups { width: 100%; margin-top: 6px; }
.pim-cups-btn { width: 100%; margin-top: 10px; padding: 9px 0; border: 1px solid var(--gold-dim); border-radius: 8px; background: transparent; color: var(--cream); font-family: var(--ff-mono); font-size: var(--fs-base); font-weight: 600; letter-spacing: 0.03em; cursor: pointer; transition: border-color 0.15s, color 0.15s, background 0.15s; }
.pim-cups-btn:hover, .pim-cups-btn:focus-visible { border-color: var(--gold); color: var(--gold-hi); background: rgba(var(--gold-rgb), 0.06); outline: none; }
.rk-cups-h { font-family: var(--ff-mono); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.06em; color: var(--gold-hi); margin: 4px 0 8px; }
.rk-cups-msg, .rk-cups-empty { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--text); opacity: 0.7; margin: 6px 0; }
.rk-cups-tabs { display: flex; gap: var(--sp-1); margin: 2px 0 10px; flex-wrap: wrap; }
.rk-cups-tab { flex: 1 1 auto; min-width: 64px; padding: 6px 8px; font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.03em; color: var(--text); background: var(--field-bg); border: 1px solid var(--border); border-radius: 4px; cursor: pointer; transition: color 0.15s, border-color 0.15s, background 0.15s; }
.rk-cups-tab:hover { border-color: var(--gold); color: var(--gold-hi); }
.rk-cups-tab.active { color: var(--sel-hi,var(--gold-hi)); border-color: var(--sel,var(--gold)); background: rgba(var(--sel-rgb,var(--gold-rgb)), 0.08); }

/* ── Repartition des places (camembert) — SeasonStatsSection + PlacementResult ── */
.rk-place-legend { display:flex; flex-wrap:wrap; gap:var(--sp-4); margin:8px 0; }
.rk-lg { display:inline-flex; align-items:center; gap:5px; font-family:var(--ff-mono); font-size:var(--fs-xs); color:var(--text); }
.rk-lg i { width:11px; height:11px; border-radius:2px; display:inline-block; flex:0 0 auto; }
.rk-ps-tw, .rk-pr-tw { overflow-x:auto; -webkit-overflow-scrolling:touch; }
.rk-ps-table, .rk-pr-table { border-collapse:collapse; width:100%; font-family:var(--ff-mono); }
.rk-ps-table { min-width:340px; }
.rk-pr-table { min-width:280px; }
.rk-ps-table th, .rk-ps-table td, .rk-pr-table th, .rk-pr-table td { padding:4px 3px; text-align:center; font-size:var(--fs-xs); border-bottom:1px solid var(--border); }
.rk-ps-table th, .rk-pr-table th { color:var(--text-hi); font-weight:700; }
.rk-ps-table td, .rk-pr-table td { color:var(--text); }
.rk-ps-table .rk-ps-lbl { text-align:left; color:var(--text); opacity:0.8; white-space:nowrap; }
.rk-ps-pie { display:flex; justify-content:center; margin:10px 0; }
.rk-ps-pie canvas { width:200px; height:200px; max-width:62vw; max-height:62vw; }
.rk-ps-bars { display:flex; align-items:flex-end; gap:3px; height:150px; margin-top:6px; padding-top:14px; }
.rk-ps-bar { flex:1 1 0; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height:100%; min-width:0; }
.rk-ps-bar i { display:block; width:62%; border-radius:2px 2px 0 0; }
.rk-ps-bar b { font-family:var(--ff-mono); font-size:var(--fs-3xs); color:var(--text); opacity:0.85; line-height:1; margin-bottom:2px; min-height:0.58rem; }
.rk-ps-bar u { font-family:var(--ff-mono); font-size:var(--fs-3xs); color:var(--text); opacity:0.7; text-decoration:none; margin-top:3px; }
.rk-pr { display:flex; gap:14px; flex-wrap:wrap; align-items:flex-start; }
.rk-pr-chart { cursor:pointer; flex:0 0 auto; }
.rk-pr-bars { display:flex; align-items:flex-end; gap:var(--sp-0); width:200px; height:100px; }
.rk-pr-chart.show-pie .rk-pr-bars { display:none; }
.rk-pr-bars i { flex:1 1 0; display:block; border-radius:2px 2px 0 0; }
.rk-pr-pie { display:none; }
.rk-pr-chart.show-pie .rk-pr-pie { display:flex; justify-content:center; }
.rk-pr-pie canvas { width:140px; height:140px; }
.rk-pr-tw { flex:1 1 200px; }
.rk-step-tabs { display:flex; gap:var(--sp-1); flex-wrap:wrap; margin:2px 0 8px; }
.rk-step-tab { padding:4px 10px; font-family:var(--ff-mono); font-size:var(--fs-xs); color:var(--text); background:var(--field-bg); border:1px solid var(--border); border-radius:4px; cursor:pointer; }
.rk-step-tab.active { color:var(--sel-hi,var(--gold-hi)); border-color:var(--sel,var(--gold)); background:rgba(var(--sel-rgb,var(--gold-rgb)),0.08); }

.rk-pager { display: flex; align-items: center; justify-content: center; gap: var(--sp-5); padding: 8px 0 2px; }
.rk-page-btn { background: var(--inset); color: var(--text); border: 1px solid var(--border); border-radius: 4px; width: 32px; height: 28px; line-height: 1; font-size: var(--fs-lg); cursor: pointer; transition: border-color 0.15s, color 0.15s; }
.rk-page-btn:hover:not(:disabled) { border-color: var(--gold); color: var(--gold-hi); }
.rk-page-btn:disabled { opacity: 0.4; cursor: default; }
.rk-page-lbl { font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--text); min-width: 56px; text-align: center; }

/* ═══════════════════════════════════════════════════════════════════
   Menu « liens PokerTH » (écran connect) — regroupe PokerTH.net /
   Discord / Shoutbox / Week-End Cup dans un seul <details> pour
   désencombrer le header (surtout sur téléphone). Reprend la chrome du
   menu ••• (#g-overflow-menu). Le 🏆 Ranking reste un bouton séparé.
   ═══════════════════════════════════════════════════════════════════ */
#s-connect .connect-header .cl-links { position: relative; }
#s-connect .connect-header .cl-links > summary {
  list-style: none;
  cursor: pointer;
}
#s-connect .connect-header .cl-links > summary::-webkit-details-marker { display: none; }
#s-connect .connect-header .cl-links > summary::marker { content: ""; }
#s-connect .connect-header .cl-links > summary img { display: block; width: 18px; height: 18px; }

#s-connect .connect-header .cl-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 200;
  width: clamp(232px, 46vw, 300px);
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 1vw, 7px);
  padding: clamp(6px, 1.4vw, 9px) clamp(5px, 1.1vw, 8px);
  box-sizing: border-box;
  background: var(--modal-bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-bar);
  box-shadow: 0 12px 32px rgba(0,0,0,0.7);
}
/* Lignes du menu : on neutralise la « chip » héritée des .btn-sm du
   cluster (fond/bord/ombre/hauteur fixe) pour des lignes plates. */
#s-connect .connect-header .cl-menu .btn-sm {
  width: 100%;
  height: auto;
  min-width: 0;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(9px, 1.8vw, 12px);
  text-align: left;
  padding: clamp(7px, 1.4vw, 10px) clamp(12px, 2.2vw, 16px);
  border-radius: 4px;
  font-size: clamp(0.8rem, 1.9vw, 0.95rem);
  white-space: nowrap;
  text-decoration: none;
  background: transparent;
  border: 1px solid transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
#s-connect .connect-header .cl-menu .btn-sm:hover {
  background: var(--panel-hi);
  border-color: var(--border-hi);
}
#s-connect .connect-header .cl-menu .cl-ico {
  flex: none;
  width: clamp(18px, 3.6vw, 24px);
  height: clamp(18px, 3.6vw, 24px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
#s-connect .connect-header .cl-menu .cl-ico img,
#s-connect .connect-header .cl-menu .cl-ico svg { display: block; width: clamp(18px, 3.6vw, 24px); height: clamp(18px, 3.6vw, 24px); }
#s-connect .connect-header .cl-menu .cl-ico-emo {
  flex: none;
  width: clamp(18px, 3.6vw, 24px);
  text-align: center;
  font-size: clamp(0.95rem, 2.2vw, 1.2rem);
  line-height: 1;
}

/* ── Advanced options modal (QML-parity settings) ──────────────────────────
   Entrée via la roue crantée (jeu + lobby). Chrome réutilisé de .km-* ; corps
   .adv-* propre. Bascules présentation appliquées par applyAdvOpts() via des
   classes sur <body>. */
#adv-modal{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;pointer-events:none}
#adv-modal .km-backdrop{display:none}
#adv-modal .km-card{pointer-events:auto}
.adv-card{max-width:420px;width:calc(100% - 32px)}
.adv-body{max-height:62vh;overflow:auto;margin-top:8px;padding-right:2px}
.adv-sec{font-size:var(--fs-2xs);letter-spacing:0.12em;text-transform:uppercase;color:var(--gold-dim);margin:13px 0 4px;font-weight:700}
.adv-sec:first-child{margin-top:4px}
/* Sections repliables de l'onglet Interface (demande narmod 2026-07-19) :
   <details class="adv-fold"> natif, plie par defaut, chevron anime. */
details.adv-fold>summary.adv-sec{cursor:pointer;list-style:none;display:flex;align-items:center;gap:var(--sp-3);user-select:none;-webkit-tap-highlight-color:transparent;padding:5px 0;font-size:var(--fs-xs);letter-spacing:0.07em} /* narmod 2026-07-19 : en-tete de section discret (eyebrow), plus petit que les options .adv-row 0.82rem */
details.adv-fold>summary.adv-sec::-webkit-details-marker{display:none}
summary.adv-sec .adv-sec-ic{flex:0 0 auto;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;opacity:.9}
summary.adv-sec .adv-sec-ic svg{width:14px;height:14px;display:block} /* 14 px : accorde a l'en-tete de section reduit */
details.adv-fold>summary.adv-sec::before{content:'\25B8';font-size:0.95em;color:var(--gold-dim);transition:transform .15s ease;flex:0 0 auto}
details.adv-fold[open]>summary.adv-sec::before{transform:rotate(90deg)}
/* Lisibilité (demande narmod 2026-07-19) : les options d'une section sont
   INDENTÉES sous leur catégorie (alignées sous l'icône), et une section
   ouverte est soulignée d'un fin séparateur sous son en-tête. */
details.adv-fold>*:not(summary){margin-left:28px}
details.adv-fold[open]>summary.adv-sec{border-bottom:1px solid var(--border);padding-bottom:7px;margin-bottom:6px}
details.adv-fold:first-child>summary.adv-sec{margin-top:4px}
.adv-row{display:flex;align-items:center;gap:9px;padding:6px 2px;font-size:var(--fs-base);color:var(--text);cursor:pointer}
.adv-row input[type=checkbox]{accent-color:var(--gold);flex-shrink:0;width:16px;height:16px}
.adv-row > span{flex:1}
.adv-row .adv-numin{flex:0 0 auto;width:92px;text-align:right;background:transparent;color:var(--text);border:1px solid var(--border);border-radius:8px;padding:5px 8px;font:inherit;font-size:var(--fs-base)}
.adv-row .adv-textin{flex:0 0 auto;width:150px;background:transparent;color:var(--text);border:1px solid var(--border);border-radius:8px;padding:5px 8px;font:inherit;font-size:var(--fs-base)}
.adv-row em{font-size:var(--fs-3xs);font-style:normal;letter-spacing:0.08em;text-transform:uppercase;color:var(--gold-dim);border:1px solid var(--border);border-radius:var(--r-bar);padding:1px 7px;opacity:0.85}
.adv-webtag{font-size:var(--fs-3xs);font-style:normal;letter-spacing:0.08em;text-transform:uppercase;color:var(--green);border:1px solid rgba(var(--green-rgb),0.45);border-radius:var(--r-bar);padding:1px 7px;opacity:0.9;flex-shrink:0}
.adv-betatag{font-size:var(--fs-3xs);font-style:normal;letter-spacing:0.08em;text-transform:uppercase;color:var(--gold);border:1px solid rgba(var(--gold-rgb),0.5);border-radius:var(--r-bar);padding:1px 7px;opacity:0.92;flex-shrink:0;margin-right:5px}
.adv-row.adv-soon{opacity:0.5;cursor:default}
body.adv-no-cardanim .seat-holecards *,body.adv-no-cardanim .hand-cards *,body.adv-no-cardanim #g-myseat-cards *{transition:none !important;animation:none !important}
body.adv-no-blinds .blind-chip,body.adv-no-blinds .dealer-chip{display:none !important}
body.adv-no-blindsbadge .blinds-next{display:none !important}
body.adv-no-handsbtn #hands-toggle-btn{display:none !important}
body.adv-no-community #ranking-btn-connect,body.adv-no-community #ranking-btn-lobby,body.adv-no-community #ranking-btn-game{display:none !important}
body.adv-no-tablezoom #g-zoom-ctrl{display:none !important}
body.adv-no-lobbychat #lobby-chat-btn{display:none !important}
body.adv-no-lobbychat #lobby-chat-panel,
body.adv-no-lobbychat #s-lobby .lobby-grid > #lobby-chat-panel{display:none !important}
#g-next-hand-btn{position:fixed;left:50%;bottom:150px;transform:translateX(-50%);z-index:950;padding:10px 22px;font-size:var(--fs-md);font-weight:700;letter-spacing:0.04em;color:#fff;background:linear-gradient(#50b840,#1e6614);border:1px solid #7ad06a;border-radius:var(--r-md);cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,0.45)}
#g-next-hand-btn:active{transform:translateX(-50%) scale(0.96)}
.adv-ign-desc{font-size:var(--fs-sm);color:var(--text);opacity:0.7;margin:2px 2px 8px}
.adv-ign-row{display:flex;align-items:center;gap:9px;padding:5px 2px;font-size:var(--fs-base);color:var(--text);border-bottom:1px solid rgba(var(--gold-rgb),0.08)}
.adv-ign-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.adv-ign-rm{font-size:var(--fs-xs);letter-spacing:0.05em;color:var(--text);background:none;border:1px solid var(--border);border-radius:var(--r-bar);padding:2px 10px;cursor:pointer}
.adv-ign-rm:hover{color:var(--gold);border-color:var(--gold-dim)}
.adv-ign-empty{font-size:var(--fs-sm);color:var(--text);opacity:0.55;padding:4px 2px}
@media (min-width:900px){body.adv-no-lobbychat #s-lobby .lobby-grid{grid-template-rows:minmax(0,1fr) 0 0 auto}body.adv-no-lobbychat #s-lobby .lob-h-v{display:none}}
@media (max-width:899.98px){body.adv-no-lobbychat #s-lobby .lobby-grid > .games-col{flex:1 1 auto !important}}

/* Estompage des cartes des perdants au showdown (fadeOutLosingCards). Le marquage
   .loser-fade est pose sur le siege par renderSeatsImmediate quand le pid est dans
   _sdLosers (rempli a EndOfHandShow). Seules les cartes sont attenuees. */
.seat.loser-fade .pk{opacity:.4;filter:grayscale(.55);transition:opacity .45s ease,filter .45s ease}
/* Drapeau pays sur l'avatar (showCountryFlagOnAvatar) — visibilite togglable. */
body.adv-no-flag .seat-flag{display:none !important}
/* Titre « PokerTH » de l'écran de connexion (.cl-app-title) : CACHÉ par
   défaut (demande narmod 19/07). Rendu visible uniquement quand l'option
   « Afficher le titre PokerTH » est activée (body.adv-show-title). */
.cl-app-title{display:none}
body.adv-show-title .cl-app-title{display:block}
/* Player-bar masquée : tes cartes/infos s'affichent dans ta self-box (siège).
   La barre d'action descend tout en bas (pin forcé en JS -> visible en permanence). */
body.adv-hide-pbar .player-bar{display:none !important}
/* Reserve de repli pour les sieges (le JS affine a la hauteur exacte de la barre
   d'action des le prochain rendu). Garde la self-box au-dessus de la barre epinglee. */
body.adv-hide-pbar .game-area{padding-bottom:clamp(210px,34dvh,290px)}
body.adv-hide-pbar .my-zone{bottom:0 !important;padding-bottom:max(8px,env(safe-area-inset-bottom))}
/* ── Mobile PORTRAIT + table plein écran + dock masqué : barre d'action COLLÉE
   au bord bas. Le panneau des boutons devient une bande pleine largeur dont le
   fond descend jusqu'au bord (coins bas droits) ; la marge du home-indicator
   (safe-area) passe DANS le panneau -> plus de bande "bois" (fond de table)
   visible sous les boutons. Scopé phone portrait uniquement : tablette/desktop
   gardent la carte flottante centrée, le paysage garde son flux. */
@media (orientation: portrait) and (max-width: 899px) {
  html[data-table-fs="1"] body.adv-hide-pbar .my-zone {
    padding-left: 0 !important; padding-right: 0 !important; padding-bottom: 0 !important;
  }
  html[data-table-fs="1"] body.adv-hide-pbar .my-zone .action-wrap { max-width: none; width: 100%; }
  html[data-table-fs="1"] body.adv-hide-pbar .my-zone .action-grid {
    max-width: none; width: 100%; margin: 0;
    border-radius: 12px 12px 0 0;   /* coins hauts arrondis, bas droits */
    border-bottom: 0;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
  }
}
/* Mode masqué (Mode PokerTH) : MA self-box (siège) affiche mes cartes ~taille tapis.
   COHERENCE PAR STYLE :
   - Style "pokerth" : on GARDE la grille native -> self-box IDENTIQUE aux adversaires,
     on agrandit SEULEMENT mes cartes (aucune surcharge de layout ci-dessous).
   - Autres styles : ils ne placent pas mes cartes nativement -> on force un layout flex
     (avatar|cartes, nom dessous) + max-width:none (sinon empilement vertical). */

/* Taille des cartes self RATTACHEE aux cartes communes via --comm-scale
   (slot QML 46x64 x echelle par appareil) : chaque palier est une FRACTION
   <= 1 de la taille riviere -> le zoom ne peut JAMAIS la depasser, sur tous
   les appareils. Niveau 0 (base QML) = 85% de la riviere. */
.seat.me .seat-holecards.shc-big .pk {
  width: calc(46px * var(--comm-scale, 1) * 0.85) !important;
  height: calc(64px * var(--comm-scale, 1) * 0.85) !important;
  font-size: calc(1.02rem * var(--comm-scale, 1) * 0.85) !important;
  border-radius: calc(5px * var(--comm-scale, 1)) !important;
}
/* Paliers du zoom de mes cartes (cycle 0-3 du bouton #g-cardzoom),
   STRICTEMENT CROISSANTS depuis la base et PLAFONNES a la riviere :
   0 = 85% · 1 = 90% · 2 = 95% · 3 = 100% (= taille exacte des cartes
   communes). Fractions de --comm-scale -> adapte a chaque appareil. */
.seat.me .seat-holecards.shc-l1 .pk { width: calc(46px * var(--comm-scale, 1) * 0.90) !important; height: calc(64px * var(--comm-scale, 1) * 0.90) !important; font-size: calc(1.02rem * var(--comm-scale, 1) * 0.90) !important; border-radius: calc(5px * var(--comm-scale, 1)) !important; }
.seat.me .seat-holecards.shc-l2 .pk { width: calc(46px * var(--comm-scale, 1) * 0.95) !important; height: calc(64px * var(--comm-scale, 1) * 0.95) !important; font-size: calc(1.02rem * var(--comm-scale, 1) * 0.95) !important; border-radius: calc(5px * var(--comm-scale, 1)) !important; }
.seat.me .seat-holecards.shc-l3 .pk { width: calc(46px * var(--comm-scale, 1)) !important; height: calc(64px * var(--comm-scale, 1)) !important; font-size: calc(1.02rem * var(--comm-scale, 1)) !important; border-radius: calc(5px * var(--comm-scale, 1)) !important; }
/* Paysage mobile (landscapeCompact) : cartes self a la taille EXACTE de la
   riviere des le niveau 0 (le transform du siege les reduit deja ~20%) —
   demande narmod « grossir les cartes de la selfbox ». Tout le cycle est mis
   au plafond pour rester monotone (plateau, jamais de retrecissement). */
@media (orientation: landscape) and (max-height: 600px) {
  /* Division par --sscale (échelle transform du siège, posée par renderSeats) :
     sans elle, la taille rivière était RE-réduite par le scale du siège
     (~x0.8) → cartes minuscules. Taille écran = taille rivière EXACTE. */
  .seat.me .seat-holecards.shc-big .pk,
  .seat.me .seat-holecards.shc-l1 .pk,
  .seat.me .seat-holecards.shc-l2 .pk,
  .seat.me .seat-holecards.shc-l3 .pk {
    width: calc(46px * var(--comm-scale, 1) / var(--sscale, 1)) !important;
    height: calc(64px * var(--comm-scale, 1) / var(--sscale, 1)) !important;
    font-size: calc(1.02rem * var(--comm-scale, 1) / var(--sscale, 1)) !important;
  }
}
/* ── Packs pokerth : self-box à la STRUCTURE QML exacte (GamePlayerSelfBox).
   Dans le QML, les cartes du self dérivent de la hauteur de la BOX
   (selfBaseHeight 96/94/82 → cardsH = H−12−barre → cartes ≈ 37×52, 36×50 en
   landscapeCompact ; avatar = min(cardsH, 60/54)). Côté web elles étaient
   couplées à la taille des cartes COMMUNES (--comm-scale), qui grossit avec
   la fenêtre — cause de la self énorme qui chevauchait ses voisins sur
   desktop. Ici : tailles fixes QML (échelle du siège appliquée par le
   transform, comme les adversaires) ; tous les paliers du bouton de zoom de
   cartes sont au même point (plateau) — en fidélité QML la taille des cartes
   self est fixe. Les packs non-pokerth gardent le couplage rivière. */
html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-big .pk,
html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l1 .pk,
html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l2 .pk,
html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l3 .pk {
  width: 37px !important; height: 52px !important;
  font-size: var(--fs-sm) !important; border-radius: 3px !important;
}
html[data-seat-struct="qml"] .seat.me .seat-avatar {
  width: 52px !important; height: 52px !important;
}
@media (orientation: landscape) and (max-height: 600px) {
  html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-big .pk,
  html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l1 .pk,
  html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l2 .pk,
  html[data-seat-struct="qml"] .seat.me .seat-holecards.shc-l3 .pk {
    width: 36px !important; height: 50px !important; font-size: var(--fs-sm) !important;
  }
  html[data-seat-struct="qml"] .seat.me .seat-avatar {
    width: 50px !important; height: 50px !important;
  }
}
/* Pastille de niveau (1/2/3/4/5) sur le bouton. */
#g-cardzoom { position: relative; }
#g-cardzoom[data-lvl="1"]::after, #g-cardzoom[data-lvl="2"]::after, #g-cardzoom[data-lvl="3"]::after {
  content: attr(data-lvl); position: absolute; top: -4px; right: -4px;
  min-width: 13px; height: 13px; border-radius: 7px; font-size: 9px; line-height: 13px;
  background: #1a1205; color: var(--accent, #E3C800); font-weight: 700; text-align: center;
}

/* Layout flex : styles NON-pokerth UNIQUEMENT (le pokerth garde sa grille native). */
html:not([data-seat-struct="qml"]) body.adv-hide-pbar .seat.me { max-width: 190px !important; min-width: 0 !important; }
html:not([data-seat-struct="qml"]) body.adv-hide-pbar .seat.me .seat-plate {
  display: flex !important; flex-wrap: wrap; max-width: 190px !important;
  align-items: center; justify-content: center; gap: var(--sp-2);
}
html:not([data-seat-struct="qml"]) body.adv-hide-pbar .seat.me .seat-avatar { order: 1; flex: none; }
html:not([data-seat-struct="qml"]) body.adv-hide-pbar .seat.me .seat-holecards.shc-big {
  order: 2; display: flex !important; gap: var(--sp-1); flex: none; grid-column: auto; grid-row: auto;
}
html:not([data-seat-struct="qml"]) body.adv-hide-pbar .seat.me .seat-info {
  order: 3; flex-basis: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 0;
}
/* ── Packs héritage (sans structure QML) : EMPREINTE bornée au gabarit de la
   bisection (114×84 adversaires, self ~150×96) — même placement et mêmes
   tailles que le pack PokerTH, habillage du pack conservé (0.3.696). ── */
html:not([data-seat-struct="qml"]) .seat:not(.me) { max-width: 114px !important; gap: 1px; }
html:not([data-seat-struct="qml"]) .seat:not(.me) .seat-avatar { width: 40px !important; height: 40px !important; font-size: var(--fs-md) !important; }
html:not([data-seat-struct="qml"]) .seat:not(.me) .seat-name { font-size: var(--fs-xs) !important; line-height: 1.15; max-width: 106px !important; }
html:not([data-seat-struct="qml"]) .seat:not(.me) .seat-money { font-size: var(--fs-xs) !important; line-height: 1.15; }
html:not([data-seat-struct="qml"]) .seat:not(.me) .seat-foot { margin-top: 1px; gap: var(--sp-1); }
/* Selecteur "Placement des sieges" dans Options avancees. */
.adv-row .adv-sel{flex:0 0 auto;min-width:132px}
.adv-lang-btn{-webkit-appearance:none;appearance:none;width:100%;display:flex;align-items:center;gap:var(--sp-3);background:var(--field-bg);border:1px solid var(--border);border-radius:2px;color:var(--cream);padding:8px 32px 8px 11px;font-family:var(--ff-mono);font-size:var(--fs-base);text-align:left;outline:none;cursor:pointer}
.adv-lang-btn:focus{border-color:var(--gold)}
.adv-lang-btn .lf{display:inline-flex;width:22px;flex:none}
.adv-lang-btn .ln{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Option "révéler mes cartes au tap" : les dos de la player-bar sont cliquables,
   lueur or pour signaler l'interaction (uniquement quand masquées). */
#g-myseat-cards.own-peek{cursor:pointer}
#g-myseat-cards.own-peek .pk.back{box-shadow:0 0 0 2px var(--accent,#E3C800),0 0 9px rgba(227,200,0,.55);transition:box-shadow .15s}
/* Anti-Call accidentel : bouton Call en attente de confirmation (2e tap). */
.btn-action.btn-call.confirm-call{background:linear-gradient(#f0a020,#b36b00);border-color:#ffd24d;color:#1a1205;animation:callConfirmPulse .85s ease-in-out infinite}
@keyframes callConfirmPulse{0%,100%{box-shadow:0 0 0 2px #ffd24d,0 0 12px rgba(240,160,32,.55)}50%{box-shadow:0 0 0 2px #ffd24d,0 0 19px rgba(240,160,32,.9)}}
/* Moniteur d'odds (option) : panneau compact en haut-gauche, semi-transparent,
   display-only (pointer-events:none -> ne bloque pas les sièges derrière). */
/* ── Panneau info unifié : onglets Historique/Chances (QML GameInfoPanel) ── */
.gip-tabs { display:flex; flex:1; margin-right:6px; min-width:0; }
/* Poignée de déplacement dédiée : les onglets couvrent presque toute la barre,
   le ⠿ garantit une prise visible (les onglets se traînent aussi, au seuil). */
.gip-grip { flex:0 0 auto; color:var(--chatlog-muted, var(--text-dim,#9aa3b5)); font-size:var(--fs-xs);
  padding:0 6px 0 2px; cursor:move; user-select:none; }
.gip-tab { flex:0 1 auto; background:transparent; border:none; border-bottom:2px solid transparent;
  color:var(--chatlog-muted, var(--text-dim, #9aa3b5)); font-size:var(--fs-2xs); letter-spacing:0.12em; text-transform:uppercase;
  padding:3px 12px 4px; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  touch-action:none; }
.gip-tab.gip-on { color:var(--chatlog-text, var(--gold)); border-bottom-color:var(--box-accent, var(--chatlog-muted, var(--gold-dim))); font-weight:700; }
.gip-tab:hover { color:var(--chatlog-text, var(--gold)); }
/* Onglet Chances : mêmes classes que l'ancien moniteur, tailles panneau. */
#g-odds-body .odds-hd{font-weight:700;font-size:var(--fs-sm);color:var(--box-accent, var(--chatlog-text, var(--gold)));margin:2px 0 5px;letter-spacing:.3px}
#g-odds-body .odds-approx{opacity:.65;font-weight:400}
#g-odds-body .odds-wait{opacity:.6;padding:4px 0;font-size:var(--fs-sm)}
#g-odds-body .odds-row{display:flex;align-items:center;gap:var(--sp-2);height:22px;font-size:var(--fs-sm)}
#g-odds-body .odds-ico{width:26px;height:17px;object-fit:contain;flex:0 0 auto}
#g-odds-body .odds-cat{flex:0 0 44%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:.9}
#g-odds-body .odds-bar{flex:1;height:7px;background:rgba(var(--gold-rgb),.14);border-radius:var(--r-xs);overflow:hidden}
#g-odds-body .odds-bar>i{display:block;height:100%;width:0;background:linear-gradient(90deg,#8a93a6,#5a6478);border-radius:3px}
#g-odds-body .odds-pct{flex:0 0 34px;text-align:right;font-variant-numeric:tabular-nums;opacity:.92}
#g-odds-body .odds-row.warm .odds-bar>i{background:linear-gradient(90deg,#f0a020,#b36b00)}
#g-odds-body .odds-row.hot .odds-bar>i{background:linear-gradient(90deg,#50c878,#1e8c4e)}
#g-odds-body .odds-row.hot .odds-pct{color:#7ce0a0;font-weight:700}

/* Onglet Stats (panneau info) : tableau VPIP/PFR/AF... des joueurs de la table. */
#g-stats-body .odds-hd{font-weight:700;font-size:var(--fs-sm);color:var(--box-accent, var(--chatlog-text, var(--gold)));margin:2px 0 5px;letter-spacing:.3px}
#g-stats-body .stats-wait{opacity:.6;padding:4px 0;font-size:var(--fs-sm)}
#g-stats-body .stats-scope{display:flex;gap:var(--sp-1);margin:0 0 6px}
#g-stats-body .stats-scope-btn{flex:0 0 auto;background:transparent;border:1px solid var(--border, rgba(255,255,255,.15));color:var(--chatlog-muted, var(--text-dim,#9aa3b5));font-size:var(--fs-2xs);letter-spacing:.1em;text-transform:uppercase;padding:2px 9px;border-radius:var(--r-sm);cursor:pointer}
#g-stats-body .stats-scope-btn.on{color:var(--chatlog-text, var(--gold));border-color:var(--box-accent, var(--gold-dim));background:rgba(var(--gold-rgb),.12);font-weight:700}
#g-stats-body .stats-scroll{overflow-x:auto}
#g-stats-body .stats-table{border-collapse:collapse;width:100%;font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
#g-stats-body .stats-table th{color:var(--chatlog-muted, var(--text-dim,#9aa3b5));font-weight:700;text-align:right;padding:2px 5px;border-bottom:1px solid var(--border, rgba(255,255,255,.12));white-space:nowrap;cursor:help}
#g-stats-body .stats-table td{text-align:right;padding:2px 5px;border-bottom:1px solid rgba(255,255,255,.05);white-space:nowrap}
#g-stats-body .stats-table .stats-name{text-align:left;max-width:96px;overflow:hidden;text-overflow:ellipsis;color:var(--chatlog-text, var(--text));font-weight:600}
#g-stats-body .stats-table tbody tr:hover td{background:rgba(var(--gold-rgb),.06)}
#g-stats-body .stats-empty{text-align:center;opacity:.6;padding:10px 0}

/* Bouton d'export .pdb dans l'onglet Stats. */
#g-stats-body .stats-export-btn{margin-left:auto;background:transparent;border:1px solid var(--border, rgba(255,255,255,.15));color:var(--chatlog-muted, var(--text-dim,#9aa3b5));font-size:var(--fs-2xs);letter-spacing:.06em;padding:2px 9px;border-radius:var(--r-sm);cursor:pointer}
#g-stats-body .stats-export-btn:hover{color:var(--chatlog-text, var(--gold));border-color:var(--box-accent, var(--gold-dim))}
#g-stats-body .stats-export-btn:disabled{opacity:.5;cursor:default}
#g-stats-body .stats-scope{align-items:center}
/* Boutons d'export dans les options avancees (section Log). */
.adv-export-row{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin-top:4px}
.adv-export-btn:disabled{opacity:.5;cursor:default}


#odds-monitor{--ws:1;position:fixed;top:54px;left:8px;z-index:42;width:132px;padding:calc(5px*var(--ws)) calc(7px*var(--ws)) calc(6px*var(--ws));background:var(--panel);border:1px solid var(--border);border-radius:calc(9px*var(--ws));box-shadow:0 4px 14px rgba(0,0,0,.42);font-size:calc(10px*var(--ws));line-height:1.25;color:var(--text);pointer-events:auto;user-select:none;cursor:move;touch-action:none}
#odds-monitor.odds-drag{opacity:.96;box-shadow:0 8px 24px rgba(0,0,0,.58);border-color:var(--border-hi)}
#odds-monitor .odds-hd{font-weight:700;font-size:calc(10.5px*var(--ws));color:var(--gold);margin-bottom:calc(3px*var(--ws));letter-spacing:.3px;padding-right:calc(14px*var(--ws))}
#odds-monitor .odds-approx{opacity:.65;font-weight:400}
#odds-monitor .odds-wait{opacity:.6;padding:2px 0}
#odds-monitor .odds-row{display:flex;align-items:center;gap:calc(4px*var(--ws));height:calc(13px*var(--ws))}
#odds-monitor .odds-cat{flex:0 0 calc(50px*var(--ws));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:.88}
#odds-monitor .odds-bar{flex:1;height:calc(6px*var(--ws));background:rgba(var(--gold-rgb),.14);border-radius:calc(3px*var(--ws));overflow:hidden}
#odds-monitor .odds-bar>i{display:block;height:100%;width:0;background:linear-gradient(90deg,#8a93a6,#5a6478);border-radius:calc(3px*var(--ws))}
#odds-monitor .odds-pct{flex:0 0 calc(27px*var(--ws));text-align:right;font-variant-numeric:tabular-nums;opacity:.92}
#odds-monitor .odds-row.warm .odds-bar>i{background:linear-gradient(90deg,#f0a020,#b36b00)}
#odds-monitor .odds-row.hot .odds-bar>i{background:linear-gradient(90deg,#50c878,#1e8c4e)}
#odds-monitor .odds-row.hot .odds-pct{color:#7ce0a0;font-weight:700}
@media (min-width:600px){#odds-monitor{resize:horizontal;overflow:hidden;min-width:104px;max-width:340px}}
@media (max-width:599.98px){#odds-monitor{--ws:.95;width:120px;top:48px}}
/* Fenetre flottante "Assistance" (force de la main) -- meme modele que #odds-monitor. */
#assist-win{--ws:1;position:fixed;top:54px;right:8px;z-index:42;width:150px;min-width:110px;max-width:210px;padding:calc(5px*var(--ws)) calc(8px*var(--ws)) calc(7px*var(--ws));background:var(--panel);border:1px solid var(--border);border-radius:calc(9px*var(--ws));box-shadow:0 4px 14px rgba(0,0,0,.42);color:var(--text);pointer-events:auto;user-select:none;cursor:move;touch-action:none}
#assist-win.hsw-drag{opacity:.96;box-shadow:0 8px 24px rgba(0,0,0,.58);border-color:var(--border-hi)}
#assist-win .hsw-hd{font-weight:700;font-size:calc(10.5px*var(--ws));color:var(--gold);margin-bottom:calc(5px*var(--ws));letter-spacing:.3px;padding-right:calc(14px*var(--ws))}
#assist-win .hs-lbl{display:block;background:transparent;border:0;padding:0;max-width:none;overflow:hidden}
#assist-win .hs-txt{display:block;font-size:calc(11.5px*var(--ws)) !important;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:none}
#assist-win #hand-strength{position:static;left:auto;right:auto;top:auto;height:auto;pointer-events:none;margin-top:calc(6px*var(--ws))}
#assist-win .hs-track{display:block;position:static;left:auto;right:auto;top:auto;height:calc(6px*var(--ws));border-radius:calc(3px*var(--ws))}
#assist-win .hs-fill{border-radius:calc(3px*var(--ws))}
@media (min-width:600px){#assist-win{resize:horizontal;overflow:hidden;max-width:340px}}
@media (max-width:599.98px){#assist-win{--ws:.96;width:auto;min-width:110px;top:48px}}
/* Assistance (force de la main) integree en tete de l'onglet « Chances » du
   panneau info unifie : meme rendu que l'ancienne fenetre flottante, mais en flux. */
#gip-assist{padding:6px 12px 7px;border-bottom:1px solid var(--chatlog-border,var(--border));background:var(--chatlog-bg, var(--field-bg))}
#gip-assist .odds-hd{font-weight:700;font-size:var(--fs-sm);color:var(--box-accent, var(--chatlog-text, var(--gold)));margin:0 0 5px;letter-spacing:.3px}
#gip-assist .hs-lbl{display:block;background:transparent;border:0;padding:0;max-width:none;overflow:hidden}
#gip-assist .hs-txt{display:block;font-size:var(--fs-sm) !important;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:none;color:var(--chatlog-text, var(--cream))}
#gip-assist #hand-strength{position:static;left:auto;right:auto;top:auto;height:auto;pointer-events:none;margin-top:6px}
#gip-assist .hs-track{display:block;position:static;left:auto;right:auto;top:auto;height:6px;border-radius:var(--r-xs);background:rgba(var(--gold-rgb),.14)}
#gip-assist .hs-fill{border-radius:3px}
/* ── Style « Segments » de l'assistance (Options avancées → Assistance) ────
   10 blocs qui se remplissent : la force se lit d'un coup d'œil sans lire le
   chiffre, et la rangée tient en 9 px de haut (barre + marges = 12 px).
   Le style actif est porté par <html data-assist-style>. */
#gip-assist .hs-segs{display:none;gap:3px;margin-top:6px}
#gip-assist .hs-segs i{flex:1;height:9px;border-radius:2px;background:rgba(var(--gold-rgb),.14);transition:background .18s ease}
#gip-assist .hs-segs i.on{background:var(--hs-col, var(--gold))}
:root[data-assist-style="segs"] #gip-assist .hs-segs{display:flex}
/* On masque la PISTE, pas #hand-strength : ce dernier recoit un display
   INLINE depuis le JS (_hsHide / renderPreFlopStrength), qui l'emporte sur
   toute regle CSS — d'ou la double barre constatee en web.30. La piste, elle,
   n'est jamais touchee en inline. margin/height a zero pour ne pas laisser de
   creux a la place de la barre. */
:root[data-assist-style="segs"] #gip-assist .hs-track{display:none}
:root[data-assist-style="segs"] #gip-assist #hand-strength{margin:0;height:0}
/* Fenêtre détachée : le ↩ est en overlay au coin haut-droit. On lui RÉSERVE une
   gouttière sur la ligne de libellé pour qu'il ne recouvre jamais le texte
   (demande narmod), et on resserre les marges pour gagner de la place. */
#g-assist-panel #gip-assist{padding:6px 9px 7px}
/* Reduction maximale : sous 52 px de haut, la fenetre ne garde que la rangee de
   segments — la couleur et le nombre de blocs suffisent a lire la force, et le
   libelle revient des qu'on agrandit. La classe est posee par un ResizeObserver
   (assist-pane.mjs) : PAS de container query ici, car #g-assist-panel n'a pas de
   taille CSS explicite et `container-type:size` la ferait collapser a 0. */
:root[data-assist-style="segs"] #g-assist-panel.assist-tiny #gip-assist{padding:4px 7px;justify-content:center}
:root[data-assist-style="segs"] #g-assist-panel.assist-tiny #gip-assist .hs-lbl{display:none}
:root[data-assist-style="segs"] #g-assist-panel.assist-tiny #gip-assist .hs-segs{margin-top:0}
#g-assist-panel #gip-assist .hs-lbl{padding-right:22px}
:root[data-assist-style="segs"] #g-assist-panel #gip-assist .hs-segs{margin-top:5px}
/* ── Assistance : rangée de titre + bouton détacher (v0.3.908) ── */
.gip-assist-hd-row{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);margin:0 0 5px}
.gip-assist-hd-row .odds-hd{margin:0}
.gip-assist-pop{flex:0 0 auto;background:none;border:none;cursor:pointer;font-size:var(--fs-md);line-height:1;padding:0 2px;color:var(--chatlog-muted, var(--gold-dim))}
.gip-assist-pop:hover{color:var(--chatlog-text, var(--gold))}
/* ── Poignée de séparation Assistance / Cotes (drag vertical) ── */
.gip-split{flex:0 0 auto;height:10px;cursor:row-resize;touch-action:none;display:flex;align-items:center;justify-content:center;background:var(--chatlog-bg, var(--field-bg));border-bottom:1px solid var(--chatlog-border,var(--border))}
.gip-split-grip{width:34px;height:3px;border-radius:2px;background:rgba(var(--gold-rgb),.28)}
.gip-split:hover .gip-split-grip{background:rgba(var(--gold-rgb),.55)}
/* ── Fenêtre flottante « Assistance » détachée (chrome comme #g-log-panel) ── */
#g-assist-panel{position:fixed;z-index:100;background:var(--panel);border:1px solid var(--border);box-shadow:0 4px 20px rgba(0,0,0,0.6);border-radius:8px;overflow:hidden;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
#g-assist-panel.floating-win{display:flex;flex-direction:column}
#g-assist-panel .gip-assist-wtitle{flex:1;margin:0 6px;font-size:var(--fs-2xs);color:var(--gold-dim);letter-spacing:0.15em;text-transform:uppercase;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#g-assist-panel .gip-assist-dock{flex:0 0 auto;background:none;border:none;color:var(--chatlog-text2, var(--chatlog-text, var(--text)));cursor:pointer;font-size:var(--fs-md);padding:0 4px}
#g-assist-panel .gip-assist-dock-mini{display:block;position:absolute;top:1px;right:2px;z-index:3;background:none;border:none;color:var(--chatlog-text2, var(--chatlog-text, var(--text)));opacity:.7;cursor:pointer;font-size:var(--fs-base);padding:2px 7px;line-height:1;border-radius:4px}
#g-assist-panel .gip-assist-dock-mini:hover{opacity:1;color:var(--gold)}
/* Détaché : le corps remplit la fenêtre et centre le contenu (fond uniforme →
   pas d'espace blanc). La mise à l'échelle du texte est gérée par zoom:var(--wz)
   posé sur les enfants directs de .floating-win.win-zoom (header + host). */
#g-assist-panel #g-assist-host{flex:1;min-height:0;display:flex}
#g-assist-panel #gip-assist{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;border-bottom:none;overflow:hidden;height:auto}
#g-assist-panel #gip-assist .hs-txt{white-space:normal;overflow:visible;text-overflow:clip}
/* Tactile (pointer:coarse) : sur la pastille (~44px de haut), les 8 poignées
   de resize mangeaient les bords (n+s = 12px, coins 13px) et volaient le drag
   au doigt → Android/iPad « du mal à déplacer ». On ne garde que le coin SE
   (celui qui porte le grip visuel), agrandi à 24px. */
@media (pointer: coarse){
  #g-assist-panel .win-rsz{display:none}
  #g-assist-panel .win-rsz-se{display:block;width:24px;height:24px}
}
/* « Mode pastille » sur TOUTES les plateformes (mobile, tablette, desktop) :
   en-tête masqué, ↩ en overlay dans le coin, drag via toute la fenêtre
   (handle = fenêtre, câblé dans assist-pane.mjs), double-clic n'importe où
   pour recentrer. */
#g-assist-panel .g-chat-panel-header{display:none}
/* Croix de fermeture des fenetres flottantes (odds + assistance). Suit --ws + le theme. */
.win-x{position:absolute;top:calc(2px*var(--ws,1));right:calc(3px*var(--ws,1));width:calc(15px*var(--ws,1));height:calc(15px*var(--ws,1));line-height:calc(14px*var(--ws,1));text-align:center;border:0;background:transparent;color:var(--text);opacity:.5;font-size:calc(12px*var(--ws,1));cursor:pointer;padding:0;border-radius:calc(4px*var(--ws,1));z-index:3;font-family:inherit}
.win-x:hover{opacity:1;color:var(--gold)}
/* Raccourcis clavier personnalisables (Options avancées). */
.adv-keys{display:flex;flex-direction:column;gap:5px;margin-top:2px}
.adv-keyrow{display:flex;align-items:center;gap:9px}
.adv-keyrow>span{flex:1;font-size:var(--fs-md)}
.kb-btn{flex:0 0 auto;min-width:42px;height:30px;padding:0 9px;border-radius:7px;border:1px solid rgba(var(--gold-rgb),.28);background:rgba(var(--gold-rgb),.08);color:var(--text);font-family:var(--ff-mono,monospace);font-weight:700;font-size:var(--fs-md);text-transform:uppercase;cursor:pointer;transition:background .12s,border-color .12s}
.kb-btn:hover{background:rgba(var(--gold-rgb),.16)}
.kb-btn.kb-active{border-color:var(--gold);background:rgba(var(--gold-rgb),.18);color:var(--gold);animation:kbPulse .9s ease-in-out infinite}
@keyframes kbPulse{0%,100%{box-shadow:0 0 0 1px var(--gold,#E3C800)}50%{box-shadow:0 0 0 2px var(--gold,#E3C800),0 0 8px rgba(227,200,0,.5)}}
.adv-keyhint{display:flex;align-items:center;gap:9px;margin-top:3px}
.adv-keyhint>span{flex:1;font-size:var(--fs-xs);opacity:.62;line-height:1.25}
.kb-reset{flex:0 0 auto;height:28px;padding:0 11px;border-radius:7px;border:1px solid rgba(var(--gold-rgb),.24);background:rgba(var(--gold-rgb),.06);color:var(--text);font-size:var(--fs-sm);cursor:pointer}
.kb-reset:hover{background:rgba(var(--gold-rgb),.13)}

/* ===== Options avancées : navigation par catégories (parité dialogue officiel PokerTH) ===== */
/* Tablette/desktop : sidebar icône+texte à gauche. Téléphone : barre d'icônes seules en haut. */
.adv-card{max-width:620px;container-type:inline-size}
.adv-layout{display:flex;gap:14px;margin-top:10px;align-items:stretch}
.adv-nav{flex:0 0 212px;display:flex;flex-direction:column;gap:var(--sp-0);border-right:1px solid var(--border);padding-right:10px;overflow-y:auto;max-height:62vh} /* 168→212 px : libellés de catégories entiers (« Paramètres par défaut »…) — demande narmod 2026-07-18 */
.adv-cat{display:flex;align-items:center;gap:var(--sp-4);width:100%;padding:8px 9px;border:0;border-radius:8px;background:transparent;color:var(--text);font-size:var(--fs-base);font-weight:600;text-align:left;cursor:pointer;transition:background .12s,color .12s}
.adv-cat:hover:not(:disabled):not(.is-active){background:rgba(var(--sel-rgb,var(--gold-rgb)),.08)}
.adv-cat .adv-cat-ic{flex:0 0 auto;width:19px;height:19px;display:inline-flex;align-items:center;justify-content:center;opacity:.85}
.adv-cat .adv-cat-ic svg{width:19px;height:19px;display:block}
.adv-cat .adv-cat-lbl{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.adv-cat.is-active{background:rgba(var(--sel-rgb,var(--gold-rgb)),.13);color:var(--sel,var(--gold));box-shadow:inset 2px 0 0 0 var(--sel,var(--gold))}
.adv-cat.is-active .adv-cat-ic{opacity:1}
.adv-cat:disabled,.adv-cat[disabled]{opacity:.38;cursor:default}
.adv-panels{flex:1;min-width:0;max-height:62vh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding-right:2px} /* overflow-x:hidden : un contenu trop large (selects/inputs de la categorie Internet) faisait panner toute la fenetre lateralement au lieu de ne defiler qu'en vertical (constate narmod 2026-07-19) */
.adv-panel{display:none}
.adv-panel.is-active{display:block}
.adv-subtabs{display:flex;gap:var(--sp-2);margin:0 0 10px}
.adv-subtab{flex:1;padding:7px 6px;cursor:pointer;background:var(--inset);color:var(--text);border:1px solid var(--border);border-radius:var(--r-sm);font-size:var(--fs-base);font-weight:600;letter-spacing:0.02em;transition:background .15s,border-color .15s,color .15s}
.adv-subtab:hover{border-color:var(--border-hi);color:var(--text-hi)}
.adv-subtab.is-active{background:rgba(var(--sel-rgb,var(--gold-rgb)),.15);border-color:var(--sel,var(--gold));color:var(--sel,var(--gold))}
.adv-uipanel{display:none}
.adv-uipanel.is-active{display:block}
.adv-panels .adv-body{max-height:none;overflow:visible;margin-top:0}
/* Panneaux « reliés » : description + bouton d'accès à l'UI existante. */
.adv-link{display:flex;flex-direction:column;gap:var(--sp-5);align-items:flex-start;padding:6px 2px}
.adv-link-desc{font-size:var(--fs-base);line-height:1.4;color:var(--text)}
.adv-link-btn{align-self:stretch;padding:11px 14px;border-radius:var(--r-md);border:1px solid var(--gold-dim);background:rgba(var(--gold-rgb),.12);color:var(--gold);font-size:var(--fs-md);font-weight:700;cursor:pointer;transition:background .12s,border-color .12s,transform .08s}
.adv-link-btn:hover{background:rgba(var(--gold-rgb),.2);border-color:var(--gold)}
.adv-link-btn:active{transform:scale(.985)}
.adv-link-btn.adv-link-danger{border-color:var(--border-hi);background:transparent;color:var(--cream)}
.adv-link-btn.adv-link-danger:hover{background:var(--inset);border-color:var(--border-hi)}
.adv-srv{display:flex;align-items:center;gap:var(--sp-3);font-size:var(--fs-sm);color:var(--text);opacity:.82}
.adv-srv .adv-srv-host{color:var(--text);font-weight:600;font-family:var(--ff-mono,monospace);word-break:break-all}
.adv-soon-tag{display:inline-block;font-size:var(--fs-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--gold-dim,#b09a00);border:1px solid var(--border);border-radius:11px;padding:3px 10px;opacity:.85}
.adv-panel-off{opacity:.55}
/* Téléphone : la nav devient une barre d'icônes scrollable en haut (libellés cachés).
   Seuil 600 = canon QML (« compact » = largeur < 600), aligné sur le gate JS (_advSetupFloat). */
@media (max-width:599.98px){
  .adv-card{max-width:560px}
  .adv-layout{flex-direction:column;gap:10px}
  .adv-nav{flex:0 0 auto;flex-direction:row;gap:var(--sp-1);border-right:0;border-bottom:1px solid var(--border);padding:0 0 8px;max-height:none;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}
  .adv-cat{flex:0 0 auto;width:auto;padding:7px 10px;border-radius:var(--r-md);justify-content:center}
  .adv-cat .adv-cat-lbl{display:none}
  .adv-cat.is-active{background:rgba(var(--sel-rgb,var(--gold-rgb)),.16);box-shadow:inset 0 -2px 0 0 var(--sel,var(--gold))}
  .adv-panels{max-height:none;min-height:0} /* la hauteur vient de la carte épinglée ci-dessous */
}
/* Portrait mobile : carte ÉPINGLÉE haut et bas (feuille plein écran à marges,
   demande narmod 2026-07-19). Plus aucun saut de taille entre catégories :
   la hauteur est fixée par les ancres top/bottom, le contenu défile dedans.
   NB : l'ancienne approche height:56dvh sur .adv-panels était inopérante —
   flex:1 (= flex-basis:0%) écrase height sur l'axe principal d'une colonne. */
@media (max-width:599.98px) and (orientation:portrait){
  #adv-modal .adv-card{width:calc(100% - 20px);max-width:none;height:calc(100% - max(28px, 2*env(safe-area-inset-top), 2*env(safe-area-inset-bottom)));margin:0;display:flex;flex-direction:column;overflow:hidden} /* dimensionnee DANS #adv-modal (inset:0, flex centre) et non en position:fixed : un ancetre transforme detournait le fixed et decalait la feuille (constate narmod 2026-07-19). Hauteur constante -> aucun saut, centrage garanti par le flex du conteneur. */
  #adv-modal .adv-card .adv-layout{flex:1 1 auto;min-height:0}
  #adv-modal .adv-card .adv-nav{flex:0 0 auto}
  #adv-modal .adv-card .adv-panels{flex:1 1 auto;min-height:0;height:auto}
}
/* Options avancees en fenetre flottante (largeur >= 600, canon QML), pas sur mobile.
   Drag/resize/zoom via le systeme generique (cf. _advSetupFloat / _enableFloating). */
@media (min-width:600px){
  .adv-card{overflow:hidden;width:620px;height:min(82vh,640px);min-width:380px;min-height:360px;max-width:94vw;max-height:92vh} /* min-width 524→380 : aligné sur minW JS, la barre d'icônes (container query) légitime une fenêtre étroite */
  #adv-modal .adv-card.floating-win{position:fixed;margin:0;max-width:none;max-height:none} /* fenetre du systeme generique (_enableFloating) ; bornes gerees en JS (_clampWinToViewport) */ /* min-width 480→524 : compense la sidebar élargie (212 px) */
  .adv-card .adv-layout{flex:1 1 auto;min-height:0}
  .adv-card .adv-nav{max-height:none;min-height:0}
  .adv-card .adv-panels{max-height:none;min-height:0}
  .adv-card .km-title{cursor:move;user-select:none;touch-action:none}
}
/* Layout du dialogue piloté par la largeur de la FENÊTRE elle-même (container
   query), plus seulement par le viewport (demande narmod 2026-07-19) : une
   fenêtre flottante rétrécie sous 600 px passe en barre d'icônes (« portrait »),
   ré-élargie elle repasse en sidebar (« landscape ») — même logique responsive
   que le client QML applique à sa propre fenêtre, et même comportement que les
   autres fenêtres flottantes. Les règles @media restent telles quelles en repli
   (mobile + navigateurs sans container queries). Seuil 600 = canon QML. */
@container (max-width:599.98px){
  .adv-layout{flex-direction:column;gap:10px}
  .adv-nav{flex:0 0 auto;flex-direction:row;gap:var(--sp-1);border-right:0;border-bottom:1px solid var(--border);padding:0 0 8px;max-height:none;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}
  .adv-cat{flex:0 0 auto;width:auto;padding:7px 10px;border-radius:var(--r-md);justify-content:center}
  .adv-cat .adv-cat-lbl{display:none}
  .adv-cat.is-active{background:rgba(var(--sel-rgb,var(--gold-rgb)),.16);box-shadow:inset 0 -2px 0 0 var(--sel,var(--gold))}
}

/* ── Badge « main gagnante » sous les community cards (parité QML WinningHandBadge,
   bible 28/06 §9) : pastille vert sombre rgba(0.05,0.24,0.05,0.92), bord #FFD700,
   halo or. Dans .felt-oval → suit le zoom/pan comme les cartes. Visible pendant
   tout le showdown, masqué à la main suivante. top posé en JS (sous #g-comm). ── */
.win-hand-badge {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;                 /* au-dessus des cartes, sous les overlays */
  /* Taille suit communityScale (--comm-scale, posé sur <html>) — comme le
     badge du pot (.pot-badge) : le libellé de résultat (« Carte haute »,
     « Brelan d'As »…) s'adapte à l'écran au lieu d'un 12 px fixe. Base QML
     12 px bold, plancher 10 px. */
  padding: max(2px, calc(3px * var(--comm-scale, 1))) max(7px, calc(12px * var(--comm-scale, 1)));
  border-radius: var(--r-pill);
  background: rgba(13, 61, 13, 0.92);
  border: 1px solid #FFD700;
  box-shadow: 0 0 10px rgba(255, 215, 0, 0.45);
  color: #FFD700;              /* AppText QML : or #FFD700, 12 px bold */
  font-size: max(10px, calc(12px * var(--comm-scale, 1)));
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  pointer-events: none;
}
/* Pop d'apparition (winHandPop QML : scale 1→1.18 en 110 ms OutQuad puis
   retour 1.0 en 170 ms OutBack — léger passage sous 1.0 avant stabilisation). */
.win-hand-badge.win-pop { animation: winHandPop 0.28s ease-out; }
@keyframes winHandPop {
  0% { scale: 1; }
  39% { scale: 1.18; }
  82% { scale: 0.985; }
  100% { scale: 1; }
}

/* ── Mode « effets réduits » (parité QmlReduceEffects, bible §1) : coupe les
   effets décoratifs coûteux — ombres, glow, backdrop-filter — pour les
   appareils faibles. Opt-in : Options avancées → Tapis. ── */
html.reduce-fx *, html.reduce-fx *::before, html.reduce-fx *::after {
  box-shadow: none !important;
  text-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* Effets réduits : coupe AUSSI les animations « pop » des pucks
   (Dealer/SB/BB, drapeau — chipPop) et des badges d'action
   (seatBadgePop/stripPop) — demande sp0ck 2026-07-17. Les éléments
   apparaissent alors sans animation, à leur état final. */
html.reduce-fx .dealer-chip,
html.reduce-fx .blind-chip,
html.reduce-fx .seat-flag,
html.reduce-fx .seat-action-badge {
  animation: none !important;
}
/* Anti-replay (sp0ck 2026-07-17) : un re-render SANS changement d'état pour ce
   siège ne rejoue pas les pops (pucks/drapeau/badge) — classe posée par
   renderSeats quand la signature du siège est identique au rendu précédent. */
.dealer-chip.no-pop, .blind-chip.no-pop, .seat-flag.no-pop, .seat-action-badge.no-pop,
.seat-bet.no-pop {
  animation: none !important;
}

/* ── Icônes des 10 mains dans le moniteur d'odds (resources/hands/ QML) ── */
#odds-monitor .odds-ico {
  flex: 0 0 auto;
  width: calc(19px * var(--ws));
  height: calc(12.5px * var(--ws));
  opacity: 0.9;
}

/* ── LobbyStatsBar (parité QML) : bandeau discret sous la liste des tables ── */
.lobby-statsbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 5px 10px;
  font-size: var(--fs-xs);
  color: var(--text-dim, #8b93a7);
  border-top: 1px solid var(--line, #2c3548);
}
.lobby-statsbar a { color: var(--gold-dim, #9a824a); text-decoration: none; }
.lobby-statsbar a:hover { text-decoration: underline; }

/* ── Sondages produit (modale lobby, extension web) ───────────────────────
   Meme moule que la modale de bienvenue du monolithe : fond assombri, carte
   centree, tokens de theme. Voir modules/ui/poll.mjs. */
.poll-back {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center; padding: 18px;
  background: rgba(0, 0, 0, .55);
}
.poll-card {
  max-width: 420px; width: 100%; max-height: 84vh;
  display: flex; flex-direction: column;
  background: var(--modal-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .5);
}
.poll-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 18px; border-bottom: 1px solid var(--border);
}
.poll-title {
  font-family: var(--ff-display); font-weight: 700;
  font-size: var(--fs-3xs, .6rem); letter-spacing: .15em; text-transform: uppercase;
  color: var(--gold-dim, #9a824a);
}
.poll-x {
  border: 0; background: none; cursor: pointer; padding: 0 2px; line-height: 1;
  font-size: .85rem; color: var(--text-dim, #8b93a7);
}
.poll-x:hover { color: var(--text-hi, #e8ecf5); }
.poll-body { padding: 16px 18px; overflow: auto; display: flex; flex-direction: column; gap: 12px; }
.poll-q { font-size: .95rem; line-height: 1.45; color: var(--text-hi, #e8ecf5); }
.poll-opts { display: flex; flex-direction: column; gap: 7px; }
.poll-opt {
  width: 100%; text-align: left;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--border, #39435a);
  background: var(--panel, #232b3b); color: var(--text, #c3cad9);
  font-size: .88rem; cursor: pointer;
}
.poll-opt:hover:not(:disabled) { border-color: var(--gold-dim, #9a824a); color: var(--text-hi, #e8ecf5); }
.poll-opt:disabled { opacity: .5; cursor: default; }
.poll-err:empty { display: none; }
.poll-err { font-size: var(--fs-xs, .72rem); color: var(--red, #d94040); }
/* Resultats : une ligne par option, barre proportionnelle, choix de
   l'utilisateur souligne par l'accent or. */
.poll-res { display: flex; flex-direction: column; gap: 6px; }
.poll-row { display: flex; align-items: center; gap: 8px; font-size: .82rem; }
.poll-lb { flex: 0 0 38%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text, #c3cad9); }
.poll-row.is-mine .poll-lb { color: var(--gold, #e3c800); }
.poll-track { flex: 1; min-width: 0; height: 7px; border-radius: 4px; background: var(--inset, rgba(0,0,0,.28)); overflow: hidden; }
.poll-track i { display: block; height: 100%; border-radius: 4px; background: var(--gold-dim, #9a824a); }
.poll-row.is-mine .poll-track i { background: var(--gold, #e3c800); }
.poll-pct { flex: 0 0 34px; text-align: right; color: var(--text-dim, #8b93a7); }
.poll-foot { font-size: var(--fs-3xs, .6rem); color: var(--text-dim, #8b93a7); }

/* Palettes officielles : pas de trait au-dessus de la statsbar (parite QML). */
:root[data-theme^="pokerth"] .lobby-statsbar { border-top: none; }

/* ── Page « À propos de PokerTH » (parité AboutPage QML 2.1.3) ── */
#about-page { position:fixed; inset:0; z-index:120; display:none; flex-direction:column; background:var(--felt); overflow-y:auto; }

/* ── Page Privacy in-app : même entête cp-header que « Créer une partie ». ── */
#privacy-page { position:fixed; inset:0; z-index:120; display:none; flex-direction:column; background:var(--felt); }
.pv-scroll { flex:1; overflow-y:auto; }
.pv-body { max-width:720px; margin:0 auto; padding:10px 18px 48px; color:var(--text); font-size:var(--fs-md); line-height:1.65; }
.pv-updated { color:var(--text-dim); font-size:var(--fs-base); margin:4px 0 14px; }
.pv-body h2 { color:var(--text-hi); font-size:var(--fs-lg); margin:22px 0 8px; padding-top:16px; border-top:1px solid var(--border-hi); }
.pv-body h2:first-of-type { border-top:0; padding-top:0; }
.pv-body a { color:var(--gold); }
.pv-body strong { color:var(--text-hi); font-weight:600; }
.pv-body ul { padding-left:20px; }
.pv-body li { margin:5px 0; }
.ab-head { display:flex; align-items:center; padding:10px 10px 0; flex-shrink:0; }
.ab-back { background:none; border:none; cursor:pointer; color:var(--text-hi); font-size:1.7rem; line-height:1; padding:2px 12px; border-radius:8px; }
.ab-back:hover { background:var(--inset-hi); }
.ab-title { font-size:1.25rem; font-weight:700; color:var(--text-hi); padding:4px 16px 10px; flex-shrink:0; }
.ab-tabs { display:flex; margin:0 16px; flex-shrink:0; }
.ab-tab { flex:1 1 0; min-width:0; border:none; cursor:pointer; padding:8px 6px; font-size:var(--fs-base); color:var(--text-hi); background:var(--inset); font-family:var(--ff-display); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ab-tab.active { background:var(--panel-hi); font-weight:600; }
:root[data-theme="pokerth-light"] .ab-tab { background:#dfe3ea; }
:root[data-theme="pokerth-light"] .ab-tab.active { background:#a9b2c6; }
.ab-body { flex:1 1 auto; padding:14px 16px 28px; }
.ab-logo { text-align:center; margin:8px 0 16px; }
.ab-suits { font-size:var(--fs-md); letter-spacing:0.3em; margin-top:8px; opacity:0.9; color:var(--text-hi); }
.ab-suits .r { color:#c0392b; }
.ab-vername { font-weight:700; font-size:var(--fs-lg); margin-top:8px; color:var(--text-hi); }
.ab-feats { margin:14px 0; color:var(--text-hi); font-size:var(--fs-md); line-height:1.75; }
.ab-copy { color:var(--text); font-size:var(--fs-base); margin-top:10px; }
.ab-net { text-align:right; margin-top:16px; }
.ab-pane a { color:var(--info,#2a6fb0); }
.ab-pane p { color:var(--text-hi); font-size:var(--fs-md); line-height:1.6; max-width:820px; }
.ab-pane ul { color:var(--text-hi); font-size:var(--fs-md); line-height:1.9; padding-left:22px; }

/* ── Galerie d'avatars d'exemple (client Qt-Widgets officiel) ── */
.avgal-overlay {
  position: fixed; inset: 0; z-index: 1200;
  display: none; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.55);
}
.avgal-box {
  position: relative;
  background: var(--panel, #1c2230);
  border: 1px solid var(--line, #2c3548);
  border-radius: 14px;
  width: min(560px, 92vw);
  max-height: 80vh;
  display: flex; flex-direction: column;
  padding: 14px;
}
.avgal-title {
  font-weight: 700; margin: 0 22px 8px 0;
  color: var(--gold, #c8a84a);
  letter-spacing: 0.06em; text-transform: uppercase; font-size: var(--fs-sm);
}
.avgal-body { overflow-y: auto; }
.avgal-cat {
  margin: 10px 0 6px; font-size: var(--fs-xs);
  color: var(--text-dim, #8b93a7);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.avgal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
  gap: var(--sp-2);
}
.avgal-item {
  padding: 0; border: 1px solid transparent; border-radius: 8px;
  background: transparent; cursor: pointer;
}
.avgal-item:hover, .avgal-item:focus-visible { border-color: var(--gold, #c8a84a); }
.avgal-item img {
  width: 100%; aspect-ratio: 1; display: block;
  border-radius: 7px; object-fit: cover;
}

/* ── Picker emoji complet : panneau plus haut + titres de sections ── */
.chat-emoji-panel { max-height: 180px; }
.chat-emoji-sec {
  grid-column: 1 / -1;
  font-size: var(--fs-2xs);
  color: var(--text-dim, #8b93a7);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 4px 2px 1px;
}

/* ── Indicateur de ping sur mon avatar (opt-in, coin de la player bar) ── */
.player-bar-left { position: relative; }
.ping-dot {
  position: absolute;
  left: 1px; top: 1px;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 1.5px solid var(--panel, #1c2230);
  z-index: 3;
  pointer-events: none;
}

/* ── Activité joueur dans le panneau « Joueurs » : 🎮 nom de la table ── */
/* Variante A : sections « En partie / Au lobby » ; le nom de la table
   redevient une sous-ligne discrète sous le pseudo. */
.pl-row .pl-game {
  display: block;
  font-size: var(--fs-2xs);
  color: var(--text-dim, #8b93a7);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  line-height: 1.2;
}
.players-list .pl-sec {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 2px 4px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-dim, #c8a84a);
  border-bottom: 1px solid var(--inset, rgba(255,255,255,0.08));
}
.players-list .pl-sec-n { color: var(--text-dim, #8b93a7); font-weight: 600; }

/* ── Bouton « Show » post-main : flotte AU-DESSUS de mes cartes (player bar),
   pastille or, visible seulement pendant la fenêtre d'attente. ── */
.pb-cards { position: relative; }
.show-cards-btn {
  position: absolute;
  left: 50%;
  top: -26px;
  transform: translateX(-50%);
  z-index: 6;
  padding: 3px 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--gold, #c8a84a);
  background: var(--panel, #1c2230);
  color: var(--gold, #c8a84a);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}
.show-cards-btn:hover { background: var(--gold, #c8a84a); color: #1c2230; }

/* ===== Boutons d'action : pack « PokerTH » (axe data-buttons="pokerth") ====
   GameActionBar.qml au pixel : radius 9, dégradé Top→Bottom par action
   (§12.3), bord = couleur Edge, police 15px bold letterSpacing .5 (12px en
   landscapeCompact), rangée 54px (40px landscapeCompact), press scale .96
   (90ms). « Call $X » passe sur 2 lignes en portrait (1 ligne en compact). */
html[data-buttons="pokerth"] .btn-action {
  border-radius: var(--r-md);
  font-weight: 700;
  letter-spacing: 0.5px;
  font-size: calc(15px * var(--bar-kf, 1));
  color: #fff;
  min-height: calc(54px * var(--bar-k, 1));
  border-width: 1px;
  border-style: solid;
  transition: transform 0.09s ease-out;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
html[data-buttons="pokerth"] .btn-action:active:not([disabled]) { transform: scale(0.96); }
html[data-buttons="pokerth"] .btn-fold {
  background: linear-gradient(to bottom, #d94040, #8b1a1a); border-color: #e87070;
}
html[data-buttons="pokerth"] .btn-call,
html[data-buttons="pokerth"] .btn-check {
  background: linear-gradient(to bottom, #4080d8, #1a3d8b); border-color: #6aa0e8;
}
html[data-buttons="pokerth"] .btn-raise {
  background: linear-gradient(to bottom, #50b840, #1e6614); border-color: #7ad06a;
}
html[data-buttons="pokerth"] .btn-allin {
  background: linear-gradient(to bottom, #9e2a2a, #5c1111); border-color: #ef5350;
}
html[data-buttons="pokerth"] .btn-action[disabled] { filter: grayscale(0.55) brightness(0.7); }
/* Portrait : montant du Call/All-In sur une 2e ligne (libellé QML 2 lignes). */
@media (orientation: portrait) {
  html[data-buttons="pokerth"] .btn-call b,
  html[data-buttons="pokerth"] .btn-allin b { display: block; font-size: 0.88em; line-height: 1.15; }
}
/* landscapeCompact (bible §2) : rangée 40px, police 12px, 1 ligne.
   Mobile = paysage h<600 ; desktop = ratio>2.1 && h<1300 (un 16:9 MAXIMISE,
   ratio ~1.91, reste non-compact — aligne sur le client officiel 2.1.1). */
@media (orientation: landscape) and (max-height: 600px),
       (min-aspect-ratio: 210/100) and (max-height: 799px) {
  html[data-buttons="pokerth"] .btn-action { min-height: 40px; font-size: 12px; padding-top: 6px; padding-bottom: 6px; }
}

/* ── Lueur chaude derrière les cartes communes (bible §9 :
   rgba(1, 0.93, 0.72, 0.12) floutée). ::before sous les cartes. ── */
#g-comm { position: relative; isolation: isolate; }
#g-comm::before {
  content: '';
  position: absolute;
  inset: -16px -24px;
  background: radial-gradient(ellipse at center, rgba(255, 237, 184, 0.12), transparent 70%);
  filter: blur(10px);
  z-index: -1;
  pointer-events: none;
}

/* ── Pop du badge de pot à chaque hausse (bible §9). ── */
@keyframes potPop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.16); }
  100% { transform: scale(1); }
}
.pot-pop { animation: potPop 0.3s ease-out; display: inline-block; }

/* ── Tri du panneau Joueurs (A–Z / pays) + 5e pastille de filtre ── */
.players-search { display: flex; align-items: center; gap: var(--sp-2); }
.players-search input { flex: 1; min-width: 0; }
.pl-sort { display: flex; gap: var(--sp-0); flex: none; }
.pl-sort-btn {
  background: var(--inset, rgba(255,255,255,0.06));
  border: 1px solid var(--border, rgba(255,255,255,0.14));
  border-radius: 8px;
  color: var(--text-dim, #8b93a7);
  cursor: pointer;
  font-size: var(--fs-2xs);
  font-weight: 700;
  padding: 5px 8px;
  line-height: 1;
}
.pl-sort-btn.active {
  color: var(--gold, #c8a84a);
  border-color: var(--gold-dim, #c8a84a);
}
.filter-chips { flex-wrap: wrap; }

/* ═══════════════════════════════════════════════════════════════════
   Lobby responsive v2 — parité QML LobbyPage (Phase 1b)
   ≥900 : 3 colonnes REDIMENSIONNABLES (poignées ; voisins suivent).
          Colonne droite = Infos (haut) / Chat (bas) + séparateur vertical.
   <900  : Parties + Chat INTÉGRÉ (empilés) ; Joueurs & Infos en slide-in.
   ═══════════════════════════════════════════════════════════════════ */

#s-lobby .lobby-grid > .create-col { display: none; }

/* Barre du bas : Joueur + Créer une partie (les 2 modes, épinglée en pied) */
.lobby-footbar { display:flex; align-items:center; gap:var(--sp-5); padding:8px 14px;
  border-top:1px solid var(--border); background:var(--panel); flex-shrink:0;
  position:sticky; bottom:0; z-index:20; }
.lobby-footbar .lfb-name { color:var(--text-hi); font-weight:700; font-size:var(--fs-base); white-space:nowrap; }
.lobby-footbar .lfb-name b { color:var(--gold); }
/* Boutons de la barre du bas. Forme commune : largeurs ÉGALES et adaptatives —
   « Joueur : … » (nowrap) garde sa place et les boutons rétrécissent quand le
   pseudo est long (flex:1 1 0 + min-width:0 + ellipsis). Couleurs : Rejoindre en
   vert et Spectateur en bleu (comme les boutons des lignes) ; Créer en or/neutre. */
.lobby-footbar .lfb-create,
.lobby-footbar .lfb-join,
.lobby-footbar .lfb-spectate {
  flex:1 1 0; min-width:0; text-align:center;
  border:1px solid transparent; border-radius:8px; padding:9px 14px; cursor:pointer;
  font-family:var(--ff-display); font-weight:600; font-size:var(--fs-md);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Créer : palette QML (or/neutre) */
.lobby-footbar .lfb-create { border-color:transparent; background:#2b3444; color:#ffffff; }
.lobby-footbar .lfb-create:hover { background:#384252; }
/* Palette claire : bouton gris neutre (col500 light), texte sombre (parite QML). */
:root[data-theme="pokerth-light"] .lobby-footbar .lfb-create { background:#c0c2c6; color:#1d222b; }
:root[data-theme="pokerth-light"] .lobby-footbar .lfb-create:hover { background:#b2b4b9; }
/* Portrait/compact (palette claire) : barre posée sur le fond blanc QML #f0f3f8,
   sans trait -> plus de cadre visible autour de « Joueur / Créer une partie ». */
@media (max-width: 899.98px) {
  :root[data-theme="pokerth-light"] .lobby-footbar { background:#f0f3f8; border-top:none; }
}
/* Rejoindre : vert (identique au bouton Rejoindre des lignes) */
.lobby-footbar .lfb-join { border-color:var(--green); background:rgba(var(--green-rgb),0.12); color:var(--green); }
.lobby-footbar .lfb-join:hover { background:rgba(var(--green-rgb),0.28); }
/* Spectateur : bleu (identique au bouton Spectateur des lignes) */
.lobby-footbar .lfb-spectate { border-color:rgba(var(--blue-rgb),0.55); background:rgba(var(--blue-rgb),0.12); color:var(--info); }
.lobby-footbar .lfb-spectate:hover { background:rgba(var(--blue-rgb),0.22); }

/* Mobile (téléphone) : le pseudo passe sur sa propre ligne et les boutons
   Rejoindre/Spectateur/Créer se placent EN DESSOUS, côte à côte à parts égales
   (sinon 3 éléments sur une ligne étroite tronquent les libellés). */
@media (max-width: 599.98px) {
  .lobby-footbar { flex-wrap:wrap; }
  .lobby-footbar .lfb-name { flex:1 1 100%; }
  /* Mobile : Rejoindre/Spectateur uniquement sur les cartes de table.
     On masque leurs doublons de la barre du bas (pseudo + Créer restent). */
  .lobby-footbar .lfb-join,
  .lobby-footbar .lfb-spectate { display: none; }
}

/* Desktop / tablette (largeur >= 600, canon QML) : Rejoindre/Spectateur uniquement via la barre du
   bas (sur la table selectionnee). On retire leurs doublons sur chaque carte —
   la ligne reste cliquable pour selectionner la table. */
@media (min-width: 600px) {
  #s-lobby .game-row.gcard .btn-join { display: none; }
}

/* Infos placeholder (rempli en Phase 2) */
#lobby-gameinfo { display:none; flex-direction:column; }
#lobby-gameinfo .lgi-empty { flex:1 1 auto; display:flex; align-items:center; justify-content:center;
  color:var(--text-dim,#8b93a7); font-size:var(--fs-sm); padding:18px; text-align:center; }

/* Chat toujours présent → on masque son bouton de fermeture et son trigger header */
#lobby-chat-panel .g-chat-panel-header button[onclick*="toggleLobbyChat"] { display:none; }
#lobby-chat-btn { display:none !important; }
/* Corps du chat : remplit le panneau (override du max-height:120px inline) — 2 modes */
#s-lobby .lobby-grid > #lobby-chat-panel .chat-msgs {
  flex:1 1 auto !important; min-height:0 !important; max-height:none !important; overflow-y:auto;
}

/* Poignées de redimensionnement (wide) — occupent leur piste de grille */
.lob-h { display:none; position:relative; }
.lob-h::after { content:''; position:absolute; background:var(--border); transition:background .12s; }
.lob-h:hover::after, .lob-h.drag::after { background:var(--gold); }
.lob-h-l, .lob-h-r { cursor:col-resize; }
.lob-h-l { grid-area:hl; } .lob-h-r { grid-area:hr; } .lob-h-v { grid-area:hv; cursor:row-resize; }
.lob-h-l::after, .lob-h-r::after { top:0; bottom:0; left:50%; width:2px; transform:translateX(-50%); }
.lob-h-v::after { left:0; right:0; top:50%; height:2px; transform:translateY(-50%); }

/* Scrim pour les slide-in mobiles */
.lob-scrim { display:none; position:fixed; inset:0; background:rgba(0,0,0,0.45); z-index:98; }
.lob-scrim.on { display:block; }

/* ── WIDE ≥900 : 3 colonnes redimensionnables ── */
@media (min-width: 900px) {
  #s-lobby { overflow:hidden; }
  #s-lobby .lobby-body { flex:1 1 auto; min-height:0; overflow:hidden; display:flex; flex-direction:column; padding:12px 14px; }
  #s-lobby .lobby-grid {
    position:relative; flex:1 1 auto; min-height:0; gap:0; display:grid;
    grid-template-columns:
      minmax(160px, min(var(--lc-l,240px), 30%)) 12px
      minmax(280px, 1fr) 12px
      minmax(200px, min(var(--lc-r,300px), 30%));
    grid-template-rows: minmax(120px, min(var(--lc-info,220px), 60%)) 12px minmax(120px,1fr) auto;
    grid-template-areas:
      "players hl games hr info"
      "players hl games hr hv"
      "players hl games hr chat"
      "players hl foot  hr chat";
    align-items:stretch;
  }
  /* Barre du bas (Joueur + Créer) : rangée dédiée SOUS la colonne Parties,
     hors du cadre du panneau (parité QML : la barre est posée sur le fond). */
  #s-lobby .lobby-grid > .lobby-footbar {
    grid-area:foot; position:static; z-index:auto;
    background:transparent; border-top:none; padding:10px 0 0;
  }
  .lob-h { display:block; }

  #s-lobby .lobby-grid > #players-panel    { grid-area:players; }
  #s-lobby .lobby-grid > .games-col        { grid-area:games; }
  #s-lobby .lobby-grid > #lobby-gameinfo   { grid-area:info; display:flex; }
  #s-lobby .lobby-grid > #lobby-chat-panel { grid-area:chat; }

  /* Ma partie en attente : liste (games) à droite ; mes infos (info) + le chat
     au centre. Simple ré-affectation des zones — le contenu ne bouge pas. */
  #s-lobby.lobby-waiting .lobby-grid {
    grid-template-areas:
      "players hl info hr games"
      "players hl hv   hr games"
      "players hl chat hr games"
      "players hl foot hr games";
  }

  /* Panneaux : sortis du mode overlay → posés statiquement dans leur colonne */
  #s-lobby .lobby-grid > #players-panel,
  #s-lobby .lobby-grid > #lobby-gameinfo,
  #s-lobby .lobby-grid > #lobby-chat-panel {
    position:static !important; inset:auto !important; transform:none !important;
    width:auto !important; height:auto !important; max-height:none !important; margin:0 !important;
    box-shadow:none; border:1px solid var(--border); border-radius:8px;
    background:var(--panel); min-height:0;
  }
  #s-lobby .lobby-grid > #players-panel,
  #s-lobby .lobby-grid > #lobby-chat-panel { display:flex !important; }

  #s-lobby .lobby-grid > #players-panel .players-list,
  #s-lobby .lobby-grid > #lobby-chat-panel .chat-msgs {
    flex:1 1 auto; min-height:0; max-height:none !important; overflow-y:auto;
  }
  #s-lobby .lobby-grid > .games-col { display:flex; flex-direction:column; min-height:0; overflow:hidden; }
  #s-lobby .lobby-grid > #players-panel,
  #s-lobby .lobby-grid > #lobby-gameinfo,
  #s-lobby .lobby-grid > #lobby-chat-panel { overflow:hidden; min-width:0; }
  #s-lobby .lobby-grid > .games-col .games-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; align-content:start; }

  #s-lobby #h-players { display:none !important; }
  #s-lobby .lobby-grid > #players-panel .g-chat-panel-header button[onclick*="togglePlayersPanel"] { display:none; }
}

/* ── COMPACT <900 : Parties + Chat intégrés ; Joueurs/Infos en slide-in ── */
@media (max-width: 899.98px) {
  #s-lobby { overflow:hidden; }
  #s-lobby .lobby-body { flex:1 1 auto; min-height:0; overflow:hidden; display:flex; flex-direction:column; padding:10px 10px; }
  #s-lobby .lobby-grid { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:var(--sp-3); align-items:stretch; }
  .lob-h { display:none !important; }

  #s-lobby .lobby-grid > .games-col { order:1; flex:0 0 clamp(120px, var(--m-games-h, 52%), 62%); min-height:0; display:flex; flex-direction:column; }
  #s-lobby .lobby-grid > .games-col .games-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; align-content:start; }

  /* Chat intégré sous les tables (plus de fenêtre flottante ni d'overlay) */
  #s-lobby .lobby-grid > #lobby-chat-panel {
    order:3; position:static !important; inset:auto !important; transform:none !important;
    display:flex !important; width:auto !important; flex:1 1 0; min-height:140px;
    max-height:none !important; box-shadow:none; z-index:auto;
    border:1px solid var(--border); border-radius:8px;
  }

  /* Joueurs : slide-in depuis la gauche */
  #s-lobby .lobby-grid > #players-panel {
    position:fixed !important; top:var(--ovl-top,48px); bottom:0; left:0; right:auto !important;
    width:min(320px,84vw); max-height:none !important; display:flex !important;
    transform:translateX(-100%); transition:transform .22s ease; z-index:100; border-radius:0;
    box-shadow:none; background:var(--panel);
  }
  #s-lobby.pl-open .lobby-grid > #players-panel { transform:translateX(0); box-shadow:2px 0 22px rgba(0,0,0,0.55); }

  /* Infos : slide-in depuis la droite (contenu Phase 2) */
  #s-lobby .lobby-grid > #lobby-gameinfo {
    position:fixed !important; top:var(--ovl-top,48px); bottom:0; right:0; left:auto;
    width:min(340px,88vw); display:flex !important; max-height:none !important; border-radius:0;
    transform:translateX(100%); transition:transform .22s ease; z-index:100;
    box-shadow:none; border-left:1px solid var(--border); background:var(--panel);
  }
  #s-lobby.gi-open .lobby-grid > #lobby-gameinfo { transform:translateX(0); box-shadow:-2px 0 22px rgba(0,0,0,0.55); }
}

/* Barre de stats : tout en bas, pleine largeur (déplacée hors de la colonne Parties) */
.lobby-statsbar { flex-shrink:0; }

/* Bouton Joueurs (👥) dans la barre de filtre — mobile seulement (parité photo) */
.fbar-players { display:none; }
@media (max-width: 899.98px) {
  .fbar-players {
    display:inline-flex; align-items:center; justify-content:center;
    width:36px; height:32px; flex:0 0 auto; border:1px solid var(--border);
    border-radius:8px; background:var(--inset); cursor:pointer; font-size:var(--fs-md); line-height:1;
  }
  .fbar-players:hover { border-color:var(--gold-dim); }
  #h-players { display:none !important; }   /* redondant avec le bouton de la barre de filtre */
}

/* ── Barre du haut du lobby : recherche joueur + filtre parties, au-dessus des colonnes ── */
.lobby-topbar { display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap; flex-shrink:0; padding:0 0 10px; }
.lobby-topbar .players-search {
  flex:1 1 280px; display:flex; align-items:center; gap:var(--sp-2);
  padding:0 !important; background:transparent !important; border:none !important;
}
.lobby-topbar .players-search input { flex:1 1 auto; width:auto; }
.lobby-topbar #g-filter-bar { flex:1 1 260px; padding:0 !important; margin:0; display:flex; align-items:center; gap:var(--sp-3); }
.lobby-topbar #g-filter-bar .gfilt-wrap { flex:1 1 auto; }
/* En mobile la barre s'empile proprement (recherche puis filtre) */
@media (max-width: 899.98px) {
  .lobby-topbar { gap:var(--sp-3); padding:0 0 8px; }
  .lobby-topbar .players-search { flex:1 1 100%; }
  .lobby-topbar #g-filter-bar { flex:1 1 100%; }
}

/* Colonne Parties : encadrée + fond plein comme les 3 autres colonnes
   (bordure/rayon/fond identiques ; supprime aussi le fond rayé qui traversait). */
#s-lobby .lobby-grid > .games-col {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  padding: var(--sp-3);
}

/* Header « Tables disponibles » : collé aux bords de la colonne (annule le
   padding 8px) → même forme pleine-largeur que les headers des 3 autres
   panneaux ; overflow:hidden + border-radius de .games-col arrondissent ses
   coins hauts pour un rendu identique. */
#s-lobby .lobby-grid > .games-col > .g-chat-panel-header {
  margin: -8px -8px 8px;
}

/* Poignée de redimensionnement Tables/Chat — MOBILE uniquement (SplitView vertical) */
.lob-hm { display:none; }
@media (max-width: 899.98px) {
  .lob-hm {
    display:block; order:2; flex:0 0 16px; position:relative;
    cursor:row-resize; touch-action:none;
  }
  .lob-hm::after {
    content:''; position:absolute; left:30%; right:30%; top:50%; height:4px;
    transform:translateY(-50%); background:var(--border); border-radius:var(--r-xs);
  }
  .lob-hm:active::after, .lob-hm.drag::after { background:var(--gold); }
}

/* ── Panneau « Infos de partie » (contenu, parité officielle) ── */
#lobby-gameinfo .g-chat-panel-header { display:flex; align-items:center; justify-content:space-between; }
#lobby-gameinfo .lgi-htitle { font-size:var(--fs-xs); color:var(--gold-dim); letter-spacing:0.12em; text-transform:uppercase; font-weight:600; }
.lgi-report { background:none; border:none; cursor:pointer; font-size:var(--fs-md); line-height:1; padding:0 2px; opacity:0.85; }
.lgi-report:hover { opacity:1; transform:scale(1.05); }
.lgi-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; padding:10px 12px; display:flex; flex-direction:column; gap:var(--sp-2); }
.lgi-row { font-size:var(--fs-base); color:var(--text); display:flex; align-items:center; gap:var(--sp-2); }
.lgi-row .lgi-ico { opacity:0.85; }
.lgi-blinds { color:var(--text-dim,#8b93a7); }
.lgi-ptitle { font-weight:700; color:var(--text); font-size:var(--fs-base); margin-top:6px; }
.lgi-players { display:flex; flex-direction:column; gap:5px; }
.lgi-gname { font-weight:700; color:var(--cream); font-size:var(--fs-md); }
/* Barre du bas (centre) : options d'attente qui remplacent « + Créer une
   partie » quand je suis dans une partie non démarrée (parité officiel). */
#lobby-wait-actions {
  flex:0 0 auto;
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px;
  padding:10px 12px; border-top:1px solid var(--border);
}
/* En mode « ma partie en attente », la barre du bas (Joueur/Créer) n'a plus
   lieu d'être : les actions Démarrer/Quitter sont au centre, sous le chat. */
#s-lobby.lobby-waiting .lobby-footbar { display:none; }
#lobby-wait-actions .wp-fillbots { flex:1 1 100%; justify-content:center; padding:var(--sp-0); }
#lobby-wait-actions .wp-actions { flex:1 1 auto; display:flex; gap:var(--sp-4); width:100%; }
#lobby-wait-actions .wp-actions .wp-btn { flex:1 1 auto; }
#lobby-wait-actions .lfb-waithint { flex:1 1 100%; font-size:var(--fs-xs); color:var(--gold-dim); font-style:italic; text-align:center; }
.lgi-prow { display:flex; align-items:center; gap:var(--sp-3); padding:6px 8px; border-radius:var(--r-sm); background:var(--inset); border:1px solid var(--border); }
.lgi-pname { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:var(--fs-base); color:var(--text); }
.lgi-prow.lgi-pending { opacity:0.6; }
/* Ligne joueur cliquable (popup joueur, comme la liste « Joueurs en ligne ») :
   curseur main, AUCUN soulignement/ligne, juste le pseudo qui passe or au survol. */
.lgi-prow.lgi-click { cursor:pointer; -webkit-tap-highlight-color:transparent; }
.lgi-prow.lgi-click, .lgi-prow.lgi-click .lgi-pname { text-decoration:none; }
.lgi-prow.lgi-click:hover .lgi-pname, .lgi-prow.lgi-click:active .lgi-pname { color:var(--gold-hi); }
.lgi-prow.lgi-click:focus { outline:none; }
.lgi-prow.lgi-click:focus-visible { border-color:var(--gold-hi); }
.lgi-pempty { color:var(--text-dim,#8b93a7); font-size:var(--fs-sm); padding:var(--sp-3); }

/* Ligne de partie sélectionnée */
.game-row.gcard.sel { border-color:var(--gold); box-shadow:0 0 0 1px var(--gold) inset; background:rgba(var(--gold-rgb),0.06); }
/* Palette claire : selection = fond kaki plein (accent or #E3C800 sur col600),
   sans liseré or sombre (parite QML). */
:root[data-theme="pokerth-light"] .game-row.gcard.sel {
  border-color:transparent; box-shadow:none; background:rgba(227,200,0,0.28);
}

/* Heure des messages de chat [HH:MM:SS] — gris discret, monospace (parité officielle) */
.msg .msg-time { color: var(--text-dim, #8b93a7); font-family: var(--ff-mono, monospace); font-size: 0.88em; margin-right: 2px; }
.st-tabbar::-webkit-scrollbar { display: none; } /* barre d'onglets styles coulissante : scrollbar masquée */
.adv-no-chatts .msg .msg-time { display: none; } /* option « heure dans le chat » decochee */

/* Icônes d'action par joueur (colonne Joueurs connectés) : ⊘ ignorer + 📊 stats */
.players-list .pl-row .pl-acts { display:inline-flex; align-items:center; gap:var(--sp-0); justify-self:end; margin-left:0; }
.pl-act { background:none; border:none; padding:3px; cursor:pointer; color:var(--gold-dim,#9a824a); display:inline-flex; align-items:center; border-radius:4px; line-height:0; }
/* Colonne « Inviter » (page d'attente) : icône verte, état envoyé estompé. */
.pl-act-inv { color:var(--green); }
.pl-act-inv:hover { background:var(--inset-hi); }
.pl-act-inv.sent { opacity:.45; cursor:default; }
.pl-act:hover { color:var(--gold); background:rgba(var(--gold-rgb),0.12); }
.pl-act.pl-act-ban.on { color:var(--red,#e05050); }

/* Déroulant de tri en bas de la colonne Joueurs connectés (parité officielle) */
.pl-sortbar { flex:0 0 auto; padding:6px 8px; border-top:1px solid var(--border); background:var(--chrome-tint,var(--panel)); }
.pl-sortbar .sel-wrap { width:100%; }

/* En-tête colonnes (afficher/masquer) de la liste « Joueurs en ligne ».
   Rendu comme 1er enfant STICKY du corps scrollable → partage la largeur et la
   gouttière de scroll des lignes. Grille alignée sur les .pl-row : mêmes pistes
   (gabarit complet posé en inline) + même gap 8px + padding latéral 0 (le 12px
   latéral vient du padding du conteneur). Chaque pastille remplit sa cellule
   (width:100%) → elle s'élargit avec la colonne. Le Nom = cellule vide. */
.pl-colhead {
  position:sticky; top:0; z-index:2;
  display:grid; align-items:center; gap:var(--sp-3);
  padding:4px 12px 6px; margin:0 -12px 2px;
  background:linear-gradient(var(--chrome-tint),var(--chrome-tint)),var(--panel); border-bottom:1px solid var(--border);
}
.pl-colh-spacer { min-width:0; }
.pl-colh-chip {
  box-sizing:border-box; width:100%;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--field-bg); border:1px solid var(--border); border-radius:var(--r-xs);
  padding:3px 0; cursor:pointer; line-height:0;
  color:var(--gold-dim); opacity:0.7;
}
.pl-colh-chip:hover { background:rgba(var(--gold-rgb),0.12); }
.pl-colh-chip.on { color:var(--gold); opacity:1; border-color:rgba(var(--gold-rgb),0.35); background:rgba(var(--gold-rgb),0.10); }
.pl-colh-lock { cursor:default; }
.pl-colh-lock:hover { background:rgba(var(--gold-rgb),0.10); }
.pl-colh-star { font-size:var(--fs-base); line-height:1; }

/* Colonne statut « en partie » : manette allumée (vert) si le joueur joue, éteinte sinon */
.players-list .pl-row .pl-status { flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; width:22px; color:var(--border); line-height:0; }
.players-list .pl-row .pl-status.on { color:var(--green,#50c878); }

/* Nom du joueur dans la barre du bas : cliquable → ouvre le profil */
.lobby-footbar .lfb-name-link { cursor:pointer; text-decoration:none; }
.lobby-footbar .lfb-name-link:hover { color:var(--gold-hi,var(--gold)); }


/* Voile derrière les slide-in Joueurs/Infos en compact (assombrit le fond,
   clic = fermeture). Le panneau lui-même a un fond opaque var(--panel). */
#s-lobby .lob-scrim { position:fixed; top:var(--ovl-top,48px); left:0; right:0; bottom:0; background:rgba(0,0,0,0.5); z-index:98; opacity:0; pointer-events:none; transition:opacity .22s ease; }
#s-lobby .lob-scrim.on { opacity:1; pointer-events:auto; }

/* Avatar avant le nom dans la barre du bas du lobby */
#lobby-foot-av { display:inline-flex; align-items:center; vertical-align:middle; margin-right:6px; }
#lobby-foot-av .pl-av { width:20px; height:20px; }

/* Bouton « Spectateur » (parties en cours) : même gabarit que Rejoindre, teinte bleue */
.game-row.gcard .btn-spectate {
  border-color: rgba(var(--blue-rgb), 0.55);
  background: rgba(var(--blue-rgb), 0.12);
  color: var(--info);
}
.game-row.gcard .btn-spectate:hover { background: rgba(var(--blue-rgb), 0.22); }

/* ── Teinte par tapis (QML tablestyle.xml) : couleurs chat/log + accent de box.
   Variables injectees par theme.mjs pour les tapis QML skinnes ; repli sur les
   couleurs de palette quand non definies -> AUCUN impact sur les autres tapis.
   L'accent de box est garde par html[data-box-accent] (les replis par style de
   siege different, donc on n'applique la regle que quand un tapis skinne est actif). */
#g-chat-panel, #g-reaction-panel, #g-log-panel { background: var(--chatlog-bg, var(--panel)); border-bottom-color: var(--chatlog-border, var(--border)); }
.g-chat-panel-header { border-bottom-color: var(--chatlog-border, var(--border)); }
.gchat-input, .g-chat-input { background: var(--chatlog-surface, var(--panel)); border-bottom-color: var(--chatlog-border, var(--border)); }
.gchat-input input, .g-chat-input input { background: var(--chatlog-surface, var(--field-bg)); border-color: var(--chatlog-border, var(--border)); color: var(--chatlog-text, var(--cream)); }
.log-panel-body { color: var(--chatlog-text, var(--cream)); }
#g-chat-msgs { color: var(--chatlog-text, var(--text-hi)); }
#g-chat-msgs .msg .txt { color: var(--chatlog-text, var(--text-hi)); }
#g-chat-msgs .msg.sys { color: var(--chatlog-text2, var(--chatlog-text, var(--text))); }
#g-chat-msgs .msg .who { color: var(--box-accent, var(--gold)); }
#g-chat-msgs .msg .msg-time { color: var(--chatlog-muted, var(--text-dim, #8b93a7)); }
#g-chat-msgs .msg.mention .txt { color: var(--box-accent, var(--gold)); font-weight: 700; }
html[data-box-accent][data-seat-struct="qml"] .seat-plate { border-color: var(--box-accent); }

/* ═══════════════════════════════════════════════════════════════════════════
   PERF iOS — Glows composités GPU (remplace les pulses box-shadow)
   ───────────────────────────────────────────────────────────────────────────
   Problème : animer `box-shadow` n'est PAS composité sur iOS Safari → repaint
   CPU à chaque frame (60 fps). Pendant une partie il y a quasi toujours ≥1
   glow actif (anneau du siège au tour ; barre d'action pendant MON tour où
   plusieurs se cumulaient) → chauffe soutenue.
   Correctif : le box-shadow devient STATIQUE (rasterisé une fois) et la
   pulsation passe par un calque ::before/::after dont on n'anime QUE
   `opacity`/`transform` (pur compositing GPU, aucun repaint).
   Fidélité visuelle conservée (§4.3 QML « cadre or pulsé »).
   Neutralisé automatiquement par `html.reduce-fx` (box-shadow:none sur *::after)
   et par prefers-reduced-motion (iteration-count:1). Sélecteurs préfixés :root
   pour tenir la spécificité des bases data-table-fs. ═════════════════════════ */

@keyframes glowRingFade  { 0%,100% { opacity:.55; transform:scale(.94); } 50% { opacity:1; transform:scale(1); } }
@keyframes glowPulseFade { 0%,100% { opacity:.5; } 50% { opacity:1; } }
@keyframes actBarPopT    { 0% { transform:scale(1); } 35% { transform:scale(1.03); } 100% { transform:scale(1); } }

/* ── Siège au tour : anneau (ex-activeRing) ── */
:root .seat.active .seat-avatar { animation: none !important; }   /* base statique de la 3583 conservée */
:root .seat.active .seat-avatar::before {
  content:""; position:absolute; inset:0; border-radius:50%;
  pointer-events:none; z-index:-1;
  box-shadow: 0 0 0 4px rgba(var(--gold-rgb), 0.55), 0 0 20px rgba(var(--gold-rgb), 0.6);
  will-change: opacity, transform;
  animation: glowRingFade 1.2s ease-in-out infinite;
}

/* ── Mon tour : barre d'action (ex-myTurnBorder / myTurnPanelGlow / actBarTurnPulse) ── */
:root .my-zone.my-turn-active { animation: none; border-top: none; }
:root .my-zone.my-turn-active .action-grid {
  position: relative;
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold), 0 0 16px 2px rgba(var(--gold-rgb), 0.42);  /* statique */
  animation: actBarPopT 0.55s cubic-bezier(.2,.9,.3,1.15) both;                  /* pop = transform seul */
}
:root .my-zone.my-turn-active .action-grid::after {
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; z-index:-1;
  box-shadow: 0 0 0 2px #ffe066, 0 0 32px 7px rgba(var(--gold-rgb), 0.74);       /* pic, statique */
  will-change: opacity;
  animation: glowPulseFade 1.4s ease-in-out 0.5s infinite;
}

/* ── Dock joueur actif (ex-pulse-gold) ── */
:root .player-bar.pb-active .player-bar-left { position: relative; animation: none; }
:root .player-bar.pb-active .player-bar-left::after {
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; z-index:-1;
  box-shadow: 0 0 22px rgba(var(--gold-rgb), 0.9);
  will-change: opacity;
  animation: glowPulseFade 1.5s ease-in-out infinite;
}

/* ── Anti-call : bouton Call en attente de 2e tap (ex-callConfirmPulse) ── */
:root .btn-action.btn-call.confirm-call {
  position: relative; animation: none;
  box-shadow: 0 0 0 2px #ffd24d, 0 0 12px rgba(240,160,32,.55);                  /* statique */
}
:root .btn-action.btn-call.confirm-call::after {
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; z-index:-1;
  box-shadow: 0 0 0 2px #ffd24d, 0 0 19px rgba(240,160,32,.9);
  will-change: opacity;
  animation: glowPulseFade .85s ease-in-out infinite;
}

/* ── Barre d'action en PORTRAIT téléphone ──────────────────────────────
   Les contraintes de largeur de la barre n'existaient que dans le bloc
   paysage (@media max-height:500 landscape) ; en portrait la barre gardait
   les tailles « desktop » (Tapis flex:1.5, dropdown large, btn min-width:80)
   et debordait de l'ecran a droite/gauche. On reproduit ici les memes
   contraintes + le Tapis a fond plat (le border-image 9-slice du skin se
   dechire sur ce petit bouton). */
/* Exception canon (décision B) — barre d'action portrait, voir §RESPONSIVE OVAL SIZE. */
@media (max-width: 740px) and (orientation: portrait) {
  .my-zone .action-grid { width: 100%; max-width: 100%; min-width: 0; box-sizing: border-box; gap: 5px; }
  .my-zone .action-grid > * { min-width: 0; }
  /* .action-grid est un flex-item de .my-zone : sans min-width:0 il ne rentre
     pas sous la largeur de son contenu et deborde de l'ecran a mon tour
     (en apercu le wrapper .actions-preview masquait le probleme). */
  .my-zone .actions-preview { min-width: 0; max-width: 100%; box-sizing: border-box; }
  .my-zone .mid-row { gap: 5px; align-items: center; }
  /* Geometrie QML phonePortrait (GameActionBar 2.1.3, raiseRowHeight 26) :
     quick-bets 38x26 a gauche, Tapis 52x26 juste apres, dropdown de mode
     132 px POUSSE a droite (margin-left:auto). Les 38 px de haut de la passe
     precedente ECRASAIENT les valeurs QML du bloc portrait historique
     (specificite egale, plus bas dans le fichier) -> rangee ~12 px trop
     haute sur tout telephone portrait. */
  .my-zone .mid-row .pct-row { flex: 0 0 auto; gap: var(--sp-1); min-width: 0; }
  .my-zone .mid-row .mode-sel-wrap { flex: 0 1 132px; min-width: 0; height: 26px; margin-left: auto; }
  .my-zone .mid-row .mode-sel-wrap select { height: 100%; padding-top: 0; padding-bottom: 0; line-height: 1.1; }
  .my-zone .act-buttons-row { gap: var(--sp-3); }
  /* Rangee Fold / Suivre / Relancer : rangee 56 px (Theme.compact QML) MAIS
     bouton visible 45 px (marges internes QML 5+6) — source 2.1.3. */
  .my-zone .act-buttons-row .btn-action { min-width: 0; min-height: 45px; font-size: var(--fs-md); letter-spacing: 0.5px; border-radius: var(--act-btn-radius, 9px); padding: 0 8px; }
  .my-zone .mid-row .btn-pct { flex: 0 0 38px; width: 38px; min-width: 38px; height: 26px; min-height: 26px; padding: 0 2px; border-radius: 5px; font-size: 11px; font-weight: 700; }
  /* Pas de badges de touches clavier sur mobile (le QML n'en affiche aucun). */
  .my-zone .act-key { display: none !important; }
  /* Champ montant borné : non contraint, il faisait ~180px et elargissait la
     bet-row -> .action-grid -> tout debordait. (Le bloc paysage le bornait deja.) */
  .my-zone .bet-row { gap: var(--sp-2); }
  /* Champ montant : 78 px de large, police 13 px (spec QML §5.2). */
  .my-zone .bet-row .raise-amt-field { width: 78px; min-width: 0; flex: 0 0 auto; height: 26px; min-height: 26px; padding: 1px 6px; font-size: 13px; }
  .my-zone .bet-row .raise-slider { flex: 1 1 auto; min-width: 40px; }
  /* Toute la chaine de conteneurs doit pouvoir se comprimer : sans min-width:0
     sur .action-wrap ET #g-actions (flex-items), le contenu min-content bloque
     le retrecissement et la barre deborde de l'ecran a mon tour. */
  .my-zone .action-wrap { max-width: 100%; min-width: 0; width: 100%; }
  .my-zone #g-actions { min-width: 0; max-width: 100%; width: 100%; }
  .my-zone .mid-row .btn-allin {
    flex: 0 0 52px; width: 52px; white-space: nowrap; min-width: 52px; height: 26px; min-height: 26px; font-size: 12px;
    border-image: none !important;
    border: 1px solid #ef5350 !important;
    background: linear-gradient(180deg, #9e2a2a, #5c1111) !important;
    color: #fff !important;
    padding: 0 2px !important;
    border-radius: var(--r-md);
  }
}

/* ── Traduction du chat (API navigateur, opt-in) : bouton 🌐 par message,
   visible seulement quand body.chat-tr-on (option activee ET API dispo). ── */
.chat-tr-btn { display: none; background: none; border: none; cursor: pointer; font-size: var(--fs-xs); padding: 0 3px; margin-left: 4px; opacity: 0.45; vertical-align: baseline; line-height: 1; }
body.chat-tr-on .msg .chat-tr-btn { display: inline; }
.chat-tr-btn:hover { opacity: 0.9; }
.chat-tr-btn.tr-active { opacity: 1; filter: drop-shadow(0 0 2px var(--gold)); }
.chat-tr-btn.tr-busy { opacity: 0.3; cursor: wait; }
.chat-tr-btn.tr-err { opacity: 0.7; filter: grayscale(1); }
.chat-tr-btn.tr-same { opacity: 0.25; cursor: default; }
/* Abréviations de chat (gg, nh, utg…) : soulignement pointillé discret + bulle
   native au survol (title = sens localisé). Voir modules/chat/abbrev.mjs. */
.chat-abbr { border-bottom: 1px dotted currentColor; cursor: help; }


/* ── Barre d'action : panneau QML (GameActionBar 2.1.3) — desktop/tablette ──
   QML : panelWidth = min(largeur, max(largeurCommunity, 380)) CENTRÉ, fond
   rgba(0,0,0,0.82), radius 10, flottant à 8 px du bord bas (le tapis se voit
   dessous). Largeur community ≈ (5×46 + 4×3) × --comm-scale = 242×cs.
   Scopé à body.adv-hide-pbar (barre joueur masquée, le défaut) : si la barre
   joueur est réaffichée, l'ancienne implantation pleine largeur reste.
   Condition élargie (0.3.567) : ≥600 px de large + souris (hover+fine) — la
   double garde 900×600 laissait une ZONE MORTE (fenêtre basse <600 ou étroite
   600–900) sans aucune géométrie QML. Les téléphones (pointer:coarse) gardent
   leurs blocs portrait/paysage dédiés. */
@media (min-width: 600px) and (hover: hover) and (pointer: fine) {
  /* .my-zone = POSITIONNEMENT SEUL (transparent, sans ombre) : en mode
     plein-tapis elle est déjà transparente !important et c'est .action-grid
     qui porte le panneau — une ombre posée ici dessinait un contour fantôme
     autour d'une boîte invisible. */
  body.adv-hide-pbar .my-zone {
    left: 50%; right: auto;
    transform: translateX(-50%);
    /* QML exact : panelWidth = max(communityVisualWidth, 380) avec
       communityVisualWidth = 264 × communityScale (et non 242+32 : la barre
       était plus étroite que le QML — retour narmod). */
    width: clamp(380px, calc(264px * var(--comm-scale, 1)), 96vw);
    bottom: 8px;
    background: transparent !important;
    border: none !important;
    box-shadow: none;
    padding: 0;
  }
  /* Le PANNEAU visuel QML vit sur .action-grid (fs et non-fs identiques) :
     fond rgba(0,0,0,0.82), radius 10, ombre douce, pleine largeur du bloc. */
  body.adv-hide-pbar .my-zone .action-grid {
    max-width: none; width: 100%;
    background: rgba(0, 0, 0, 0.82);
    border-radius: var(--r-bar);
    /* Paddings QML exacts (raiseSection top 4 / cotes 8 / bas 2 ; la rangee
       d'action porte ses propres marges verticales 5/5 en dessous). */
    padding: 4px 8px 2px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  }
  /* Rangée montant/slider QML : champ 78×26, police 13, spacing 6. */
  body.adv-hide-pbar .my-zone .bet-row { gap: var(--sp-2); }
  body.adv-hide-pbar .my-zone .bet-row .raise-amt-field {
    width: 78px; height: 26px; min-height: 26px; font-size: 13px; flex: 0 0 auto;
  }
}


/* ── Barre d'action QML — finitions desktop/tablette (suite 0.3.541) ── */
@media (min-width: 600px) and (hover: hover) and (pointer: fine) {
  /* Les effets « mon tour » (cadre/glow dorés) sont CONSERVÉS — retrait
     annulé à la demande de narmod (0.3.544). */
  /* Rangée intermédiaire QML (raiseRowHeight 26) : 1/3 · 1/2 · Pot · TAPIS
     sont tous des pilules de 26 px — côté web, Tapis portait la classe des
     GROS boutons d'action (~37 px) et gonflait toute la rangée : c'était la
     principale disparité perçue avec le QML. Le dropdown se raccorde à la
     même hauteur. */
  /* Toute la rangée intermédiaire à 26 px EXACTEMENT (raiseRowHeight QML) :
     1/3 · 1/2 · Pot avaient un padding sans plafond de hauteur → plus hauts
     que Tapis (26 px explicites). Harmonisation. */
  body.adv-hide-pbar .my-zone .pct-row .btn-pct {
    height: 26px; min-height: 26px;
    padding: 0 8px;
    font-size: var(--fs-xs);
    line-height: 1;
    display: inline-flex; align-items: center; justify-content: center;
  }
  body.adv-hide-pbar .my-zone .mid-row > .btn-action.btn-allin {
    height: 26px; min-height: 26px;
    padding: 0 10px !important;
    font-size: var(--fs-xs) !important;
    letter-spacing: 0.3px;
    flex: 0 0 auto;
  }
  body.adv-hide-pbar .my-zone .mid-row .mode-sel-wrap,
  body.adv-hide-pbar .my-zone .mid-row .mode-sel-wrap select { height: 26px; }
  /* Derniers gabarits QML (GameActionBar) : largeurs fixes et polices. */
  body.adv-hide-pbar .my-zone .pct-row .btn-pct { flex: 0 0 38px; width: 38px !important; min-width: 38px !important; padding: 0 2px !important; font-size: 11px; }
  body.adv-hide-pbar .my-zone .pct-row .btn-pct .pct-p { font-size: 11px; }
  body.adv-hide-pbar .my-zone .mid-row > .btn-action.btn-allin { flex: 0 0 52px; width: 52px; padding: 0 2px !important; font-size: 12px !important; }
  /* Thèmes à SVG de boutons (data-btn-img) : Tapis 52×26 en image du thème
     ÉTIRÉE 100%/100% comme le QML (Image.Stretch) — identique au mode
     portrait/iOS. Le repli 9-slice à bords 6px se déchirait sur Edge/desktop
     (retour narmod 15/07) ; si un letterboxing SVG réapparaît sur Linux, le
     corriger dans le SVG (preserveAspectRatio) et non ici. */
  :root[data-btn-img] body.adv-hide-pbar .my-zone .mid-row > .btn-action.btn-allin {
    border: none !important;
    background: transparent !important;
    background-image: var(--btn-allin-img) !important;
    background-size: 100% 100% !important;
    background-repeat: no-repeat !important;
    border-radius: var(--r-sm);
    padding: 0 !important;
  }
  body.adv-hide-pbar .my-zone .mid-row .mode-sel-wrap select { font-size: 11px; }
  /* Slider QML : rail 4 px, poignée 18×18 ronde. */
  body.adv-hide-pbar .my-zone .bet-row input[type="range"] {
    -webkit-appearance: none; appearance: none;
    height: 4px; border-radius: 2px;
    background: rgba(255, 255, 255, 0.22);
  }
  body.adv-hide-pbar .my-zone .bet-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; border-radius: var(--r-md);
    background: #4CAF50; border: 1px solid rgba(255, 255, 255, 0.5);
    cursor: pointer;
  }
  body.adv-hide-pbar .my-zone .bet-row input[type="range"]::-moz-range-track {
    height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.22);
  }
  body.adv-hide-pbar .my-zone .bet-row input[type="range"]::-moz-range-thumb {
    width: 18px; height: 18px; border-radius: var(--r-md);
    background: #4CAF50; border: 1px solid rgba(255, 255, 255, 0.5);
    cursor: pointer;
  }
  /* Dropdown de mode : 132 px comme le QML, hauteur raccordée à la rangée. */
  body.adv-hide-pbar .my-zone .mid-row .mode-sel-wrap { flex: 0 0 132px; }
  body.adv-hide-pbar .my-zone .mid-row .mode-sel-wrap select {
    padding-top: 4px; padding-bottom: 4px; font-size: var(--fs-xs);
  }
}


/* ── Zoom des cartes du joueur RETIRÉ (demande narmod) : dans les packs
   pokerth les cartes self sont à taille QML fixe, le bouton n'a plus d'objet ;
   il est masqué partout pour une UI identique sur tous les écrans. ── */
#g-cardzoom { display: none !important; }

/* ── Barre d'action QML — dernière passe (mode panneau desktop/tablette) ── */
@media (min-width: 600px) and (hover: hover) and (pointer: fine) {
  /* Pastilles de raccourci [F]/[C]/[R] : extension web absente du QML. */
  body.adv-hide-pbar .my-zone .act-key { display: none !important; }
  /* Boutons d'action : typo QML exacte — 15px bold, letterSpacing 0.5,
     radius 9 (GameActionBar §5.5). */
  /* Rangée du bas = spec QML COMPLÈTE (GameActionBar, rectifiée) : les
     boutons REMPLISSENT la rangée actionRowHeight 54 (fillWidth+fillHeight),
     largeurs égales, espacement 8 — le 168×43 n'est que l'espace de dessin
     des SVG de thème, étiré sur toute la hauteur (correction : pas d'« air »
     interne). Police 15 bold ls 0.5 lineHeight 0.95, radius 9. */
  /* Hauteur pilotée par le régime QML discret (--bar-k, updateBottomLayout) :
     54 desktop (≥900) · 56 Theme.compact (600–900) — plus de 54 en dur, la
     fenêtre étroite retombe sur la bonne valeur au lieu d'une zone morte. */
  /* La RANGEE fait 54 (56 compact) mais le RowLayout QML des boutons a des
     marges internes top 5 / bottom 5 (6 compact) -> le BOUTON visible fait
     rangee - 10 (44 desktop, ~45 compact). C'etait l'erreur de la passe
     0.3.541 (« pas d'air interne ») : les boutons web etaient 10 px trop
     hauts par rapport au client officiel. */
  body.adv-hide-pbar .my-zone .act-buttons-row { height: calc(54px * var(--bar-k, 1)); box-sizing: border-box; padding: 5px 0; gap: 8px; align-items: stretch; }
  body.adv-hide-pbar .my-zone .act-buttons-row .btn-action {
    height: calc(54px * var(--bar-k, 1) - 10px) !important; min-height: 0 !important; max-height: calc(54px * var(--bar-k, 1) - 10px) !important;
    flex: 1 1 0;
    padding: 0 10px !important;
    font-size: calc(15px * var(--bar-kf, 1)) !important;
    font-weight: 700;
    letter-spacing: 0.5px;
    border-radius: var(--act-btn-radius, 9px);
    line-height: 1.05;
  }
  /* Montant sur une DEUXIÈME ligne (« Suivre / $40 »), comme le QML. */
  body.adv-hide-pbar .my-zone .act-buttons-row .btn-action > b,
  body.adv-hide-pbar .my-zone .act-buttons-row .btn-action .raise-btn-amt {
    display: block;
    line-height: 1.05;
  }
  body.adv-hide-pbar .my-zone .action-grid { gap: 3px; }
  body.adv-hide-pbar .my-zone .mid-row { gap: var(--sp-1); }
  /* (liseré/ombre gérés sur .action-grid ci-dessus) */
}


/* ── Parité QML : plate pokerth amincie vers GamePlayerBox 2.1.3 (opp base
   ≈121×71/84 vs nos 164×101 mesurés) — des boîtes intrinsèques plus petites
   agrandissent la lacune verticale → commScale/rivière/barre remontent au
   niveau QML sans toucher aux formules (calibration narmod). ── */
html[data-seat-struct="qml"] .seat-plate { padding: 3px 5px !important; gap: 2px !important; }
html[data-seat-struct="qml"] .seat:not(.me) .seat-avatar { width: 34px !important; height: 34px !important; }
html[data-seat-struct="qml"] .seat:not(.me) .seat-holecards .pk { width: 25px; height: 34px; font-size: var(--fs-3xs); }
html[data-seat-struct="qml"] .seat:not(.me) .seat-name { font-size: var(--fs-2xs); line-height: 1.1; }
html[data-seat-struct="qml"] .seat:not(.me) .seat-money { font-size: var(--fs-xs); line-height: 1.1; }
html[data-seat-struct="qml"] .seat:not(.me) .seat-narrow .seat-avatar { width: 36px !important; height: 36px !important; }
html[data-seat-struct="qml"] .seat:not(.me) .seat-narrow .seat-holecards .pk { width: 26px; height: 36px; }
/* ── HUD par siège + grille de range (thème client) ─────────────────────── */
#hud-layer{position:absolute;inset:0;pointer-events:none;z-index:6;overflow:visible}
.hud-box{position:absolute;pointer-events:auto;cursor:pointer;
  min-width:104px;background:var(--panel);border:1px solid var(--border);border-radius:8px;
  padding:3px 6px 4px;box-shadow:0 3px 10px rgba(0,0,0,.42);backdrop-filter:blur(3px);
  font-size:10px;line-height:1.25;user-select:none;transition:border-color .15s}
.hud-box:hover{border-color:var(--border-hi)}
.hud-box{cursor:grab;touch-action:none}
.hud-box.hud-dragging{cursor:grabbing;opacity:.92;z-index:11;box-shadow:0 6px 18px rgba(0,0,0,.6);transition:none}
.hud-head{display:flex;align-items:baseline;gap:var(--sp-2);margin-bottom:2px}
.hud-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--gold);font-weight:700;letter-spacing:.02em;font-size:10.5px}
.hud-hands{color:var(--text);font-variant-numeric:tabular-nums;font-size:9px;opacity:.8}
.hud-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px 7px}
.hud-stat{display:flex;align-items:baseline;justify-content:space-between;gap:3px}
.hud-lbl{color:var(--text);font-style:normal;font-size:8.5px;letter-spacing:.03em;opacity:.75}
.hud-val{color:var(--text-hi);font-weight:600;font-variant-numeric:tabular-nums}

/* Grille de range (modale centrée) */
#range-modal{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;
  background:rgba(0,0,0,.6);padding:16px}
#range-modal .range-card{background:var(--panel-hi);border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:0 12px 40px rgba(0,0,0,.55);max-width:min(96vw,720px);max-height:92vh;display:flex;flex-direction:column;overflow:hidden}
#range-modal .range-head{display:flex;align-items:center;gap:var(--sp-5);flex-wrap:wrap;
  padding:9px 12px;border-bottom:1px solid var(--border)}
#range-modal .range-title{flex:1;min-width:120px;color:var(--gold);font-weight:700;font-size:var(--fs-base)}
#range-modal .range-filters{display:flex;gap:10px}
#range-modal .range-filters label{color:var(--text);font-size:var(--fs-2xs);text-transform:uppercase;letter-spacing:.08em;display:flex;align-items:center;gap:4px}
#range-modal .range-filters select{background:var(--field-bg);color:var(--text-hi);border:1px solid var(--border);border-radius:5px;padding:1px 4px;font-size:var(--fs-xs)}
#range-modal .range-close{background:none;border:none;color:var(--text);cursor:pointer;font-size:var(--fs-md);padding:0 4px}
#range-modal .range-close:hover{color:var(--gold)}
#range-modal .range-body{overflow:auto;padding:10px 12px}
#range-modal .range-legend{padding:6px 12px 9px;color:var(--text);opacity:.7;font-size:var(--fs-2xs);border-top:1px solid var(--border)}
/* Panneau détaillé d'un joueur : prolongement de la boîte HUD (popover ancré,
   dans #hud-layer). S'ouvre au-dessus/en dessous selon la position du siège. */
#hud-detail{position:absolute;z-index:9;pointer-events:auto;width:190px;max-width:72vw;
  background:var(--panel-hi);border:1px solid var(--border-hi);border-radius:var(--r-md);
  box-shadow:0 8px 26px rgba(0,0,0,.55);backdrop-filter:blur(4px);padding:6px 8px 7px;
  font-size:11px;line-height:1.3;animation:hud-d-in .12s ease-out}
@keyframes hud-d-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
#hud-detail .hud-d-head{display:flex;align-items:baseline;gap:var(--sp-3);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid var(--border)}
#hud-detail .hud-d-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--gold);font-weight:700;font-size:var(--fs-base)}
#hud-detail .hud-d-hands{color:var(--text);font-size:var(--fs-2xs);opacity:.8;font-variant-numeric:tabular-nums;flex-shrink:0}
/* Portee des stats limitee a la session courante (joueurs invites) : le pseudo
   d'un invite peut etre repris par une autre personne d'une session a l'autre. */
/* Bloc stats de comportement dans la fenetre d'avatar (popup profil joueur).
   Independant du HUD flottant : visible meme HUD desactive.
   Calque sur .pim-ig (le cadre Stack/Miser) : meme largeur pleine, meme fond,
   meme bordure, memes tokens de couleur. --text-dim n'existe pas dans le
   theme : les libelles utilisent --gold-dim comme .pim-ig-k, les valeurs
   --cream comme .pim-ig-v (la colorisation par seuils passe en style inline). */
.pim-stat-box{
  width: 100%;
  margin-top: var(--sp-2);
  padding: 10px 12px;
  background: var(--field-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.pim-stat-head{display:flex;align-items:baseline;gap:var(--sp-2);margin-bottom:8px;padding-bottom:6px;border-bottom:1px solid var(--border)}
.pim-stat-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--gold-dim);font-family:var(--ff-mono);font-size:var(--fs-base);letter-spacing:.04em;text-transform:uppercase}
.pim-stat-scope{flex-shrink:0;color:var(--gold-dim);font-family:var(--ff-mono);font-size:var(--fs-sm);border:1px solid var(--gold-dim);border-radius:6px;padding:0 5px;line-height:1.6}
.pim-stat-hands{flex-shrink:0;color:var(--cream);font-family:var(--ff-mono);font-size:var(--fs-sm);opacity:.9}
/* Deux colonnes fixes : les libelles restent alignes et la valeur colle a sa
   propre etiquette, comme les lignes du cadre Stack juste au-dessus. */
.pim-stat-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px var(--sp-5)}
.pim-stat{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-2);min-width:0;font-size:var(--fs-base)}
.pim-stat i{font-style:normal;color:var(--gold-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pim-stat b{color:var(--cream);font-family:var(--ff-mono);font-weight:700;flex-shrink:0}
.pim-trend{display:flex;align-items:baseline;gap:var(--sp-2);margin-top:8px;padding-top:6px;border-top:1px solid var(--border);font-size:var(--fs-base)}
.pim-t-lbl{flex:1;min-width:0;color:var(--gold-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pim-t-cell{display:inline-flex;align-items:baseline;gap:4px;flex-shrink:0}
.pim-t-cell i{font-style:normal;color:var(--gold-dim)}
.pim-t-cell b{color:var(--cream);font-family:var(--ff-mono);font-weight:700}
.pim-t-cell u{text-decoration:none;color:var(--gold);font-weight:700}
/* Tendance recente : VPIP/AF sur les 20 dernieres mains vs la moyenne globale.
   La fleche marque un ecart significatif (cf. _TREND_EPS), la double barre un
   comportement stable. */
#hud-detail .hud-d-trend{display:flex;align-items:center;gap:var(--sp-2);margin-top:5px;padding-top:5px;border-top:1px solid var(--border);font-size:var(--fs-2xs)}
#hud-detail .hud-d-t-lbl{flex:1;min-width:0;color:var(--text-dim,#a0acc4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#hud-detail .hud-d-t-cell{display:inline-flex;align-items:baseline;gap:3px;flex-shrink:0}
#hud-detail .hud-d-t-cell i{font-style:normal;color:var(--text-dim,#a0acc4);opacity:.85}
#hud-detail .hud-d-t-cell b{color:var(--text);font-variant-numeric:tabular-nums}
#hud-detail .hud-d-t-cell u{text-decoration:none;color:var(--gold);font-weight:700}
#hud-detail .hud-d-scope{flex-shrink:0;color:var(--text-dim,#a0acc4);font-size:var(--fs-3xs,10px);opacity:.75;border:1px solid var(--border);border-radius:6px;padding:0 5px;line-height:1.5}
#hud-detail .hud-d-grid{display:grid;grid-template-columns:1fr 1fr;gap:2px 12px}
#hud-detail .hud-d-row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-2);padding:1px 0}
#hud-detail .hud-d-lbl{color:var(--text);font-size:var(--fs-xs);opacity:.85}
#hud-detail .hud-d-val{color:var(--text-hi);font-weight:700;font-variant-numeric:tabular-nums;font-size:var(--fs-xs)}
#hud-detail .hud-d-range{margin-top:6px;width:100%;background:rgba(var(--gold-rgb),.14);border:1px solid var(--border-hi);color:var(--gold);font-size:var(--fs-xs);letter-spacing:.03em;padding:4px 8px;border-radius:var(--r-sm);cursor:pointer}
#hud-detail .hud-d-range:hover{background:rgba(var(--gold-rgb),.22)}
.range-grid{border-collapse:separate;border-spacing:2px;margin:0 auto}
.range-grid td{width:38px;height:34px;text-align:center;vertical-align:middle;border-radius:4px;
  background:var(--field-bg);color:var(--text);font-size:9px;line-height:1.05;position:relative}
.range-grid td.filled{font-weight:700}
.range-grid .rc-combo{display:block;font-size:9.5px}
.range-grid .rc-count{display:block;font-size:8px;opacity:.85;font-variant-numeric:tabular-nums}
/* Mobile : HUD très compact — une seule ligne VPIP/PFR/AF (les 3 dernières
   stats sont masquées pour réduire l'encombrement en portrait 9-max). */
@media (max-width:599.98px){
  .range-grid td{width:26px;height:26px;font-size:7.5px}
  .range-grid .rc-combo{font-size:8px}
  .hud-box{min-width:0;width:auto;max-width:104px;font-size:7.5px;padding:2px 4px;border-radius:var(--r-sm);line-height:1.12}
  .hud-head{gap:3px;margin-bottom:1px}
  .hud-name{font-size:8px;max-width:66px}
  .hud-hands{font-size:6.5px}
  .hud-grid{grid-template-columns:repeat(3,auto);gap:0 6px;justify-content:start}
  .hud-grid .hud-stat:nth-child(n+4){display:none}
  .hud-lbl{font-size:6px}
  .hud-val{font-size:7.5px}
}
/* Très petits écrans (portrait étroit) : encore plus dense. */
@media (max-width:400px){
  .hud-box{max-width:96px;font-size:7px;padding:1px 3px}
  .hud-name{max-width:58px;font-size:7.5px}
  .hud-grid{gap:0 5px}
  .hud-lbl{font-size:5.5px}
  .hud-val{font-size:7px}
}
/* Mobile paysage (peu de hauteur) : même compacité qu'en portrait — n'affiche
   que VPIP/PFR/AF, indépendamment de la largeur. */
@media (orientation:landscape) and (max-height:600px){
  .hud-box{min-width:0;width:auto;max-width:112px;font-size:8px;padding:2px 4px;border-radius:var(--r-sm);line-height:1.15}
  .hud-head{gap:3px;margin-bottom:1px}
  .hud-name{font-size:8.5px;max-width:72px}
  .hud-hands{font-size:7px}
  .hud-grid{grid-template-columns:repeat(3,auto);gap:0 6px;justify-content:start}
  .hud-grid .hud-stat:nth-child(n+4){display:none}
  .hud-lbl{font-size:6.5px}
  .hud-val{font-size:8px}
}

/* ── Zoom de fenêtre (demande narmod 2026-07-18) : le contenu (texte,
   contrôles, espacements) suit la taille de la fenêtre — propriété CSS `zoom`
   (standardisée) sur les enfants directs : le layout interne se calcule en
   coordonnées locales puis est mis à l'échelle, flex et scroll restent
   corrects. Les poignées de redimensionnement (.win-rsz) gardent leur taille
   réelle pour rester faciles à attraper. --wz est posé en JS
   (_applyWinZoom / _advApplyZoom) = taille fenêtre / taille par défaut ×
   facteur global du viewport de l'app. ── */
.floating-win.win-zoom > :not(.win-rsz) { zoom: var(--wz, 1); }

/* ── Défilement STRICTEMENT vertical partout (demande narmod 2026-07-19) ──
   overflow-y:auto seul laisse overflow-x se calculer en auto : n'importe quel
   contenu trop large fait alors panner le panneau latéralement (constaté sur
   la catégorie Internet des options avancées). On verrouille l'axe X de TOUS
   les conteneurs à défilement vertical de l'app d'un bloc, ici en fin de
   feuille pour gagner la cascade. Exceptions volontairement ABSENTES de cette
   liste (défilement horizontal légitime) : .avp-cats, .rk-awards, .rk-ps-tw,
   .rk-pr-tw, #g-stats-body .stats-scroll, .adv-nav (mobile), .st-tabbar,
   #range-modal .range-body (grille 2D). */
.cp-scroll, #s-connect, .gim-card, .pim-card, .avp-grid, #s-lobby,
.games-scroll, .chat-msgs, .emote-suggest, .react-grid,
#stats-overlay, .log-panel-body, .wc-players, .game-log, .wait-page,
.km-card, .lobby-body, .chat-emoji-panel, .music-body, .rk-body,
#rk-profile, .adv-body, #about-page, .pv-scroll, .avgal-body, .lgi-scroll
{ overflow-x: hidden; }

/* ── Lot 7 — Adaptation petits écrans (≤380px) : réduction du barème
   typographique uniquement, pour limiter les débordements sur très petits
   téléphones. Bloc en fin de fichier → l'emporte sur les défauts :root quand il
   matche. Les éléments ayant déjà leur propre override à ce breakpoint gardent
   leur taille (leur règle gagne). Voir docs/DESIGN_TOKENS.md §Responsive. */
@media (max-width: 380px) {
  :root {
    --fs-3xs: .52rem; --fs-2xs: .58rem; --fs-xs: .66rem;  --fs-sm: .74rem;
    --fs-base: .80rem; --fs-md: .90rem; --fs-lg: 1.0rem;  --fs-xl: 1.28rem;
    --fs-2xl: 1.5rem;  --fs-hero: 2.4rem;
  }
}

/* Trophée classement : or vif en thème sombre, or foncé en thème clair (lisibilité). */
/* Le trophee suit la couleur de l'icone du bouton (neutre au repos, or sous
   .win-open) — meme traitement que les autres icones d'en-tete. */
.rk-trophy{fill:currentColor}

/* ── Succès / Achievements — onglet « Trophées » du ranking modal (mode entraînement) ── */
#rk-ach-wrap { display: flex; flex-direction: column; gap: 6px; padding: 4px 2px 2px; }
.rk-ach-head { display: flex; align-items: baseline; justify-content: space-between; margin: 2px 2px 2px; }
.rk-ach-mode { font-size: var(--fs-sm); letter-spacing: 0.06em; color: var(--text); opacity: 0.75; font-weight: 600; }
.rk-ach-prog { font-size: var(--fs-sm); letter-spacing: 0.06em; color: var(--gold); font-weight: 700; }
.rk-ach-cat { font-size: var(--fs-sm); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-dim); margin: 8px 2px 0; }
.rk-ach-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 9px; background: rgba(var(--gold-rgb), 0.05); border: 1px solid var(--border); }
.rk-ach-row.on { border-color: rgba(var(--gold-rgb), 0.35); }
.rk-ach-row.off { opacity: 0.42; filter: grayscale(1); }
.rk-ach-ico { font-size: 1.35rem; line-height: 1; width: 1.8rem; text-align: center; flex: none; }
.rk-ach-txt { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.rk-ach-txt b { font-size: var(--fs-base); color: var(--text-hi); }
.rk-ach-txt small { font-size: var(--fs-sm); color: var(--text); opacity: 0.8; white-space: normal; }
.rk-ach-badge { flex: none; font-size: 0.95rem; color: var(--gold); }

/* ── Encart « Trophées X/10 » (popup Mon profil + overlay fin de partie, entraînement) ── */
.ach-badge { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 8px 12px; border-radius: 9px; background: rgba(var(--gold-rgb), 0.08); border: 1px solid rgba(var(--gold-rgb), 0.35); cursor: pointer; }
.ach-badge:hover { background: rgba(var(--gold-rgb), 0.14); }
.ach-badge-ico { font-size: 1.1rem; line-height: 1; }
.ach-badge-lbl { font-weight: 600; color: var(--text-hi); flex: 1; }
.ach-badge-val { font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; }
.ach-badge-endgame { margin-top: 12px; justify-content: center; }
.rk-ach-req { flex: none; font-size: 0.66rem; color: var(--gold-dim); background: rgba(var(--gold-rgb), 0.10); border: 1px solid rgba(var(--gold-rgb), 0.25); border-radius: 999px; padding: 1px 7px; white-space: nowrap; }

/* ── Indicateur « disquette » de synchronisation (headers) ─────────────────── */
.hdr-sync { display: none; align-items: center; justify-content: center; width: 24px; height: 24px; flex: none; color: var(--gold-dim); }
.hdr-sync.on { display: inline-flex; animation: hdrSyncPulse 1.15s ease-in-out infinite; }
.hdr-sync svg { width: 17px; height: 17px; display: block; }
@keyframes hdrSyncPulse { 0%, 100% { opacity: 0.32; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .hdr-sync.on { animation: none; opacity: 0.85; } }
