/* ==================================================================
   OdinBet — système de thème (clair / sombre).
   Toutes les couleurs passent par des variables : le thème sombre ne
   fait que redéfinir les surfaces / textes / bordures. Les couleurs de
   marque (teal / orange) sont conservées dans les deux thèmes.
   Le thème actif est porté par [data-theme] sur <html> (posé très tôt
   par /js/theme-init.js pour éviter tout flash).
   ================================================================== */

:root, :root[data-theme="light"] {
  color-scheme: light;

  /* --- Échelle d'élévation (voir le thème sombre pour la logique) -------
     En clair, on ne peut pas monter indéfiniment : le niveau 1 est déjà
     blanc. L'échelle s'inverse donc au-dessus — un élément posé SUR une
     carte se creuse au lieu de se soulever. C'est la convention des
     thèmes clairs, et ça se lit aussi bien.
       0 = fond de page        (le plus teinté)
       1 = cartes, panneaux    (blanc, se détache du fond)
       2 = survol, imbriqué    (très légèrement creusé)
       3 = actif, imbriqué x2  (creusé franchement) */
  --bg: #eaeef4;              /* niveau 0 — blanc cassé, jamais de blanc pur */
  --surface: #ffffff;         /* niveau 1 */
  --surface-2: #f2f5f9;       /* niveau 2 */
  --surface-3: #e4eaf1;       /* niveau 3 */
  --border: #dde4ee;
  --border-strong: #c2cdda;

  --text: #1a2230;            /* gris très foncé, jamais de noir pur */
  --text-soft: #46566b;
  --text-dim: #7b8a9c;

  --good: #1aa971;  --good-wash: #e4f7ef;  --good-ink: #0f7a52;  --good-line: #b9e6d2;
  --bad: #e5484d;   --bad-wash: #fdeceb;   --bad-ink: #a3282c;   --bad-line: #f3c0c1;

  --brand-wash: #e2f6f5;
  --action-wash: #fff2df;
  --action-ink: #8a4e00;

  /* Header : blanc sur fond teinté, donc déjà au-dessus. La bordure basse
     est un cran plus marquée que les autres pour trancher net. */
  --header-bg: rgba(255, 255, 255, 0.88);
  --header-line: #d2dbe6;
  --backdrop: rgba(16, 32, 43, 0.42);
  --toast-bg: #1a2230;  --toast-fg: #ffffff;
  --shine: rgba(255, 255, 255, 0.75);

  --shadow-sm: 0 1px 3px rgba(16, 32, 43, 0.05);
  --shadow: 0 4px 16px rgba(16, 32, 43, 0.08), 0 1px 3px rgba(16, 32, 43, 0.05);
  --shadow-lg: 0 16px 44px rgba(16, 32, 43, 0.14);

  /* halos de fond (profondeur) + ascenseur */
  /* Rareté : gris / bleu / or, partout où un objet apparaît */
  --rar-common: #97a4b4;      --rar-common-wash: #eef1f5;  --rar-common-ink: #5b6979;
  --rar-rare: #3b82f6;        --rar-rare-wash: #e8f0fe;    --rar-rare-ink: #1d4ed8;
  --rar-legendary: #e0a416;   --rar-legendary-wash: #fdf3dc; --rar-legendary-ink: #8a5f00;

  --depth-1: rgba(18, 189, 185, 0.10);
  --depth-2: rgba(245, 150, 14, 0.09);
  --depth-3: rgba(10, 143, 140, 0.05);
  --scroll-thumb: #c3cedb;
  --scroll-thumb-hover: #9fb0c2;

  --pastille-l: 91%;
  --pastille-tl: 32%;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  /* --- Échelle d'élévation ---------------------------------------------
     Sur fond sombre, une ombre portée ne se voit pas : c'est l'écart de
     teinte qui porte la hiérarchie. Trois niveaux nettement séparés, ~11
     points de luminance entre chacun — assez pour se lire, assez peu
     pour rester sobre.
       0 = fond de page      (le plus sombre)
       1 = cartes, panneaux  (se détachent du fond)
       2 = survol, imbriqué  (un cran au-dessus)
       3 = actif, dropdown   (le plus clair)
     Les mêmes variables servent dans les deux thèmes : seule leur valeur
     change ici. */
  --bg: #0d1016;              /* niveau 0 — anthracite profond, jamais noir pur */
  --surface: #1a1e27;         /* niveau 1 — cartes, coupon, header */
  --surface-2: #242934;       /* niveau 2 */
  --surface-3: #2e3441;       /* niveau 3 */
  --border: #363d4c;          /* assez clair pour dessiner l'arête d'une carte */
  --border-strong: #4b5466;

  --text: #e8eaee;           /* blanc cassé */
  --text-soft: #b3bbc8;
  --text-dim: #828b9a;

  --good: #2ad495;  --good-wash: #143a2c;  --good-ink: #79e2ba;  --good-line: #2c5a48;
  --bad: #ff6b6f;   --bad-wash: #3a2022;   --bad-ink: #ffb0b2;   --bad-line: #5a3134;

  --brand-wash: #123539;
  --action-wash: #3c2d15;
  --action-ink: #ffce8f;

  /* Le header est au niveau 1 comme les cartes, mais posé sur le niveau 0 :
     l'écart suffit à séparer la navigation du contenu, et la bordure basse
     (--header-line) trace la limite même quand une carte passe dessous. */
  --header-bg: rgba(26, 30, 39, 0.92);
  --header-line: #3d4658;
  --backdrop: rgba(0, 0, 0, 0.62);
  --toast-bg: #eef0f3;  --toast-fg: #17191f;
  --shine: rgba(255, 255, 255, 0.10);

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
  --shadow: 0 6px 22px rgba(0, 0, 0, 0.42), 0 1px 3px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.55);

  --rar-common: #78859a;      --rar-common-wash: #2b303a;  --rar-common-ink: #aab4c2;
  --rar-rare: #5b9bff;        --rar-rare-wash: #1b2740;    --rar-rare-ink: #a8c8ff;
  --rar-legendary: #f0b93c;   --rar-legendary-wash: #3a2f14; --rar-legendary-ink: #ffd97a;

  /* Halos de fond : très dilués (4-5 %) pour casser l'aplat sans jamais
     rattraper la teinte des cartes — sinon le niveau 1 ne se lit plus. */
  --depth-1: rgba(18, 189, 185, 0.05);
  --depth-2: rgba(245, 150, 14, 0.04);
  --depth-3: rgba(10, 143, 140, 0.06);
  --scroll-thumb: #414958;
  --scroll-thumb-hover: #565f70;

  --pastille-l: 26%;
  --pastille-tl: 78%;
}

:root {
  /* --- 2 accents, identiques dans les 2 thèmes --- */
  --brand: #12bdb9;
  --brand-strong: #0a8f8c;
  --action: #f5960e;
  --action-strong: #dd8206;

  /* alias de compat */
  --primary: var(--brand);
  --primary-strong: var(--brand-strong);
  --primary-ink: #ffffff;
  --primary-wash: var(--brand-wash);
  --cta: var(--action);
  --cta-strong: var(--action-strong);
  --accent: var(--action);
  --accent-ink: var(--action-ink);
  --special: var(--brand);
  --special-wash: var(--brand-wash);

  --radius: 16px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --header-h: 60px;

  /* --- Typographie : UNE seule famille pour tout le site ---------------
     Pas de police distante : la CSP interdit les CDN, et une police
     système évite le flash de texte non stylé. La hiérarchie vient de
     l'échelle et de la graisse, pas d'un mélange de familles. */
  --font: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;

  --fs-xs: 0.75rem;    /* 12px — mentions, méta */
  --fs-sm: 0.8125rem;  /* 13px — libellés, tableaux */
  --fs-base: 0.9375rem;/* 15px — corps de texte */
  --fs-md: 1.0625rem;  /* 17px — sous-titres (h3) */
  --fs-lg: 1.25rem;    /* 20px — titres de carte (h2) */
  --fs-xl: 1.625rem;   /* 26px — titre de page (h1) */
  --fs-2xl: 2.125rem;  /* 34px — chiffres héros */

  --lh-tight: 1.2;
  --lh-base: 1.55;

  /* --- Espacement : grille de 4px (demi-pas à 2 et 6) ------------------ */
  --sp-0: 0;
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 12px;
  --sp-6: 16px;
  --sp-7: 20px;
  --sp-8: 24px;
  --sp-9: 32px;
  --sp-10: 40px;
  --sp-11: 48px;
  --sp-12: 64px;

  /* --- Transitions : une seule durée par intention --------------------- */
  --t-fast: 0.12s;
  --t-base: 0.18s;
  --t-slow: 0.28s;
  --ease: cubic-bezier(0.2, 0.8, 0.3, 1);
}

/* transition douce uniquement pendant le changement de thème */
html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
  transition: background-color 0.18s ease, border-color 0.18s ease,
    color 0.18s ease, box-shadow 0.18s ease, fill 0.18s ease !important;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { overflow-x: clip; }          /* pas de scroll horizontal involontaire */

body {
  font-family: var(--font);
  font-size: var(--fs-base);
  /* Fond en profondeur : deux halos de marque très dilués sur l'aplat de
     base, fixés au viewport. Aucune image, aucun coût réseau. */
  background:
    radial-gradient(1100px 620px at 12% -8%, var(--depth-1), transparent 62%),
    radial-gradient(900px 560px at 92% 4%, var(--depth-2), transparent 58%),
    radial-gradient(760px 620px at 60% 92%, var(--depth-3), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  line-height: var(--lh-base);
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--brand-strong); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Hiérarchie : une seule famille, la différence se joue sur taille +
   graisse + interlignage. Les chiffres passent en chasse fixe pour que
   les colonnes de Pièces s'alignent. */
h1, h2, h3, h4 {
  line-height: var(--lh-tight); margin: 0 0 0.4em;
  font-weight: 800; letter-spacing: -0.02em; overflow-wrap: break-word;
}
h1 { font-size: var(--fs-lg); letter-spacing: -0.03em; }
h2 { font-size: var(--fs-md); }
h3 { font-size: var(--fs-base); letter-spacing: -0.01em; }
h4 { font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim); }
@media (min-width: 768px) {
  h1 { font-size: var(--fs-xl); }
  h2 { font-size: var(--fs-lg); }
  h3 { font-size: var(--fs-md); }
}
.amount, .balance-chip, .odds, .recap-val, .stat-value,
table.data td, .tk-total, .shame-amount {
  font-variant-numeric: tabular-nums;
}

::selection { background: var(--brand-wash); }

/* ---------- Barre de défilement fine, aux couleurs du site ---------- */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--radius-pill);
}
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* ---------- Transition d'entrée de page ---------- */
main.container { animation: page-in var(--t-slow) var(--ease); }
@keyframes page-in { from { opacity: 0; transform: translateY(6px); } }
/* Sortie : posée par app.js juste avant de suivre un lien interne. */
body.page-leaving main.container { opacity: 0; transform: translateY(-4px); transition: opacity 0.14s ease, transform 0.14s ease; }
@media (prefers-reduced-motion: reduce) {
  main.container { animation: none; }
  body.page-leaving main.container { opacity: 1; transform: none; transition: none; }
}

/* ---------- Layout ---------- */
.container {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 16px;
}
@media (min-width: 768px) { .container { padding: 0 20px; } }
main.container { flex: 1 0 auto; padding-top: 16px; padding-bottom: 56px; }

.layout-2col {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: start;
}
.col-side { position: static; }

/* Desktop : 2 colonnes, ticket collé à droite */
@media (min-width: 768px) {
  .layout-2col { grid-template-columns: minmax(0, 1fr) 340px; gap: 20px; }
  .col-side { position: sticky; top: calc(var(--header-h) + 16px); }
}

.page-head { margin-bottom: 12px; }
.page-head h1 { margin-bottom: 2px; }
.page-head .muted { font-size: 0.9rem; }

/* ---------- Bandeau sponsor ---------- */
.sponsor-banner {
  background: linear-gradient(90deg, var(--brand-wash), var(--action-wash));
  border-bottom: 1px solid var(--border);
  color: var(--text-soft);
  font-size: 0.8rem;
  font-weight: 600;
  text-align: center;
  padding: 6px 12px;
}

/* ---------- Header ---------- */
.site-header {
  background: var(--header-bg);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--header-line);
  position: sticky;
  top: 0;
  z-index: 40;
}
.site-header .bar {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  padding: 8px 16px;
  max-width: 1180px;
  margin: 0 auto;
  min-height: var(--header-h);
}
.brand {
  font-weight: 900;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 1;      /* peut se réduire : le menu ☰ reste prioritaire */
  min-width: 0;
  overflow: hidden;
}
.brand:hover { text-decoration: none; }
/* Sur desktop, la barre a toujours assez de place pour "OdinBet" en entier :
   l'overflow:hidden ci-dessus ne sert qu'à protéger le mobile (colonne du
   menu ☰ prioritaire). Le laisser actif plus large rognait le bonnet de Noël
   posé sur le T, qui déborde légèrement de la boîte de la lettre par design. */
@media (min-width: 768px) {
  :root[data-season] .brand { overflow: visible; }
}
.brand .dot { color: var(--brand); }
/* Le « O » est isolé pour qu'une saison puisse le remplacer par un objet
   (citrouille, boule de Noël…). Hors saison, c'est un O tout simple. */
.brand-o { position: relative; display: inline-block; }
.brand-o > svg { display: none; }

.site-nav { display: none; }
.header-right {
  display: flex; align-items: center; gap: 6px; margin-left: auto;
  min-width: 0;                       /* autorise la réduction sur petits écrans */
}
/* Le bouton menu ne doit jamais être poussé hors de l'écran. */
.nav-toggle { flex-shrink: 0; order: 99; }
@media (max-width: 400px) {
  .site-header .bar { gap: 6px 8px; padding: 8px 12px; }
  .header-right { gap: 4px; }
  .balance-chip { padding: 6px 8px; font-size: 0.82rem; }
}
.header-desk { display: none; }          /* pseudo / admin / déconnexion : desktop seulement */

.icon-btn {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  font-size: 1rem;
  line-height: 1;
  padding: 6px 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.icon-btn:hover { border-color: var(--brand); color: var(--text); }

.balance-chip {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  padding: 6px 12px;
  font-weight: 800;
  font-size: 0.88rem;
  white-space: nowrap;
  color: var(--text);
}
.balance-chip:hover { text-decoration: none; border-color: var(--brand); }
.balance-chip .amount { color: var(--action-ink); }
/* Runes : violet plutôt que l'ambre des Pièces — deux jetons côte à côte
   dans le header doivent se distinguer au premier coup d'œil. */
.runes-chip .amount { color: var(--rar-rare, #7b6bd6); }
.runes-chip:hover { border-color: var(--rar-rare, #7b6bd6); }

/* menu plein écran (mobile) */
.nav-toggle { display: inline-flex; }
#nav-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 70;                 /* au-dessus du header et du coupon flottant */
  padding: calc(var(--header-h) + 14px) 16px 30px;
  overflow-y: auto;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.16s ease, transform 0.16s ease;
}
html.nav-open #nav-overlay { opacity: 1; transform: none; pointer-events: auto; }
html.nav-open { overflow: hidden; }
#nav-overlay nav { display: flex; flex-direction: column; }
#nav-overlay a, #nav-overlay button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 16px 12px;
  border: none;
  border-bottom: 1px solid var(--border);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}
#nav-overlay a.active { color: var(--brand-strong); }
#nav-overlay a:hover, #nav-overlay button:hover { text-decoration: none; background: var(--surface-2); }
#nav-overlay .nav-cta { color: var(--brand-strong); }
/* bouton de fermeture (croix) posé en haut à droite du menu */
#nav-overlay #nav-close {
  position: absolute;
  top: 0; right: 10px; left: auto;
  height: var(--header-h);
  width: auto;
  padding: 0 8px;
  border: none;
  border-bottom: none;
  background: none;
  color: var(--text);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}

@media (min-width: 768px) {
  .site-header .bar { padding: 8px 20px; gap: 8px 16px; }
  .brand { font-size: 1.2rem; }
  .site-nav { display: flex; gap: 2px; flex: 1; margin-left: 4px; }
  .site-nav a {
    color: var(--text-soft);
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    font-weight: 600;
  }
  .site-nav a:hover { color: var(--text); background: var(--surface-3); text-decoration: none; }
  .site-nav a.active { color: var(--brand-strong); background: var(--brand-wash); }
  .header-right { gap: 8px; }
  .header-desk { display: flex; align-items: center; gap: 8px; }
  .nav-toggle { display: none; }
  #nav-overlay { display: none; }
}

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 16px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.05s ease, background 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}
.btn:hover { border-color: var(--action); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* tous les boutons d'action = la couleur d'action (orange) */
.btn-primary, .btn-cta {
  background: var(--action);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 6px 16px rgba(245, 150, 14, 0.3);
}
.btn-primary:hover, .btn-cta:hover { background: var(--action-strong); border-color: transparent; }
.btn-cta { box-shadow: 0 8px 22px rgba(245, 150, 14, 0.34); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-soft); }
.btn-ghost:hover { background: var(--surface-3); color: var(--text); border-color: transparent; }
.btn-sm { padding: 6px 12px; font-size: 0.84rem; }
.btn-block { width: 100%; }

/* ---------- Cartes ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 16px; }
.card h2 { margin-top: 0; }

.grid { display: grid; gap: 16px; }
@media (min-width: 768px) { .grid.cols-2 { grid-template-columns: 1fr 1fr; } }

/* ---------- Formulaires ---------- */
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 0.82rem; font-weight: 600; color: var(--text-soft); margin-bottom: 4px; }
.field input, .field textarea, .field select {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 12px;
  font: inherit;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 3px solid var(--primary-wash);
  outline-offset: 0;
  border-color: var(--primary);
}
.field .hint { font-size: 0.78rem; color: var(--text-dim); margin-top: 4px; }

.form-error {
  background: var(--bad-wash);
  border: 1px solid var(--bad-line);
  color: var(--bad-ink);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 0.9rem;
  margin-bottom: 12px;
}
.form-ok {
  background: var(--good-wash);
  border: 1px solid var(--good-line);
  color: var(--good-ink);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 0.9rem;
  margin-bottom: 12px;
}

/* ---------- Onglets (bet.html / login) ---------- */
.tabs { display: flex; gap: 6px; margin-bottom: 16px; }
.tabs button {
  flex: 1;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  font-weight: 700;
}
.tabs button.active { background: var(--surface); color: var(--text); border-color: var(--primary); }

/* ---------- Badges ---------- */
.badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 800;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text-soft);
  letter-spacing: 0.01em;
}
.badge.admin { color: var(--primary-strong); border-color: var(--primary); background: var(--primary-wash); }
.badge.broke { color: var(--action-ink); border-color: var(--action); background: var(--action-wash); }
.badge.rarity-common { color: var(--rar-common-ink); border-color: var(--rar-common); background: var(--rar-common-wash); }
.badge.rarity-rare { color: var(--rar-rare-ink); border-color: var(--rar-rare); background: var(--rar-rare-wash); }
.badge.rarity-legendary { color: var(--rar-legendary-ink); border-color: var(--rar-legendary); background: var(--rar-legendary-wash); }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table.data th, table.data td {
  text-align: left;
  padding: 8px 8px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.data th { color: var(--text-dim); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
.amount-pos { color: var(--good); font-weight: 700; }
.amount-neg { color: var(--bad); font-weight: 700; }

/* ---------- Divers ---------- */
.muted { color: var(--text-dim); }
.stack > * + * { margin-top: 12px; }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
.empty-state {
  text-align: center;
  color: var(--text-dim);
  padding: var(--sp-9) var(--sp-6);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  font-size: var(--fs-sm);
}
.empty-state.is-small { padding: var(--sp-6) var(--sp-5); }
.empty-art {
  font-size: 2.4rem; line-height: 1;
  margin-bottom: var(--sp-4);
  display: inline-block;
  filter: grayscale(0.25); opacity: 0.9;
  animation: empty-float 4.5s ease-in-out infinite;
}
.empty-state.is-small .empty-art { font-size: 1.8rem; margin-bottom: var(--sp-3); }
@keyframes empty-float {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-5px) rotate(2deg); }
}
.empty-title {
  margin: 0; font-size: var(--fs-base); font-weight: 700; color: var(--text);
}
.empty-text { margin: var(--sp-2) auto 0; max-width: 42ch; }
.empty-state .btn { margin-top: var(--sp-5); }
@media (prefers-reduced-motion: reduce) { .empty-art { animation: none; } }

/* ---------- Fil d'Ariane ---------- */
.crumbs {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.crumbs a { color: var(--text-soft); }
.crumbs .sep { color: var(--border-strong); }

/* ==================================================================
   Cartes de marché (paris)
   ================================================================== */
.bet-list { display: block; }
.cat-title {
  font-size: 0.8rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-dim);
  margin: 20px 0 8px;
}
.cat-title:first-child { margin-top: 0; }

.bet-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 16px;
  box-shadow: var(--shadow-sm);
  margin-bottom: 12px;
  transition: box-shadow 0.16s ease, border-color 0.16s ease;
}
@media (min-width: 768px) { .bet-card { padding: 16px 16px; margin-bottom: 12px; } }
.bet-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow); }

/* "En vedette" : bordure marquée + badge, PAS de fond différent */
.bet-card.featured { border: 2px solid var(--action); }
.bet-card.special { border-left: 3px solid var(--brand); }
.featured-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 900;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #fff;
  background: var(--action);
  border-radius: var(--radius-pill);
  padding: 3px 12px;
  margin-bottom: 8px;
}

.bet-head { display: flex; align-items: flex-start; gap: 8px; }
.bet-head-main { min-width: 0; flex: 1; }
.bet-icon {
  flex-shrink: 0;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  font-size: 1rem; line-height: 1;
}
.bet-context {
  font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bet-head h3 { margin: 1px 0 0; font-size: 1.02rem; line-height: 1.3; }
.bet-head h3 a { color: var(--text); }
.bet-head h3 a:hover { color: var(--brand-strong); }
.bet-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.bet-desc { margin: 8px 0 0; font-size: 0.88rem; color: var(--text-dim); }

/* pill "▶ Live" -> lien stream, seulement quand le match est en direct */
.bet-stream-pill {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px;
  border-radius: var(--radius-pill);
  background: var(--bad); color: #fff;
  font-size: 0.72rem; font-weight: 800;
  white-space: nowrap;
  transition: transform 0.15s ease;
}
.bet-stream-pill:hover { transform: scale(1.05); text-decoration: none; color: #fff; }

/* ---- Ligne d'affiche : [Équipe A]  [contexte temporel]  [Équipe B] ---- */
.match-line {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding: 8px 4px;
  border-top: 1px solid var(--border);
}
.match-line .ml-team {
  font-weight: 800;
  font-size: 1.02rem;
  color: var(--text);
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.match-line .ml-team-b { text-align: right; }
.match-line .ml-mid {
  display: flex; flex-direction: column; align-items: center;
  line-height: 1.15;
}
.ml-when-label {
  font-size: 0.72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-dim);
}
.ml-when-label.is-live { color: var(--bad); }
.ml-when-sub { font-size: 0.9rem; font-weight: 800; color: var(--text); }
.match-line.is-live { border-color: var(--bad-line); }
.bet-foot { margin-top: 12px; font-size: 0.76rem; color: var(--text-dim); font-weight: 600; }

.bet-tag {
  font-size: 0.68rem;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--text-soft);
  border: 1px solid var(--border);
}
.bet-tag.tag-hot { background: var(--brand-wash); color: var(--brand-strong); border-color: var(--brand); }
.bet-tag.tag-special { background: var(--brand-wash); color: var(--brand-strong); }

/* bandeau score en direct (match rattaché) */
.match-score {
  margin-top: 8px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.match-score.is-live { border-color: var(--bad-line); background: var(--bad-wash); }
.ms-line {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 0.9rem;
}
.ms-team { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-team-b { text-align: right; }
.ms-nums { font-weight: 900; font-size: 1.05rem; letter-spacing: 0.02em; }
.ms-nums b { color: var(--text); }
.ms-sep { margin: 0 4px; color: var(--text-dim); }
.ms-sub {
  margin-top: 4px;
  font-size: 0.78rem;
  color: var(--text-soft);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.ms-sub b { color: var(--text); font-weight: 800; }
.ms-streak {
  font-weight: 800;
  color: var(--action-ink);
  background: var(--action-wash);
  border: 1px solid var(--action);
  border-radius: var(--radius-pill);
  padding: 1px 8px;
  font-size: 0.72rem;
}
.ms-form {
  margin-top: 4px;
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.72rem;
  color: var(--text-dim);
  font-weight: 600;
}
.ms-form span:last-child { text-align: right; }

/* section "Cotes en forte hausse" (§7) */
.movers { margin: 6px 0 4px; }
.movers-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mover {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.mover:hover { border-color: var(--brand); text-decoration: none; }
.mover-txt { display: flex; flex-direction: column; min-width: 0; }
.mover-txt b { font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mover-txt span { font-size: 0.78rem; color: var(--text-dim); }
.mover-odds { flex-shrink: 0; font-weight: 800; font-size: 0.92rem; color: var(--action-ink); white-space: nowrap; }

/* ==================================================================
   Vue match détaillée (§8)
   ================================================================== */
.match-hub-head { margin-bottom: 12px; }
.mh-top {
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}
.mh-teams {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  font-size: 1.15rem;
  font-weight: 800;
}
.mh-teams > span:first-child { text-align: right; }
.mh-teams > span:last-child { text-align: left; }
.mh-vs {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text-dim);
  white-space: nowrap;
}

.market-tabs {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
  -webkit-overflow-scrolling: touch;
}
.market-tab {
  flex-shrink: 0;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-dim);
  font: inherit;
  font-weight: 800;
  font-size: 0.92rem;
  padding: 8px 12px;
  cursor: pointer;
  white-space: nowrap;
}
.market-tab:hover { color: var(--text); }
.market-tab.active { color: var(--brand-strong); border-bottom-color: var(--brand); }

/* barre de résolution orga sous une carte de marché (vue match) */
.market-admin {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.market-admin .ma-winner {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font: inherit;
  font-size: 0.85rem;
  max-width: 220px;
}

/* lien "+N marchés" sur une carte de pari liée à un match (accueil) */
.more-markets {
  display: inline-block;
  margin-top: 8px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--brand-strong);
}
.more-markets:hover { text-decoration: underline; }

/* badge EN DIRECT + point qui pulse */
.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.68rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  color: var(--bad-ink);
  background: var(--bad-wash);
  border: 1px solid var(--bad-line);
  border-radius: var(--radius-pill);
  padding: 2px 8px 2px 6px;
}
.live-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--bad);
  box-shadow: 0 0 0 0 rgba(229, 72, 77, 0.55);
  animation: live-pulse 1.6s ease-out infinite;
}
@keyframes live-pulse {
  0% { box-shadow: 0 0 0 0 rgba(229, 72, 77, 0.55); }
  70% { box-shadow: 0 0 0 7px rgba(229, 72, 77, 0); }
  100% { box-shadow: 0 0 0 0 rgba(229, 72, 77, 0); }
}
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }

.countdown {
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--action-ink);
  background: var(--action-wash);
  border: 1px solid var(--action);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
}
.countdown.urgent { color: var(--bad-ink); background: var(--bad-wash); border-color: var(--bad-line); }
/* compte à rebours "commence dans X" : couleur de marque (à venir, pas urgent) */
.countdown.starts { color: var(--brand-strong); background: var(--brand-wash); border-color: var(--brand); }

.info-i {
  width: 17px; height: 17px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  color: var(--text-dim);
  font-size: 0.68rem;
  font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  cursor: help;
}

/* ---- issues : boutons "pilule", nom au-dessus / cote (gras italique) dessous ---- */
.outcomes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-top: 12px;
}
.outcomes.cols-3 { grid-template-columns: repeat(3, 1fr); }
.outcome.lone { grid-column: 1 / -1; }

.outcome.pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-height: 54px;
  padding: 6px 8px 8px;
  border-radius: 14px;                       /* pilule très arrondie */
  border: 1.5px solid var(--brand);
  background: var(--brand-wash);             /* remplissage accent */
  color: var(--text);
  font: inherit;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  text-align: center;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.outcome.pill:hover:not(:disabled) {
  transform: scale(1.03);
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  box-shadow: 0 6px 18px rgba(15, 181, 177, 0.32);
}
.outcome.pill:active:not(:disabled) { transform: scale(0.98); }
.outcome.pill:disabled { opacity: 0.55; cursor: not-allowed; }

.outcome.pill.selected {
  background: var(--brand);
  border-color: var(--brand-strong);
  color: #fff;
  box-shadow: 0 6px 18px rgba(15, 181, 177, 0.45);
}
.outcome.pill.winner {
  background: var(--good); border-color: var(--good-ink); color: #fff;
}

/* nom : au-dessus, discret */
.o-name {
  font-weight: 500;
  font-size: 0.76rem;
  max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0.9;
}
/* cote : EN DESSOUS, GRAS ITALIQUE, nettement plus grande — elle domine */
.o-odds {
  font-weight: 800;
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1;
  letter-spacing: -0.01em;
}
.outcome.pill:not(.selected):not(.winner):not(:hover) .o-odds { color: var(--action-ink); }

.o-trend {
  font-style: normal;
  font-size: 0.6rem;
  vertical-align: 0.28em;
  margin-left: 2px;
}
.o-trend.up { color: var(--good); }
.o-trend.down { color: var(--bad); }
.outcome.pill:hover .o-trend,
.outcome.pill.selected .o-trend, .outcome.pill.winner .o-trend { color: rgba(255, 255, 255, 0.9); }

.outcome.odds-bumped { animation: odds-bump 1.6s ease-out; }
@keyframes odds-bump {
  0% { box-shadow: 0 0 0 0 var(--action); }
  12% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--action) 45%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.outcome.odds-bumped .o-odds { animation: odds-pop 0.5s ease-out; }
@keyframes odds-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.14); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .outcome.pill:hover:not(:disabled), .outcome.pill:active:not(:disabled) { transform: none; }
  .outcome.odds-bumped, .outcome.odds-bumped .o-odds { animation: none; }
}

/* barre de popularité : ancrée en bas, verte (la + misée) -> rouge (la - misée) */
.o-pop {
  position: absolute;
  left: 8px; right: 8px; bottom: 5px;
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, currentColor 16%, transparent);
  overflow: hidden;
}
.o-pop-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--text-dim);
  transition: width 0.5s cubic-bezier(0.2, 0.7, 0.3, 1), background 0.3s ease;
}
.o-pop-fill.pop-hot { background: var(--good); }
.o-pop-fill.pop-cold { background: var(--bad); }
.outcome.pill:hover .o-pop-fill,
.outcome.pill.selected .o-pop-fill,
.outcome.pill.winner .o-pop-fill { background: rgba(255, 255, 255, 0.9); }

/* ==================================================================
   Coupon de pari (ticket)
   Desktop : carte dans la colonne de droite.
   Mobile  : bandeau flottant -> tiroir (bottom sheet).
   ================================================================== */
.ticket-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - var(--header-h) - 40px);
  overflow: hidden;
}

.tk-backdrop, .tk-bar { display: none; }

.tk-handle { display: none; }

.tk-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 800;
  font-size: 0.92rem;
  flex-shrink: 0;
}
.tk-clear {
  background: none; border: none;
  color: var(--text-dim);
  cursor: pointer;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
}
.tk-clear:hover { color: var(--bad); }

/* onglets Simple / Combiné */
.tk-tabs {
  display: flex;
  gap: 4px;
  padding: 8px 12px 0;
  flex-shrink: 0;
}
.tk-tabs button {
  flex: 1;
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-soft);
  font: inherit;
  font-weight: 800;
  font-size: 0.84rem;
  padding: 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.tk-tabs button.active { background: var(--brand); border-color: var(--brand); color: #fff; }

.tk-body { padding: 12px 12px; overflow-y: auto; flex: 1; }

/* état vide : texte seul, pas d'image */
.tk-empty-text {
  margin: 8px 0;
  padding: 24px 8px;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.9rem;
}

/* cartes récap compactes */
.tk-cards { display: flex; flex-direction: column; gap: 8px; }
.tk-pick-card {
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 32px 8px 12px;
}
.tk-x {
  position: absolute;
  top: 6px; right: 6px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; border-radius: 6px;
  color: var(--text-dim); cursor: pointer;
  font-size: 0.76rem; line-height: 1;
}
.tk-x:hover { color: var(--bad); background: var(--bad-wash); }
.tk-pick-meta {
  font-size: 0.72rem;
  color: var(--text-dim);
  font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tk-pick-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 3px;
}
.tk-pick-name { font-weight: 600; font-size: 0.9rem; }
.tk-pick-odds { flex-shrink: 0; font-weight: 700; font-size: 1rem; color: var(--action-ink); }
.tk-pick-stake {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--border);
}
.tk-pick-stake span { font-size: 0.78rem; color: var(--text-dim); font-weight: 600; }
.tk-pick-stake input {
  width: 92px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font: inherit; font-weight: 700; text-align: right;
}

/* pied : cote totale, mise, gains, CTA */
.tk-foot { padding: 12px 16px 12px; border-top: 1px solid var(--border); flex-shrink: 0; }
.tk-line { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; font-size: 0.9rem; }
.tk-line span { color: var(--text-dim); font-weight: 600; }
.tk-line b { font-weight: 800; color: var(--text); }
.tk-odds-line { border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.tk-stake { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 8px 0 2px; }
.tk-stake label { font-weight: 700; font-size: 0.9rem; }
.tk-stake input {
  width: 118px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 12px;
  font: inherit;
  font-weight: 800;
  text-align: right;
}
.tk-payout b { color: var(--good); font-size: 1.2rem; }
.tk-msg:not(:empty) { margin: 8px 0 0; }
.tk-foot .btn { margin-top: 8px; }
.tk-conflict {
  margin-top: 8px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--bad-wash);
  border: 1px solid var(--bad-line);
  color: var(--bad-ink);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.35;
}

/* -------- mobile : bandeau + tiroir -------- */
@media (max-width: 767px) {
  .layout-2col { gap: 0; }
  .col-side { margin: 0; min-height: 0; }

  /* le ticket "en flux" (colonne) ne sert plus : on passe en bandeau/tiroir */
  #ticket .ticket-panel {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 60;
    max-height: 84vh;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: none;
    box-shadow: var(--shadow-lg);
    transform: translateY(105%);
    transition: transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1);
  }
  #ticket.expanded .ticket-panel { transform: translateY(0); }

  #ticket .tk-handle {
    display: block;
    width: 42px; height: 4px;
    border-radius: 999px;
    background: var(--border-strong);
    margin: 8px auto 2px;
    flex-shrink: 0;
  }

  #ticket .tk-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: var(--backdrop);
    z-index: 55;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
  }
  #ticket.expanded .tk-backdrop { opacity: 1; pointer-events: auto; }

  /* bandeau flottant quand des sélections existent et que le tiroir est fermé */
  #ticket.has-selections .tk-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    position: fixed;
    left: 10px; right: 10px; bottom: 10px;
    z-index: 58;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 8px 12px;
    font: inherit;
    text-align: left;
    cursor: pointer;
  }
  #ticket.expanded .tk-bar { display: none; }
  .tk-bar-count {
    flex-shrink: 0;
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-weight: 900;
    display: flex; align-items: center; justify-content: center;
  }
  .tk-bar-mid { flex: 1; display: flex; flex-direction: column; min-width: 0; }
  .tk-bar-label { font-size: 0.78rem; color: var(--text-dim); font-weight: 600; }
  .tk-bar-gain { font-weight: 800; font-size: 0.95rem; }
  .tk-bar-cta { flex-shrink: 0; color: var(--primary-strong); font-weight: 800; font-size: 0.85rem; }

  /* le bandeau flottant ne doit jamais masquer le disclaimer du pied de page */
  body:has(#ticket.has-selections) main.container { padding-bottom: 20px; }
  body:has(#ticket.has-selections) .site-footer { padding-bottom: 80px; }
}

/* ==================================================================
   Coupons (historique)
   ================================================================== */
.ticket-list { display: flex; flex-direction: column; gap: 8px; }
.ticket {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px;
  background: var(--surface-2);
}
.ticket-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 0.82rem; margin-bottom: 8px; }
.legs { list-style: none; margin: 0; padding: 0; }
.leg { display: flex; gap: 8px; padding: 4px 0; }
.leg-mark { width: 16px; text-align: center; font-weight: 800; }
.leg-txt { display: flex; flex-direction: column; }
.leg-bet { font-size: 0.78rem; color: var(--text-dim); }
.leg-pick { font-size: 0.9rem; }
.leg-won .leg-mark { color: var(--good); }
.leg-lost .leg-mark { color: var(--bad); }
.leg-void .leg-mark, .leg-void .leg-pick { color: var(--text-dim); text-decoration: line-through; }
.ticket-foot { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); font-size: 0.9rem; }
.badge.st-pending { color: var(--primary-strong); border-color: var(--primary); background: var(--primary-wash); }
.badge.st-won { color: #0f7a52; border-color: #b9e6d2; background: var(--good-wash); }
.badge.st-lost { color: #a3282c; border-color: #f3c0c1; background: var(--bad-wash); }
.badge.st-refunded { color: var(--text-dim); }

/* cash out (§7) */
.ticket-cashout {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.ticket-cashout .btn { border-color: var(--brand); color: var(--brand-strong); font-weight: 800; }
.ticket-cashout .btn:hover { background: var(--brand-wash); }
.ticket-cashout .muted { font-size: 0.78rem; }

/* ==================================================================
   Profil
   ================================================================== */
.hero h1 { margin-bottom: 6px; }
#p-card, #pub-card { transition: background-image 0.3s ease; }
.avatar {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 900; font-size: 0.95rem;
  flex-shrink: 0;
  color: var(--text-soft);
}
.skin-slot + .skin-slot { margin-top: 12px; }
.skin-slot h3 { font-size: 0.95rem; margin: 0 0 8px; }
.skin-row { display: flex; flex-wrap: wrap; gap: 8px; }
.skin-chip {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 4px 6px 4px 12px;
}
.skin-chip.equipped { border-color: var(--primary); background: var(--primary-wash); }
.skin-name { font-weight: 800; }

/* ==================================================================
   Boutique
   ================================================================== */
.shop-notice {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 12px 0 8px;
  padding: 16px 20px;
  border-radius: var(--radius);
  border: 2px solid var(--accent);
  background: linear-gradient(120deg, var(--action-wash), var(--brand-wash) 85%);
  box-shadow: 0 8px 24px rgba(245, 165, 36, 0.18);
  overflow: hidden;
}
.shop-notice::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 40%;
  left: -60%;
  background: linear-gradient(100deg, transparent, var(--shine), transparent);
  transform: skewX(-18deg);
  animation: shop-shine 4.5s ease-in-out infinite;
}
@keyframes shop-shine { 0%, 60% { left: -60%; } 85%, 100% { left: 130%; } }
.shop-notice-emoji { font-size: 2.6rem; line-height: 1; flex-shrink: 0; }
.shop-notice-tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: var(--radius-pill);
  padding: 3px 8px;
  margin-bottom: 6px;
}
.shop-notice-text {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1.4;
}
@media (prefers-reduced-motion: reduce) { .shop-notice::after { animation: none; display: none; } }
@media (max-width: 767px) {
  .shop-notice { flex-direction: column; text-align: center; gap: 8px; padding: 12px 16px; }
}

.shop-section { margin-top: 24px; }
.shop-section:first-child { margin-top: 4px; }
.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  margin-top: 12px;
}
.shop-item { display: flex; flex-direction: column; margin: 0; }
.shop-item-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.shop-item-head h3 { margin: 0 0 4px; font-size: 1rem; }
.shop-item p.muted { flex: 1; font-size: 0.88rem; }
.stock-line { font-size: 0.78rem; color: var(--text-dim); margin: 4px 0 0; }
.stock-line.stock-match { color: var(--accent-ink); font-weight: 700; }
.shop-item-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 12px; padding-top: 8px; border-top: 1px solid var(--border);
}
.shop-item-foot .price { font-weight: 900; color: var(--accent-ink); }
/* Deux lignes prix+bouton pour un article double-monnaie (commun) : la
   deuxième colle un peu plus près, sinon l'écart entre les deux paraît
   accidentel plutôt que voulu. */
.shop-item-foot + .shop-item-foot { margin-top: 6px; padding-top: 6px; }
.shop-item-foot .price-runes { color: var(--rar-rare, #7b6bd6); }
.buy-note { margin-top: 8px; }
.buy-note textarea {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 8px;
  font: inherit;
  resize: vertical;
  margin-bottom: 8px;
}
.buy-msg:not(:empty) { margin-top: 8px; }

/* ==================================================================
   Classement + Hall of Shame
   ================================================================== */
.lb-table td, .lb-table th { vertical-align: middle; }
.lb-table .lb-rank { font-size: 1.05rem; font-weight: 900; width: 40px; text-align: center; }
.lb-table tr.lb-podium { background: var(--action-wash); }
.lb-table a { color: var(--text); font-weight: 600; }
.lb-table a:hover { color: var(--primary-strong); }

.shame-title { margin-top: 32px; }
.shame-headline {
  display: flex; align-items: center; gap: 16px;
  border-color: var(--bad);
  background: linear-gradient(180deg, var(--bad-wash), var(--surface));
}
.shame-amount { font-size: 2rem; font-weight: 900; color: var(--bad); white-space: nowrap; }
.shame-headline a { color: var(--text); }
.shame-wall { display: flex; flex-wrap: wrap; gap: 8px; }
.shame-chip {
  display: inline-block;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  padding: 4px 12px;
  font-size: 0.85rem;
  color: var(--text-soft);
}
.shame-wall a:hover .shame-chip { color: var(--text); border-color: var(--accent); }
.shame-list { margin: 0; padding-left: 20px; }
.shame-list li { padding: 4px 0; border-bottom: 1px solid var(--border); }
.shame-list li:last-child { border-bottom: none; }
.shame-list a { color: var(--text); font-weight: 600; }

/* ==================================================================
   Crédits
   ================================================================== */
.credits-ul { list-style: none; margin: 0; padding: 0; }
.credits-ul li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.credits-ul li:last-child { border-bottom: none; }
.credit-role { color: var(--text-dim); font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; }
.credit-name { font-weight: 800; font-size: 1.05rem; }

/* ==================================================================
   Notifications
   ================================================================== */
.notif-wrap { position: relative; display: inline-flex; }
.notif-bell {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  font-size: 1rem;
  line-height: 1;
  padding: 6px 8px;
  cursor: pointer;
}
.notif-bell:hover { border-color: var(--primary); }
.notif-count {
  position: absolute; top: -6px; right: -6px;
  background: var(--cta); color: #fff;
  border-radius: 999px;
  font-size: 0.66rem; font-weight: 900;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
}
#notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: min(340px, calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  z-index: 60;
  overflow: hidden;
}
.notif-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 12px; border-bottom: 1px solid var(--border);
}
.notif-mute { background: none; border: none; cursor: pointer; font-size: 1rem; }
.notif-list { max-height: 60vh; overflow-y: auto; }
.notif-item { display: block; padding: 8px 12px; border-bottom: 1px solid var(--border); color: var(--text); }
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--surface-2); text-decoration: none; }
.notif-item.unread { background: var(--primary-wash); }
.notif-item.unread .notif-title::before {
  content: ""; display: inline-block;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--primary); margin-right: 6px; vertical-align: middle;
}
.notif-title { font-weight: 800; font-size: 0.9rem; }
.notif-body { color: var(--text-soft); font-size: 0.85rem; margin-top: 2px; }
.notif-time { color: var(--text-dim); font-size: 0.72rem; margin-top: 4px; }
.notif-empty { padding: 20px 12px; text-align: center; color: var(--text-dim); font-size: 0.9rem; }

/* ==================================================================
   Admin
   ================================================================== */
/* .stat-subtabs partage le meme habillage que .admin-tabs (sous-onglets de
   la page Statistiques), mais SANS la classe .admin-tabs elle-meme : le
   commutateur d'onglets principal cible ".admin-tabs button" pour appeler
   showTab() — la lui donner aurait fait retomber chaque clic sur "dash". */
.admin-tabs, .stat-subtabs { display: flex; gap: 4px; margin: 4px 0 16px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.admin-tabs button, .stat-subtabs button {
  background: none; border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-dim);
  font: inherit; font-weight: 800;
  padding: 8px 12px; cursor: pointer;
}
.admin-tabs button:hover, .stat-subtabs button:hover { color: var(--text); }
.admin-tabs button.active, .stat-subtabs button.active { color: var(--primary-strong); border-bottom-color: var(--primary); }
.new-item-details { margin-top: 12px; }
.new-item-details summary { display: inline-block; list-style: none; }
.new-item-details summary::-webkit-details-marker { display: none; }
#form-settings h3 { margin: 12px 0 6px; font-size: 0.9rem; color: var(--primary-strong); text-transform: uppercase; letter-spacing: 0.04em; }
#form-settings h3:first-child { margin-top: 0; }

/* Édition des cotes en direct (liste des paris admin) */
.oc-edit {
  display: flex; flex-direction: column; gap: 6px;
  margin: 8px 0;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.oc-edit .oc-line { gap: 6px; }
.oc-edit input {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font: inherit;
}
.oc-edit input:disabled { opacity: 0.6; cursor: not-allowed; }
.oc-edit .oc-odds { font-weight: 700; text-align: right; }
.oc-edit textarea {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font: inherit;
  resize: vertical;
}

/* pastilles de compo (panel admin) */
.mp-chip {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  color: var(--text-soft);
  margin: 1px 0;
}
.mp-chip.star { background: var(--action-wash); color: var(--action-ink); border: 1px solid var(--action); }

/* ==================================================================
   Régie (2e écran) — reste sombre, c'est un overlay stream
   ================================================================== */
.regie-body { min-height: 100vh; display: flex; background: #0b1622; color: #e7f1f7; }
#regie { flex: 1; display: flex; flex-direction: column; padding: 24px; }
.regie-start { margin: auto; text-align: center; max-width: 460px; }
.regie-start h1 { font-size: 2rem; }
.regie-start .muted { color: #93aec1; }
.regie-start .btn { font-size: 1.1rem; padding: 12px 20px; margin-top: 12px; background: var(--primary); color: #04222b; border: none; }
.regie-status { position: fixed; top: 14px; right: 18px; font-size: 0.8rem; color: #93aec1; display: flex; align-items: center; gap: 6px; }
.dot-on, .dot-off { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.dot-on { background: #34d399; box-shadow: 0 0 8px #34d399; }
.dot-off { background: #fb7185; }
#regie-stage { flex: 1; display: flex; align-items: center; justify-content: center; min-height: 40vh; }
.regie-alert {
  display: flex; align-items: center; gap: 28px;
  background: linear-gradient(135deg, #172c3e, #12212f);
  border: 1px solid var(--primary);
  border-radius: 20px;
  padding: 32px 40px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  max-width: 90vw;
  opacity: 0; transform: translateY(30px) scale(0.95);
  transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.2, 1.2, 0.3, 1);
}
.regie-alert.in { opacity: 1; transform: translateY(0) scale(1); }
.regie-alert.out { opacity: 0; transform: translateY(-20px) scale(0.97); }
.regie-emoji { font-size: 4.5rem; line-height: 1; }
.regie-who { font-size: 2.4rem; font-weight: 900; color: var(--primary); }
.regie-what { font-size: 1.5rem; margin-top: 2px; }
.regie-note {
  margin-top: 8px; font-size: 1.2rem; font-style: italic; color: #e7f1f7;
  background: #0e1b2a; border-left: 3px solid var(--accent);
  padding: 8px 12px; border-radius: 6px;
}
.regie-price { margin-top: 8px; font-size: 1.3rem; font-weight: 800; color: var(--accent); }
#regie-feed { display: flex; flex-direction: column; gap: 6px; max-width: 640px; margin: 0 auto; width: 100%; }
.regie-feed-item {
  display: flex; align-items: center; gap: 12px;
  background: #12212f; border: 1px solid #24405a; border-radius: 10px;
  padding: 8px 12px; font-size: 0.9rem; opacity: 0.8;
}
.regie-feed-item .regie-emoji { font-size: 1.4rem; }
.regie-feed-item .regie-who { font-size: 1rem; color: var(--primary); }
.regie-feed-item .regie-what { font-size: 0.9rem; }
.regie-feed-item .regie-note { font-size: 0.85rem; margin-top: 4px; padding: 4px 8px; }
.regie-feed-item .regie-price { font-size: 0.85rem; margin-top: 2px; }

/* ==================================================================
   Pied de page / disclaimer
   ================================================================== */
.site-footer {
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 16px;
  margin-top: auto;
}
.site-footer .inner {
  max-width: 1180px; margin: 0 auto;
  display: flex; gap: 12px; align-items: center; justify-content: space-between;
  flex-wrap: wrap; font-size: 0.82rem; color: var(--text-dim);
}
.disclaimer {
  font-weight: 700;
  color: var(--text-soft);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
}

/* ==================================================================
   Toast
   ================================================================== */
#toast {
  position: fixed; left: 50%; bottom: 24px;
  transform: translateX(-50%) translateY(8px);
  background: var(--toast-bg);
  border: 1px solid var(--toast-bg);
  color: var(--toast-fg);
  padding: 12px 16px;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
  z-index: 80;
  font-size: 0.9rem;
  font-weight: 600;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ==================================================================
   Animation d'apparition au scroll (opt-in : seulement si le JS tourne)
   ================================================================== */
html.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.4s ease, transform 0.45s cubic-bezier(0.2, 0.7, 0.3, 1);
}
html.js .reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .reveal { opacity: 1; transform: none; transition: none; }
  .regie-alert { transition: opacity 0.2s ease; }
}

/* ==================================================================
   Roulette de secours (remplace la recharge passive) — un seul écran.
   Le rouge / noir / vert est confiné à ce mini-jeu, jamais au thème.
   ================================================================== */
/* Les couleurs de la roulette sont des réglages admin, posés en ligne par
   roulette.js — elles ne vivent plus en variables CSS (elles doivent être
   identiques dans les deux thèmes, sinon la roue ne correspondrait plus aux
   pastilles de choix). */

.roul-card { max-width: 520px; margin: 0 auto; text-align: center; }
.roul-card h1 { margin: 0 0 2px; font-size: 1.4rem; }

.roul-stage {
  position: relative;
  width: min(320px, 78vw);
  aspect-ratio: 1;
  margin: 20px auto 6px;
}
.roul-wheel {
  position: absolute; inset: 0;
  border-radius: 50%;
  /* Le conic-gradient est posé en ligne par roulette.js : le nombre de
     quartiers, leur ordre et leurs couleurs viennent des réglages admin.
     Cette valeur ne sert que si le JS n'a pas encore rendu la roue. */
  background: var(--surface-3);
  border: 6px solid var(--surface);
  box-shadow: 0 0 0 3px var(--border-strong), var(--shadow-lg),
    inset 0 0 26px rgba(0, 0, 0, 0.4);
  will-change: transform;
}
.roul-ball-track {
  position: absolute; inset: 0;
  transform-origin: 50% 50%;
  will-change: transform;
}
.roul-ball {
  position: absolute; top: 4.5%; left: 50%;
  width: 7%; aspect-ratio: 1; margin-left: -3.5%;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 30%, #fff, #cbd0da 68%, #99a0ac);
  box-shadow: 0 2px 7px rgba(0, 0, 0, 0.55);
}
.roul-hub {
  position: absolute; top: 50%; left: 50%;
  width: 34%; aspect-ratio: 1;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  font-size: 1.5rem;
  background: var(--surface);
  border-radius: 50%;
  box-shadow: 0 0 0 3px var(--border-strong), var(--shadow);
}

.roul-panel { margin-top: 16px; }
.roul-msg { margin: 0 0 12px; color: var(--text-soft); }
.roul-msg-win { color: var(--good-ink); font-weight: 700; }
.roul-err { color: var(--bad-ink); }

.roul-choices { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.roul-choice {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 12px 6px;
  border: 2px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text); font: inherit; cursor: pointer;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.roul-choice:hover { transform: translateY(-2px) scale(1.02); box-shadow: var(--shadow); }
.roul-choice:active { transform: translateY(0) scale(0.99); }
.roul-choice:disabled { opacity: 0.5; cursor: not-allowed; }
.roul-choice.is-picked { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-wash); }
.roul-swatch {
  width: 26px; height: 26px; border-radius: 50%;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25);
}
.roul-choice-label { font-weight: 700; font-size: 0.9rem; }
.roul-choice-odds { font-size: 0.76rem; color: var(--text-dim); }

.roul-fine { margin: 16px 0 0; font-size: 0.74rem; color: var(--text-dim); }

.roul-win .roul-hub { animation: roul-hub-pop 0.5s ease; }
@keyframes roul-hub-pop { 40% { transform: translate(-50%, -50%) scale(1.18); } }

/* Pastille d'accès rapide dans le header quand le solde est à 0.
   Mobile : icône seule, pour ne jamais pousser le menu ☰ hors de l'écran. */
.roul-pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  padding: 6px 8px;
  flex-shrink: 0;
  border: 1px solid var(--action);
  border-radius: var(--radius-pill);
  background: var(--action-wash); color: var(--action-ink);
  font-weight: 700; font-size: 0.82rem; white-space: nowrap;
  transition: transform 0.15s ease;
}
.roul-pill:hover { transform: scale(1.03); text-decoration: none; }
.roul-pill-txt { display: none; }
@media (min-width: 768px) {
  .roul-pill { padding: 4px 12px; }
  .roul-pill-txt { display: inline; }
}

@media (prefers-reduced-motion: reduce) {
  .roul-ball-track, .roul-wheel { transition: none !important; }
  .roul-choice:hover { transform: none; }
}

/* ==================================================================
   Paris de service (§10) : démonstration permanente + tutoriel.
   ================================================================== */
.bet-tag.tag-demo {
  background: var(--action-wash);
  color: var(--action-ink);
  border-color: var(--action);
}
.bet-card-demo {
  border-style: dashed;
  border-color: var(--border-strong);
  /* Une couche opaque SOUS les hachures : sans elle, le transparent laisse
     voir le fond de page entre les bandes — invisible sur fond clair, mais
     illisible dès que la page a une couleur franche (saison Noël). */
  background:
    repeating-linear-gradient(-45deg, transparent 0 12px, var(--surface-2) 12px 24px),
    var(--surface);
}
.bet-card-demo .bet-foot { font-style: italic; }

/* Bouton d'issue en mode démo : cliquable, mais aucun lien avec le coupon. */
.outcome-demo { cursor: pointer; }
.outcome-demo.poked {
  border-color: var(--brand);
  background: var(--brand-wash);
  box-shadow: 0 0 0 3px var(--brand-wash);
}
.outcome-demo { position: relative; overflow: hidden; }
.outcome-demo.poked::after {
  content: "aucun gain, c'est une démo 🙂";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 2px 8px;
  font-size: 0.66rem;
  font-weight: 700;
  text-align: center;
  color: var(--brand-ink, var(--brand-strong));
  background: var(--brand-wash);
}

/* ==================================================================
   Tutoriel guidé (§11) : voile + élément « soulevé » + bulle.
   ================================================================== */
/* conteneur neutre : pas de contexte d'empilement, les enfants vivent
   dans celui du <body> pour que .tuto-raise puisse passer entre le
   voile et la bulle. */
.tuto-root { position: static; }
.tuto-dim {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(9, 14, 22, 0.74);
  animation: tuto-fade 0.22s ease;
}
.tuto-dim.soft { background: rgba(9, 14, 22, 0.5); }
@keyframes tuto-fade { from { opacity: 0; } }

/* l'élément mis en avant passe au-dessus du voile, avec un halo */
.tuto-raise { position: relative !important; z-index: 1001 !important; }
.tuto-glow {
  outline: 3px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 8px rgba(18, 189, 185, 0.28), 0 16px 46px rgba(0, 0, 0, 0.5);
  animation: tuto-pulse 1.8s ease-in-out infinite;
}
@keyframes tuto-pulse {
  50% { box-shadow: 0 0 0 12px rgba(18, 189, 185, 0.12), 0 16px 46px rgba(0, 0, 0, 0.5); }
}

.tuto-bubble {
  position: fixed;
  z-index: 1002;
  width: min(360px, calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 16px 16px 12px;
  animation: tuto-bubble-in 0.24s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes tuto-bubble-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } }
.tuto-bubble.shake { animation: tuto-shake 0.35s ease; }
@keyframes tuto-shake {
  25% { transform: translateX(-5px); } 50% { transform: translateX(5px); }
  75% { transform: translateX(-3px); }
}

.tuto-progress {
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--brand-strong);
}
.tuto-title { margin: 4px 0 6px; font-size: 1.05rem; }
.tuto-body { margin: 0; font-size: 0.9rem; color: var(--text-soft); line-height: 1.5; }
.tuto-closing {
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 0.95rem; font-weight: 700; font-style: italic; color: var(--text);
}
.tuto-actions {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 12px;
}
.tuto-actions-right { display: flex; align-items: center; gap: 6px; }
.tuto-next:disabled { opacity: 0.6; }
.tuto-bubble [hidden] { display: none !important; }

/* ==================================================================
   Avatars en couches (§12) : base (créature + fond) + chapeau + vêtement.
   ================================================================== */
.avatar-stack { position: relative; overflow: hidden; }
.avatar-stack .av-core {
  font-size: 1.7em; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.avatar-stack .av-initials { font-weight: 900; }
.avatar-stack .av-layer {
  position: absolute; left: 0; right: 0;
  text-align: center; line-height: 1; pointer-events: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.avatar-stack .av-head { top: -0.14em; font-size: 1.18em; }
.avatar-stack .av-cloth { bottom: -0.18em; font-size: 1.05em; }
/* Accessoire (guirlande au cou, nez de renne…) : entre le vêtement et le
   couvre-chef. Cadre complet, car un accessoire ne se pose ni en haut ni en
   bas — c'est le visuel qui décide où il tombe. */
.avatar-stack .av-acc {
  top: 0; bottom: 0; font-size: 1em;
  display: flex; align-items: center; justify-content: center;
}
.avatar-stack img.av-core,
.avatar-stack img.av-img.av-core { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Un calque en image est toujours un cadre plein : le dessin se place
   lui-même dans son viewBox (bonnet en haut, pull en bas, nez au centre).
   Évite d'avoir une règle de position par emplacement. */
.avatar-stack img.av-layer {
  inset: 0; width: 100%; height: 100%; object-fit: contain;
}

/* Avatar plus grand sur les pages profil */
#p-avatar, #pub-avatar { width: 64px; height: 64px; font-size: 1.2rem; }

/* Petit avatar pour les listes (classement, mur des fauchés) */
.avatar-xs {
  width: 24px; height: 24px; font-size: 0.62rem;
  border-width: 1px; vertical-align: middle;
}
.player-cell { display: inline-flex; align-items: center; gap: 8px; }
.shame-chip .avatar-xs { margin-right: 6px; }
.shame-list .player-cell { vertical-align: middle; }

/* Inventaire (profil) : pastilles d'aperçu */
.skin-chip-name { font-weight: 700; font-size: 0.86rem; }
.skin-emoji { font-size: 1.15rem; line-height: 1; }
.skin-dot {
  width: 18px; height: 18px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
  flex-shrink: 0;
}
.skin-emoji.pv-img {
  display: inline-flex; width: 22px; height: 22px;
  border-radius: 6px; background: var(--surface-3);
}
.skin-emoji img { display: block; width: 100%; height: 100%; object-fit: contain; }
.skin-slot h3 .muted { font-weight: 400; font-size: 0.78rem; }

/* Boutique : aperçu de skin + sous-titres par catégorie */
.shop-subhead {
  margin: 20px 0 0; font-size: 0.9rem;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim);
}
.shop-skin-preview {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: 9px; font-size: 1.2rem; line-height: 1;
  background: var(--surface-3);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}
.shop-skin-preview img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Vignette d'un skin livré en image. Le visuel est un calque plein cadre
   (le dessin n'occupe qu'une bande : bonnet en haut, guirlande au cou,
   vêtement en bas). Réduit à 34 px, le sujet devient un point — donc on
   agrandit et on cadre sur la bonne bande, emplacement par emplacement. */
.pv-img { overflow: hidden; }
.pv-img img { transform: scale(2.2); }
.pv-avatar_headwear img { transform-origin: 50% 19%; }
.pv-avatar_clothing img { transform-origin: 50% 79%; }
/* Les accessoires vont du nez (y≈51) à la guirlande (y≈74) : un cadrage
   intermédiaire, un peu moins serré, garde les deux dans la vignette. */
.pv-avatar_accessory img { transform: scale(1.8); transform-origin: 50% 64%; }
.pv-avatar_base img { transform: none; }
.shop-item-head { align-items: center; }

/* Fond de profil animé "Neige qui tombe" (asset_path = "anim:neige").
   Deux nappes de flocons en dégradés radiaux, décalées en boucle : aucune
   image, aucun script, et une seule propriété animée. */
.pbg-neige {
  background-color: #12283f;
  background-image:
    radial-gradient(2.4px 2.4px at 18px 12px, rgba(255, 255, 255, 0.95), transparent 62%),
    radial-gradient(1.8px 1.8px at 62px 38px, rgba(255, 255, 255, 0.8), transparent 62%),
    radial-gradient(2.8px 2.8px at 104px 20px, rgba(255, 255, 255, 0.9), transparent 62%),
    radial-gradient(1.6px 1.6px at 140px 58px, rgba(255, 255, 255, 0.75), transparent 62%),
    radial-gradient(2.2px 2.2px at 40px 74px, rgba(255, 255, 255, 0.85), transparent 62%),
    radial-gradient(2px 2px at 86px 66px, rgba(255, 255, 255, 0.8), transparent 62%),
    radial-gradient(1.5px 1.5px at 122px 84px, rgba(255, 255, 255, 0.7), transparent 62%),
    radial-gradient(2.6px 2.6px at 8px 48px, rgba(255, 255, 255, 0.9), transparent 62%),
    linear-gradient(160deg, #1d4e86, #0b1f3a 70%);
  background-size:
    150px 88px, 130px 76px, 170px 96px, 120px 70px,
    160px 92px, 140px 80px, 110px 64px, 180px 104px, cover;
  color: #f4f7fa;
  animation: pbg-neige-tombe 9s linear infinite;
}
/* Chaque nappe a sa propre hauteur de motif : à durée égale, elles tombent
   donc à des vitesses différentes — c'est ce qui donne la profondeur. */
@keyframes pbg-neige-tombe {
  to {
    background-position:
      6px 88px, -10px 76px, 14px 96px, -6px 70px,
      10px 92px, -8px 80px, 12px 64px, -4px 104px, 0 0;
  }
}
@media (prefers-reduced-motion: reduce) { .pbg-neige { animation: none; } }

.tuto-fx { position: fixed; inset: 0; z-index: 1003; pointer-events: none; overflow: hidden; }
.tuto-win {
  position: absolute; left: 50%; top: 38%;
  transform: translate(-50%, -50%);
  font-size: clamp(2rem, 9vw, 3.4rem); font-weight: 900; font-style: italic;
  color: var(--good-ink);
  text-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
  animation: tuto-win-pop 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes tuto-win-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  60% { transform: translate(-50%, -50%) scale(1.12); }
  100% { transform: translate(-50%, -50%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .tuto-glow { animation: none; }
  .tuto-bubble, .tuto-dim, .tuto-win { animation: none; }
}

/* ==================================================================
   Micro-interactions (§14) : léger agrandissement au survol / à l'appui.
   Subtil et cohérent partout ; désactivé si l'utilisateur limite les animations.
   ================================================================== */
.btn, .shop-item, .mover, .skin-chip, .credit-row,
.bet-card, .notif-item, .lb-table tbody tr, .shame-chip {
  transition: transform 0.15s ease, box-shadow 0.16s ease, border-color 0.16s ease, background 0.15s ease;
}
.btn:hover:not(:disabled) { transform: scale(1.02); }
.btn:active:not(:disabled) { transform: scale(0.97); }
.shop-item:hover { transform: scale(1.012); }
.mover:hover { transform: scale(1.015); }
.bet-card:hover { transform: scale(1.006); }
.shame-wall a:hover .shame-chip { transform: scale(1.04); }
.info-i { transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease; }
.info-i:hover { transform: scale(1.12); }

@media (prefers-reduced-motion: reduce) {
  .btn, .shop-item, .mover, .skin-chip, .credit-row, .bet-card, .notif-item,
  .lb-table tbody tr, .shame-chip, .info-i, .bet-stream-pill {
    transition: box-shadow 0.16s ease, border-color 0.16s ease;
  }
  .btn:hover, .btn:active, .shop-item:hover, .mover:hover, .bet-card:hover,
  .shame-wall a:hover .shame-chip, .info-i:hover, .bet-stream-pill:hover { transform: none; }
}

/* ==================================================================
   Passe d'animations (§14b) — rendre le site vivant, sans GIF.
   Tout est court (150–320 ms) et coupé sous prefers-reduced-motion.
   ================================================================== */

/* --- Cartes de pari : lift au survol + icône qui réagit --- */
.bet-card { transition: transform 0.18s ease, box-shadow 0.2s ease, border-color 0.2s ease; }
.bet-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--brand);
}
.bet-icon { transition: transform 0.2s ease, background 0.2s ease; }
.bet-card:hover .bet-icon { transform: rotate(-8deg) scale(1.08); background: var(--brand-wash); }

/* --- Boutons de cote : reflet qui balaie au survol (hors pari démo) --- */
.outcome.pill:not(.outcome-demo)::after {
  content: "";
  position: absolute; top: 0; left: -60%;
  width: 45%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.28), transparent);
  transform: skewX(-18deg);
  transition: left 0.5s ease;
  pointer-events: none;
}
.outcome.pill:not(.outcome-demo):hover:not(:disabled)::after { left: 130%; }

/* --- Jeton de solde : "pop" quand le montant change --- */
.balance-chip { transition: transform 0.15s ease, border-color 0.15s ease; }
.balance-chip.bump { animation: chip-bump 0.5s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes chip-bump {
  0% { transform: scale(1); }
  35% { transform: scale(1.16); }
  60% { transform: scale(0.97); }
  100% { transform: scale(1); }
}
.balance-chip.bump .amount { animation: chip-flash 0.6s ease; }
@keyframes chip-flash { 0%, 100% { color: var(--action-ink); } 40% { color: var(--good); } }

/* --- Nav : soulignement animé au survol (desktop) --- */
@media (min-width: 768px) {
  .site-nav a { position: relative; }
  .site-nav a::after {
    content: "";
    position: absolute; left: 12px; right: 12px; bottom: 3px;
    height: 2px; border-radius: 2px;
    background: var(--brand);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
  }
  .site-nav a:hover::after, .site-nav a.active::after { transform: scaleX(1); }
}

/* --- Titres de sections : petit fondu-glissé --- */
html.js .cat-title { animation: cat-in 0.35s ease both; }
@keyframes cat-in { from { opacity: 0; transform: translateX(-6px); } }

/* --- Cloche de notifs : secousse à la réception --- */
.notif-bell.ring { animation: bell-ring 0.7s ease; transform-origin: top center; }
@keyframes bell-ring {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(16deg); }
  30% { transform: rotate(-13deg); }
  45% { transform: rotate(9deg); }
  60% { transform: rotate(-6deg); }
  75% { transform: rotate(3deg); }
}
.notif-count { animation: count-pop 0.32s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes count-pop { from { transform: scale(0); } 60% { transform: scale(1.3); } }

/* --- Coupon : bandeau qui remonte, cartes de sélection qui apparaissent --- */
#ticket.has-selections .tk-bar { animation: tk-bar-in 0.32s cubic-bezier(0.2, 0.85, 0.25, 1); }
@keyframes tk-bar-in { from { opacity: 0; transform: translateY(28px); } }
.tk-pick-card { animation: tk-pick-in 0.28s cubic-bezier(0.2, 0.85, 0.25, 1) both; }
@keyframes tk-pick-in { from { opacity: 0; transform: translateY(10px) scale(0.97); } }
.tk-bar-count, .tk-pick-odds { transition: transform 0.15s ease; }
.tk-bar:hover .tk-bar-count { transform: scale(1.08); }
.tk-payout b { transition: color 0.2s ease; }

/* --- Pastilles d'accès (Roulette / Live) : respiration discrète --- */
.roul-pill { animation: soft-glow 2.6s ease-in-out infinite; }
@keyframes soft-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 150, 14, 0); }
  50% { box-shadow: 0 0 0 5px rgba(245, 150, 14, 0.16); }
}
.bet-stream-pill { animation: soft-glow-red 2s ease-in-out infinite; }
@keyframes soft-glow-red {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 72, 77, 0); }
  50% { box-shadow: 0 0 0 4px rgba(229, 72, 77, 0.28); }
}

/* --- Ligne d'affiche : le point "EN DIRECT" clignote --- */
.ml-when-label.is-live { animation: live-blink 1.4s ease-in-out infinite; }
@keyframes live-blink { 50% { opacity: 0.45; } }

/* --- Boutique : articles qui se soulèvent --- */
.shop-item { transition: transform 0.18s ease, box-shadow 0.2s ease, border-color 0.2s ease; }
.shop-item:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--border-strong); }
.shop-skin-preview { transition: transform 0.2s ease; }
.shop-item:hover .shop-skin-preview { transform: scale(1.12) rotate(-4deg); }

/* --- Lignes de classement : léger décalage au survol --- */
.lb-table tbody tr { transition: background 0.16s ease, transform 0.16s ease; }
.lb-table tbody tr:hover { background: var(--surface-2); transform: translateX(3px); }

/* --- Onglets de marché : bascule douce --- */
.market-tabs button, .tabs button { transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.15s ease; }
.market-tabs button:active, .tabs button:active { transform: scale(0.96); }

/* --- Avatar en couches : le chapeau salue au survol du profil --- */
#p-card:hover .av-head, #pub-card:hover .av-head { animation: hat-tip 0.7s ease; }
/* Pas de translateX ici : le calque est déjà centré (span pleine largeur ou
   image plein cadre). En ajouter un décalait le chapeau d'une demi-largeur. */
@keyframes hat-tip { 30% { transform: translateY(-3px) rotate(-12deg); } }

@media (prefers-reduced-motion: reduce) {
  .bet-card, .bet-card:hover, .bet-icon, .shop-item, .shop-item:hover,
  .lb-table tbody tr:hover, .balance-chip.bump, .balance-chip.bump .amount {
    animation: none !important;
    transform: none !important;
  }
  .outcome.pill:not(.outcome-demo)::after { display: none; }
  html.js .cat-title { animation: none; }
  .notif-bell.ring, .notif-count, .tk-pick-card,
  #ticket.has-selections .tk-bar { animation: none; }
  .roul-pill, .bet-stream-pill, .ml-when-label.is-live { animation: none; }
  .site-nav a::after { transition: none; }
}

/* ==================================================================
   Passe de professionnalisation
   Squelettes de chargement · focus clavier · boutique par catégories ·
   page Règles & confidentialité · case de consentement · page 404.
   ================================================================== */

/* ---------- Squelettes de chargement ---------- */
.sk-stack { display: flex; flex-direction: column; gap: 12px; }
.sk-grid {
  display: grid; gap: 12px; margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.sk {
  border-radius: var(--radius);
  background: linear-gradient(100deg, var(--surface-2) 30%, var(--surface-3) 50%, var(--surface-2) 70%);
  background-size: 220% 100%;
  animation: sk-shimmer 1.25s linear infinite;
}
.sk-card { height: 132px; }
.sk-tile { height: 168px; }
.sk-row { height: 44px; border-radius: var(--radius-sm); }
@keyframes sk-shimmer { from { background-position: 120% 0; } to { background-position: -120% 0; } }
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; background: var(--surface-2); }
}

/* ---------- Focus clavier visible et homogène ---------- */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.btn:focus-visible, .outcome:focus-visible, .shop-tab:focus-visible, .shop-chip:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
/* jamais de contour au clic souris, seulement au clavier */
:where(a, button):focus:not(:focus-visible) { outline: none; }

/* Lien d'évitement (accessibilité clavier) */
.skip-link {
  position: absolute; left: 8px; top: -100px;
  z-index: 200;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--brand); border-radius: var(--radius-sm);
  padding: 8px 12px; font-weight: 700;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 8px; text-decoration: none; }

/* ---------- Boutique : catégories principales + sous-filtres ---------- */
.shop-tabs {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin: 4px 0 8px;
}
.shop-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-soft);
  font: inherit; font-weight: 700; font-size: 0.95rem;
  cursor: pointer;
  transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease, transform 0.14s ease;
}
.shop-tab:hover { color: var(--text); border-color: var(--brand); }
.shop-tab:active { transform: scale(0.97); }
.shop-tab.active {
  background: var(--brand); border-color: var(--brand); color: var(--primary-ink);
  box-shadow: 0 4px 14px rgba(18, 189, 185, 0.32);
}
.shop-tab-n {
  font-size: 0.74rem; font-weight: 800;
  background: var(--surface-3); color: var(--text-dim);
  border-radius: var(--radius-pill); padding: 1px 6px;
}
.shop-tab.active .shop-tab-n { background: rgba(255, 255, 255, 0.24); color: #fff; }

.shop-hint { margin: 0 0 12px; font-size: 0.88rem; }

.shop-filters { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; }
.shop-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-dim);
  font: inherit; font-weight: 600; font-size: 0.84rem;
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease, border-color 0.14s ease;
}
.shop-chip:hover { color: var(--text); border-color: var(--border-strong); }
.shop-chip.active {
  background: var(--brand-wash); border-color: var(--brand); color: var(--brand-strong);
}
.shop-chip-n { font-size: 0.72rem; opacity: 0.75; font-weight: 800; }

/* ---------- Case de consentement (inscription) ---------- */
.consent {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 4px 0 12px;
  padding: 12px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 0.84rem; line-height: 1.45; color: var(--text-soft);
  cursor: pointer;
}
.consent input[type="checkbox"] {
  flex-shrink: 0; margin-top: 2px;
  width: 18px; height: 18px; accent-color: var(--brand); cursor: pointer;
}
.consent a { font-weight: 700; }
.consent:has(input:checked) { border-color: var(--brand); background: var(--brand-wash); }

/* ---------- Page Règles & confidentialité ---------- */
.legal { max-width: 820px; }
.legal h2 { font-size: 1.1rem; margin-top: 0; }
.legal p { line-height: 1.6; }
.legal ul, .legal ol { line-height: 1.6; padding-left: 20px; margin: 8px 0 0; }
.legal li + li { margin-top: 6px; }
.legal-list li { padding-left: 2px; }
.legal-alert {
  border-color: var(--action);
  background: linear-gradient(180deg, var(--action-wash), var(--surface));
}
.legal-alert h2 { color: var(--action-ink); }
.legal-contact { font-weight: 700; font-size: 1rem; margin: 0 0 6px; }
.legal-foot { margin: 16px 0 0; text-align: center; font-size: 0.85rem; }
.legal .table-wrap { margin-top: 8px; }
.legal table.data td { vertical-align: top; line-height: 1.5; }

/* ---------- Page 404 ---------- */
.err-page { max-width: 560px; margin: 8vh auto; text-align: center; }
.err-code {
  font-size: clamp(3.5rem, 16vw, 6rem); font-weight: 900; font-style: italic;
  line-height: 1; color: var(--brand); letter-spacing: -0.03em;
}
.err-page h1 { margin: 6px 0 8px; font-size: 1.4rem; }
.err-page p { color: var(--text-soft); }
.err-actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }

/* Deuxième rangée de filtres : rareté (onglet Personnalisation) */
.shop-filters-rarity { align-items: center; margin-top: 8px; }
.shop-filters-label {
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-dim); margin-right: 2px;
}
.rarity-chip.r-common.active { background: var(--rar-common-wash); border-color: var(--rar-common); color: var(--rar-common-ink); }
.rarity-chip.r-rare.active { background: var(--rar-rare-wash); border-color: var(--rar-rare); color: var(--rar-rare-ink); }
.rarity-chip.r-legendary.active { background: var(--rar-legendary-wash); border-color: var(--rar-legendary); color: var(--rar-legendary-ink); }

/* ==================================================================
   Panel admin : tableau de bord, rôles, journal.
   ================================================================== */
.stat-grid {
  display: grid; gap: 12px; margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
.stat-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 12px 12px;
  transition: transform 0.16s ease, border-color 0.16s ease;
}
.stat-card:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.stat-value { font-size: 1.55rem; font-weight: 900; line-height: 1.1; letter-spacing: -0.02em; }
.stat-label {
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-dim); margin-top: 3px;
}
.stat-hint { font-size: 0.76rem; color: var(--text-dim); margin-top: 4px; }
.stat-card.tone-hot { border-left-color: var(--brand); }
.stat-card.tone-warn { border-left-color: var(--action); }
.stat-card.tone-warn .stat-value { color: var(--action-ink); }
.stat-card.tone-live { border-left-color: var(--bad); }
.stat-card.tone-live .stat-value { color: var(--bad); }

.badge.role-mod { color: var(--brand-strong); border-color: var(--brand); background: var(--brand-wash); }
.it-role {
  background: var(--surface-2); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); color: var(--text); padding: 6px 8px; font: inherit;
  font-size: 0.84rem;
}
.role-table td:not(:first-child) { text-align: center; width: 110px; }
.user-ledger { margin-top: 8px; }
.user-ledger table.data { font-size: 0.82rem; }

/* ==================================================================
   Pause globale : bandeau joueur + carte d'urgence côté admin.
   ================================================================== */
.pause-banner {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 16px;
  background: linear-gradient(90deg, var(--bad-wash), var(--action-wash));
  border-bottom: 2px solid var(--bad);
  color: var(--bad-ink);
  font-size: 0.86rem; font-weight: 600; text-align: center;
}
.pause-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--bad);
  flex-shrink: 0; animation: live-pulse 1.5s ease-in-out infinite;
}
/* pendant la pause, les actions d'argent se grisent (le serveur refuse aussi) */
html.site-paused .outcome:not(.outcome-demo),
html.site-paused [data-buy],
html.site-paused [data-place],
html.site-paused .roul-choice {
  pointer-events: none; opacity: 0.45; filter: grayscale(0.6);
}

.pause-card { border-left: 4px solid var(--good); }
.pause-card.is-paused {
  border-left-color: var(--bad);
  background: linear-gradient(180deg, var(--bad-wash), var(--surface));
}
.pause-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.pause-head h2 { margin: 0 0 2px; }
.pause-head .muted { margin: 0; }
.pause-btn {
  background: var(--bad); border-color: var(--bad); color: #fff;
  font-weight: 800; padding: 12px 20px; font-size: 1rem;
  box-shadow: 0 6px 18px rgba(229, 72, 77, 0.3);
  flex-shrink: 0;
}
.pause-btn:hover { background: var(--bad-ink); border-color: var(--bad-ink); }
.pause-card.is-paused .pause-btn {
  background: var(--good); border-color: var(--good);
  box-shadow: 0 6px 18px rgba(26, 169, 113, 0.32);
}
.pause-card.is-paused .pause-btn:hover { background: var(--good-ink); border-color: var(--good-ink); }
.btn-lg { padding: 12px 20px; font-size: 1rem; }
@media (prefers-reduced-motion: reduce) { .pause-dot { animation: none; } }

/* ==================================================================
   Série de victoires + mur spectateur (visiteur non connecté).
   ================================================================== */
.streak-chip {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 6px; border-radius: 999px;
  background: var(--action-wash); border: 1px solid var(--accent);
  color: var(--action-ink);
  font-size: 0.72rem; font-weight: 800; white-space: nowrap;
  animation: streak-glow 2.4s ease-in-out infinite;
}
@keyframes streak-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(240, 165, 0, 0); }
  50% { box-shadow: 0 0 0 3px rgba(240, 165, 0, 0.16); }
}

.wall-backdrop {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: var(--backdrop);
  backdrop-filter: blur(3px);
  animation: tuto-fade 0.18s ease;
}
.wall-card {
  width: min(420px, 100%);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 24px 24px 20px;
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.32);
  text-align: center;
  animation: wall-in 0.24s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes wall-in { from { opacity: 0; transform: translateY(14px) scale(0.96); } }
.wall-emoji { font-size: 2.4rem; line-height: 1; display: inline-block; animation: wall-coin 2.6s ease-in-out infinite; }
@keyframes wall-coin {
  0%, 70%, 100% { transform: rotateY(0deg); }
  85% { transform: rotateY(180deg); }
}
.wall-card h2 { margin: 8px 0 8px; font-size: 1.18rem; }
.wall-card p { margin: 0 0 8px; font-size: 0.9rem; }
.wall-fine { font-size: 0.78rem !important; }
.wall-actions { display: grid; gap: 8px; margin: 16px 0 8px; }
.wall-close {
  background: none; border: none; cursor: pointer;
  color: var(--text-dim); font-size: 0.8rem; text-decoration: underline;
  padding: 4px;
}
.wall-close:hover { color: var(--text); }
@media (prefers-reduced-motion: reduce) {
  .streak-chip, .wall-emoji, .wall-card, .wall-backdrop { animation: none; }
}

/* ==================================================================
   Bilan de fin de tournoi (/bilan) : carte récap partageable.
   ================================================================== */
.recap-card {
  background: linear-gradient(160deg, var(--surface-2), var(--surface));
  border-top: 3px solid var(--accent);
}
.recap-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.recap-who { font-size: 1.3rem; font-weight: 800; }
.recap-net { text-align: right; font-size: 1.5rem; font-weight: 800; line-height: 1.1; }
.recap-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.recap-stat {
  background: var(--surface-3); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 12px 8px; text-align: center;
  transition: transform 0.16s ease, border-color 0.16s ease;
}
.recap-stat:hover { transform: translateY(-2px); border-color: var(--primary); }
.recap-val { font-size: 1.25rem; font-weight: 800; }
.recap-lab { font-size: 0.74rem; color: var(--text-dim); text-transform: lowercase; }
.recap-hint { font-size: 0.72rem; color: var(--text-dim); }

.recap-hl { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.recap-hl li {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 0.9rem; padding: 8px 8px;
  background: var(--surface-3); border-radius: var(--radius-sm);
  border-left: 3px solid var(--line);
}
.hl-tag {
  font-size: 0.7rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--text-dim); flex-shrink: 0;
}
.hl-good { color: var(--good); }
.hl-bad { color: var(--bad); }
.hl-bold { color: var(--action-ink); }

.recap-verdict {
  margin: 16px 0 0; padding: 12px 12px;
  background: var(--action-wash); border-radius: var(--radius-sm);
  font-style: italic; font-size: 0.92rem;
}
.recap-foot { margin-top: 12px; font-size: 0.8rem; }
.recap-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.recap-actions[hidden] { display: none; }
.recap-fine { margin-top: 16px; font-size: 0.8rem; }

/* ==================================================================
   Jeu d'icônes unique (voir /js/icons.js). Un seul tracé, une seule
   graisse, la couleur suit le texte.
   ================================================================== */
.ico {
  width: 1em; height: 1em;
  flex-shrink: 0;
  vertical-align: -0.135em;
  stroke: currentColor;
}
.ico-sm { width: 0.85em; height: 0.85em; }
.ico-lg { width: 1.25em; height: 1.25em; }
/* Icône seule dans un bouton : elle porte la taille du bouton, pas du texte. */
.icon-btn .ico, .notif-bell .ico { width: 18px; height: 18px; vertical-align: middle; }
.btn .ico { margin-right: 6px; margin-left: -2px; }
.btn .ico:only-child { margin: 0; }

/* ==================================================================
   Confettis de victoire (voir /js/celebrate.js). Purement décoratif :
   au-dessus de tout, mais transparent aux clics.
   ================================================================== */
.confetti {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 200;
  overflow: hidden;
}
.confetti i {
  position: absolute;
  top: -20px;
  display: block;
  opacity: 0;
  animation-name: confetti-fall;
  animation-timing-function: cubic-bezier(0.25, 0.6, 0.5, 1);
  animation-fill-mode: forwards;
}
@keyframes confetti-fall {
  0% { opacity: 0; transform: translate3d(0, -10px, 0) rotate(0deg); }
  8% { opacity: 1; }
  85% { opacity: 1; }
  100% {
    opacity: 0;
    transform: translate3d(var(--drift), 100vh, 0) rotate(var(--spin));
  }
}
@media (prefers-reduced-motion: reduce) { .confetti { display: none; } }

/* ==================================================================
   Rareté : un seul langage visuel, partout où un objet apparaît
   (boutique, profil, aperçus). Gris = commun, bleu = rare, or = légendaire.
   L'or scintille lentement — c'est le seul niveau qui bouge.
   ================================================================== */
[data-rar] { --rar: var(--rar-common); --rar-wash: var(--rar-common-wash); --rar-ink: var(--rar-common-ink); }
[data-rar="rare"] { --rar: var(--rar-rare); --rar-wash: var(--rar-rare-wash); --rar-ink: var(--rar-rare-ink); }
[data-rar="legendary"] { --rar: var(--rar-legendary); --rar-wash: var(--rar-legendary-wash); --rar-ink: var(--rar-legendary-ink); }

/* Tuile de boutique / puce de skin : liseré à gauche + anneau discret. */
.shop-item[data-rar], .skin-chip[data-rar] {
  border-color: color-mix(in srgb, var(--rar) 45%, var(--border));
  box-shadow: inset 3px 0 0 var(--rar), var(--shadow-sm);
}
.shop-item[data-rar="legendary"], .skin-chip[data-rar="legendary"] {
  position: relative; overflow: hidden;
}
/* Scintillement or : une bande de lumière qui traverse, très espacée. */
.shop-item[data-rar="legendary"]::after,
.skin-chip[data-rar="legendary"]::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, var(--shine) 50%, transparent 62%);
  transform: translateX(-120%);
  animation: rar-shimmer 5.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes rar-shimmer {
  0%, 72% { transform: translateX(-120%); }
  100% { transform: translateX(120%); }
}

/* Aperçu carré d'un objet (pastille / swatch) : l'anneau porte la rareté. */
.skin-swatch[data-rar], .shop-prev[data-rar] {
  box-shadow: 0 0 0 2px var(--rar);
}

/* Pastille de rareté réutilisable hors badge (listes admin, aperçus). */
.rar-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--rar); flex-shrink: 0;
}
@media (prefers-reduced-motion: reduce) {
  .shop-item[data-rar="legendary"]::after, .skin-chip[data-rar="legendary"]::after { animation: none; opacity: 0; }
}

/* Voyant d'état (panneau admin) : même pastille que le bandeau de pause. */
.state-dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  vertical-align: 0.05em; margin-right: 2px;
}
.state-dot.is-good { background: var(--good); }
.state-dot.is-bad { background: var(--bad); animation: live-pulse 1.5s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .state-dot.is-bad { animation: none; } }

/* Icône en tête de titre : alignée sur la ligne de base du texte. */
h1 > .ico, h2 > .ico, h3 > .ico { margin-right: 6px; color: var(--text-dim); }

/* ==================================================================
   Élévation — les deux thèmes.
   Un seul jeu de règles : chaque élément est placé sur un NIVEAU, et ce
   sont les variables du thème actif qui décident de la teinte.
     niveau 0 --bg  |  1 --surface  |  2 --surface-2  |  3 --surface-3
   En sombre l'échelle monte vers le clair ; en clair elle monte vers le
   blanc jusqu'au niveau 1, puis se creuse (on ne peut pas dépasser le
   blanc). Dans les deux cas la hiérarchie se lit.
   ================================================================== */

/* --- Niveau 2 : ce qui réagit au survol change d'un cran ------------- */
.bet-card:hover,
.shop-item:hover,
.recap-stat:hover,
.stat-card:hover,
.lb-table tbody tr:hover {
  background: var(--surface-2);
}

/* --- Niveau 2 : ce qui flotte au-dessus d'une page (menus, modales) et
   le pied du coupon, qui doit se détacher du corps qu'il conclut.
   En clair les flottants restent blancs — leur ombre portée suffit —
   sauf le pied du coupon, qui est collé à sa carte. -------------------- */
:root[data-theme="dark"] #notif-panel,
:root[data-theme="dark"] .tuto-bubble,
:root[data-theme="dark"] .wall-card,
.ticket-panel .tk-foot {
  background: var(--surface-2);
}

/* --- Niveau 3 : le survol À L'INTÉRIEUR d'un flottant --------------- */
#notif-panel .notif-item:hover,
.site-nav a:hover {
  background: var(--surface-3);
}

/* --- Le coupon et les panneaux latéraux sont au niveau 1 ------------
   Sans ça, le « Coupon vide » se noyait dans le fond de page. */
.ticket-panel,
.col-side > .card {
  background: var(--surface);
  border-color: var(--border-strong);
}

/* L'état vide se situe par rapport à CE QUI LE PORTE, pas par rapport au
   fond de page : posé sur la page il est au niveau 2, posé dans une carte
   il descend au niveau 3 — sinon il repasse sous la teinte de sa carte et
   le problème se reproduit à l'intérieur. */
.empty-state {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.ticket-panel .empty-state,
.card .empty-state {
  background: var(--surface-3);
}

/* Mot de passe temporaire (panel admin) : lisible une seule fois, donc
   affiché gros et sélectionnable d'un coup. */
.pw-box {
  margin-top: 8px; padding: 12px;
  background: var(--action-wash);
  border: 1px solid var(--action);
  border-radius: var(--radius-sm);
}
.pw-label {
  font-size: 0.72rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--action-ink); margin-bottom: 6px;
}
.pw-code {
  display: block;
  font-family: var(--font-mono);
  font-size: 1.15rem; font-weight: 700; letter-spacing: 0.06em;
  padding: 8px 12px;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  user-select: all;              /* un clic sélectionne tout */
  overflow-wrap: anywhere;
}
.pw-box .btn { margin-top: 8px; }

/* Bouton en attente de réponse serveur (voir busy() dans app.js). */
.btn.is-loading { cursor: progress; opacity: 0.85; }
.btn-spin {
  display: inline-block; width: 0.85em; height: 0.85em;
  margin-right: 6px; vertical-align: -0.1em;
  border: 2px solid currentColor; border-top-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn-spin { animation-duration: 1.6s; }
}

/* Liste terme / définition des pages légales. */
.legal-dl { margin: 12px 0 0; }
.legal-dl dt {
  font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-dim); margin-top: 12px;
}
.legal-dl dt:first-child { margin-top: 0; }
.legal-dl dd { margin: 2px 0 0; }

/* ==================================================================
   Panneau roulette (réglages admin) : aperçu de la roue à gauche,
   champs à droite. L'aperçu se redessine à chaque frappe.
   ================================================================== */
.roul-admin {
  display: grid; gap: var(--sp-6);
  grid-template-columns: 1fr;
  margin-top: var(--sp-5);
}
@media (min-width: 900px) {
  .roul-admin { grid-template-columns: 220px minmax(0, 1fr); align-items: start; }
  .roul-admin-preview { position: sticky; top: calc(var(--header-h) + 16px); }
}
.roul-admin-preview {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  text-align: center;
}
.roul-prev-wheel {
  width: 100%; max-width: 170px; margin: 0 auto var(--sp-5);
  aspect-ratio: 1; border-radius: 50%;
  border: 5px solid var(--surface);
  box-shadow: 0 0 0 2px var(--border-strong), var(--shadow);
  background: var(--surface-3);
}
.roul-prev-legend { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); }
.roul-prev-row {
  display: flex; align-items: center; gap: var(--sp-4);
  text-align: left;
}
.roul-prev-row strong { margin-left: auto; font-variant-numeric: tabular-nums; }
.roul-prev-row.is-off { opacity: 0.45; text-decoration: line-through; }

.roul-admin-fields h4 {
  margin: var(--sp-7) 0 var(--sp-4);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--border);
}
.roul-admin-fields h4:first-child { margin-top: 0; }
.grid.cols-3 { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; }
@media (min-width: 620px) { .grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
input[type="color"] {
  width: 100%; height: 40px; padding: 2px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); cursor: pointer;
}

/* Actions sous le résultat de la roulette (Relancer + retour). */
.roul-actions {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  justify-content: center; margin-top: var(--sp-5);
}
/* Bouton grisé pendant le délai : il reste lisible, il n'a l'air ni cassé
   ni cliquable. Le décompte vit dedans. */
.roul-actions .btn[disabled] {
  opacity: 0.55; cursor: not-allowed; filter: grayscale(0.7);
}
.roul-actions .btn[disabled] strong { font-variant-numeric: tabular-nums; }

/* ==================================================================
   Marchés joueurs : une colonne par équipe (5 contre 5) plutôt qu'une
   liste de 10 noms où l'on ne sait plus qui joue pour qui.
   ================================================================== */
.outcomes.by-team {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
}
@media (min-width: 560px) {
  .outcomes.by-team { grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
}
.team-col { min-width: 0; }
.team-col-head {
  font-size: var(--fs-xs); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-dim);
  padding: 0 0 var(--sp-3);
  margin-bottom: var(--sp-3);
  border-bottom: 2px solid var(--border-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* La colonne de droite se distingue par la couleur de son filet : les deux
   équipes se repèrent d'un coup d'œil, même en scrollant vite. */
.team-col:last-child .team-col-head { border-bottom-color: var(--primary); }
.team-col:first-child .team-col-head { border-bottom-color: var(--accent); }
.team-col-list { display: grid; gap: var(--sp-3); }
/* Dans une colonne, chaque issue prend toute la largeur : on lit une liste
   de noms, pas une grille. */
.outcomes.by-team .outcome.pill { width: 100%; }

/* ==================================================================
   Clips communautaires : formulaire, cartes, j'aime, classement.
   ================================================================== */
.clip-form { margin-bottom: var(--sp-6); }
.clip-form h2 { margin-bottom: var(--sp-2); }
.clip-form-hint { font-size: var(--fs-sm); margin: 0 0 var(--sp-5); }
.clip-form .btn { margin-top: var(--sp-5); }
.clip-cta { margin-bottom: var(--sp-6); border-left: 3px solid var(--accent); }

.clip-card { margin-bottom: var(--sp-5); position: relative; }
/* Un clip retenu par l'orga se voit de loin : liseré doré, comme la rareté
   légendaire de la boutique — même langage visuel pour « ça compte ». */
.clip-card.is-featured {
  border-color: var(--rar-legendary);
  box-shadow: inset 3px 0 0 var(--rar-legendary), var(--shadow-sm);
}
.clip-flag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--rar-legendary-ink);
  background: var(--rar-legendary-wash);
  border: 1px solid var(--rar-legendary);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
  margin-bottom: var(--sp-4);
}

.clip-head { display: flex; gap: var(--sp-5); align-items: flex-start; }
.clip-platform {
  font-size: 1.5rem; line-height: 1; flex-shrink: 0;
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); border: 1px solid var(--border);
}
.clip-main { min-width: 0; flex: 1; }
.clip-main h3 { margin: 0 0 var(--sp-2); }
.clip-main h3 a { color: inherit; }
.clip-main h3 a:hover { color: var(--brand-strong); }
.clip-meta {
  display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; font-size: var(--fs-xs);
}

.clip-foot {
  display: flex; align-items: center; gap: var(--sp-4);
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}
.clip-like {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--radius-pill);
  background: var(--surface-2); border: 1px solid var(--border-strong);
  color: var(--text-soft); font-size: var(--fs-sm); font-weight: 700;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), border-color var(--t-base) ease,
    color var(--t-base) ease, background var(--t-base) ease;
}
.clip-like:hover:not([disabled]) { transform: translateY(-1px); border-color: var(--bad); color: var(--bad); }
.clip-like[disabled] { opacity: 0.55; cursor: not-allowed; }
.clip-like.liked { color: var(--bad); border-color: var(--bad); background: var(--bad-wash); }
.clip-heart { font-size: 1.05rem; line-height: 1; }
.clip-likes { font-variant-numeric: tabular-nums; }
.clip-like.pop { animation: clip-pop 0.34s var(--ease); }
@keyframes clip-pop { 40% { transform: scale(1.16); } }
.clip-foot .btn { margin-left: auto; }

.clippers { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.clippers li {
  display: flex; align-items: center; gap: var(--sp-4);
  font-size: var(--fs-sm);
}
.clippers li > a { min-width: 0; overflow: hidden; }
.clippers strong { margin-left: auto; font-variant-numeric: tabular-nums; }
.clipper-rank {
  width: 22px; height: 22px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--surface-3);
  font-size: var(--fs-xs); font-weight: 800; color: var(--text-dim);
}
.clippers li:first-child .clipper-rank {
  background: var(--rar-legendary-wash); color: var(--rar-legendary-ink);
  border: 1px solid var(--rar-legendary);
}
@media (prefers-reduced-motion: reduce) {
  .clip-like, .clip-like.pop { transition: none; animation: none; }
}


/* ==================================================================
   THÈME SAISONNIER
   Deuxième axe, indépendant de clair/sombre :
     data-theme  = light | dark            -> préférence du visiteur
     data-season = none | halloween | noel -> décision de l'orga
   Une saison ne remplace pas le thème : elle repeint quelques variables
   par-dessus et ajoute des décors. Le mode sombre reste sombre.

   Le décor vit dans #season-fx, SOUS le header et sous le contenu, sans
   jamais capter un clic. Tout le mouvement est coupé sous
   prefers-reduced-motion ; le décor, lui, reste visible.
   ================================================================== */

#season-fx {
  position: fixed; inset: 0;
  pointer-events: none;
  /* z-index posé plus bas : voir « Décors saisonniers : deux couches ». */
  overflow: hidden;
}
/* Le « O » remplacé garde exactement la place de la lettre : le logo ne
   saute pas quand une saison s'active. */
:root[data-season="halloween"] .brand-o,
:root[data-season="noel"] .brand-o {
  /* Boîte fixée à la taille d'une lettre : l'objet remplace le « O » sans
     jamais mordre sur le « d » qui suit. La lettre reste dans le flux
     (transparente) pour que le logo garde sa largeur et ne saute pas. */
  width: 1.12em; height: 1.12em;
  color: transparent;
  vertical-align: -0.2em;
  overflow: hidden;
}
:root[data-season="halloween"] .brand-o > svg,
:root[data-season="noel"] .brand-o > svg {
  display: block;
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}

/* ==================================================================
   HALLOWEEN
   ================================================================== */
:root[data-season="halloween"] {
  --hw-orange: #ff8a1f;
  --hw-orange-deep: #e0670a;
  --hw-purple: #8b5cf6;
  --hw-purple-deep: #5b21b6;

  /* L'orange prend l'accent, le violet le secondaire. Le teal de marque
     reste sur les cotes : c'est la couleur qui porte l'information, elle
     ne change pas au gré des saisons. */
  --accent: var(--hw-orange);
  --action: var(--hw-orange);
  --action-strong: var(--hw-orange-deep);
  --special: var(--hw-purple);
}
:root[data-season="halloween"]:not([data-theme="dark"]) {
  --bg: #f6f1f7;
  --action-wash: #fff1e0;
  --action-ink: #9a4a00;
  --depth-1: rgba(255, 138, 31, 0.07);
  --depth-2: rgba(139, 92, 246, 0.06);
  --depth-3: rgba(255, 138, 31, 0.04);
}
:root[data-season="halloween"][data-theme="dark"] {
  --bg: #100916;                /* nuit violacée, jamais du noir plat */
  --surface: #1c1227;
  --surface-2: #261933;
  --surface-3: #322142;
  --border: #3e2b52;
  --border-strong: #563d72;
  --header-bg: rgba(28, 18, 39, 0.93);
  --header-line: #6b4a8c;
  --action-wash: #3a2410;
  --action-ink: #ffc98a;
  --depth-1: rgba(255, 138, 31, 0.08);
  --depth-2: rgba(139, 92, 246, 0.10);
  --depth-3: rgba(139, 92, 246, 0.05);
}

/* La citrouille du logo : la chair vacille, la découpe reste nette. */
:root[data-season="halloween"] .brand-o > svg {
  animation: hw-flicker 3.4s ease-in-out infinite;
}
@keyframes hw-flicker {
  0%, 100% { filter: drop-shadow(0 0 3px rgba(255, 138, 31, 0.6)); }
  46% { filter: drop-shadow(0 0 7px rgba(255, 160, 60, 0.95)); }
  52% { filter: drop-shadow(0 0 2px rgba(255, 138, 31, 0.4)); }
  58% { filter: drop-shadow(0 0 6px rgba(255, 160, 60, 0.8)); }
}

/* Lune basse, derrière tout. Visible surtout en thème sombre. */
.hw-moon {
  position: absolute; top: 6%; right: 7%;
  width: 130px; height: 130px; border-radius: 50%;
  background: radial-gradient(circle at 36% 32%, #fff6e0, #ffe4a8 58%, #e8c477);
  box-shadow: 0 0 70px 24px rgba(255, 214, 140, 0.16);
  opacity: 0.1;
}
:root[data-theme="dark"] .hw-moon { opacity: 0.22; }
@media (max-width: 900px) { .hw-moon { display: none; } }

.hw-web {
  position: absolute; top: 0;
  width: 56px; height: 56px;
  color: var(--hw-purple);
  opacity: 0.22;
  display: none;
}
.hw-web.left { left: 0; }
.hw-web.right { right: 0; transform: scaleX(-1); }
/* La barre est centrée jusqu'à 1180px de large : en dessous de cette largeur
   de fenêtre, il ne reste aucune marge hors du bandeau, et la toile
   toucherait forcément le logo ou les liens. On la masque plutôt que de
   risquer un chevauchement, même discret (le z-index négatif plus bas la
   protège déjà, mais autant qu'elle reste dans un vrai coin). */
@media (min-width: 1400px) { .hw-web { display: block; } }

/* L'araignée descend de son fil, s'arrête, puis remonte. */
.hw-spider {
  position: absolute; top: 0; left: calc(50% + 420px);
  display: flex; flex-direction: column; align-items: center;
  color: var(--hw-purple-deep);
  animation: hw-drop 14s ease-in-out infinite;
}
:root[data-theme="dark"] .hw-spider { color: #b79bff; }
.hw-silk {
  display: block; width: 1px; height: 120px;
  background: linear-gradient(var(--hw-purple), rgba(139, 92, 246, 0.25));
}
@keyframes hw-drop {
  0%, 100% { transform: translateY(-150px); }
  16%, 46% { transform: translateY(0); }
  62% { transform: translateY(-150px); }
}
@media (max-width: 1100px) { .hw-spider { display: none; } }

/* Chauves-souris suspendues : dans les marges, et seulement s'il y en a. */
.hw-hang {
  position: absolute; top: 0;
  display: none;
  transform-origin: 50% 0;
  color: var(--hw-purple-deep);
  opacity: 0.5;
  animation: hw-sway 5.5s ease-in-out infinite;
}
:root[data-theme="dark"] .hw-hang { color: #2a1840; opacity: 0.8; }
.hw-hang .hw-thread {
  display: block; width: 1px; margin: 0 auto;
  background: linear-gradient(var(--hw-purple), transparent);
}
@keyframes hw-sway {
  0%, 100% { transform: rotate(-5deg); }
  50% { transform: rotate(5deg); }
}
/* Le contenu fait 1180px : au-delà de ~1320px il reste de la marge. */
@media (min-width: 1320px) { .hw-hang { display: block; } }

/* Une petite colonie traverse l'écran, en décalé. */
.hw-flyer {
  position: absolute; left: -60px;
  width: 30px; height: 30px;
  color: #241238;
  opacity: 0;
  animation: hw-cross 30s linear infinite;
}
:root[data-theme="dark"] .hw-flyer { color: #060309; }
.hw-flyer.f0 { top: 16%; }
.hw-flyer.f1 { top: 22%; width: 22px; height: 22px; }
.hw-flyer.f2 { top: 12%; width: 26px; height: 26px; }
@keyframes hw-cross {
  0%, 80% { opacity: 0; transform: translate(-60px, 0) scale(0.8); }
  82% { opacity: 0.4; }
  90% { transform: translate(52vw, -30px) scale(1); }
  97% { opacity: 0.4; }
  100% { opacity: 0; transform: translate(106vw, 14px) scale(0.8); }
}
.hw-flyer .hw-wing { transform-origin: 50% 50%; animation: hw-flap 0.4s ease-in-out infinite; }
@keyframes hw-flap { 50% { transform: scaleY(0.5); } }

/* --- Confettis de bonbons qui tombent, légers, en fond --------------- */
.hw-candy {
  position: absolute; top: -14px;
  animation-name: hw-candy-fall;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  opacity: 0.55;
}
@keyframes hw-candy-fall {
  from { transform: translate(0, -14px) rotate(0deg); }
  to { transform: translate(var(--drift), 105vh) rotate(var(--spin)); }
}
@media (prefers-reduced-motion: reduce) { .hw-candy { animation: none; display: none; } }

/* --- Sorcière qui traverse l'écran de temps en temps ------------------
   Vit dans #season-fx (fond), comme l'araignée et les chauves-souris : la
   demande laissait le choix "derrière ou au-dessus", et ça reste cohérent
   avec le reste du décor Halloween qui est tout en arrière-plan. */
.hw-witch {
  position: absolute;
  top: var(--witch-top, 18%);
  left: -180px;
  width: 150px; height: 56px;
  opacity: 0;
  animation: hw-witch-fly var(--witch-dur, 60s) linear infinite;
  animation-delay: var(--witch-delay, 0s);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}
/* Longue attente, passage bref : un intervalle de 45 à 90s en moyenne,
   re-tiré au sort à CHAQUE cycle par season.ui.js (pas figé au chargement),
   pour qu'il ne devienne jamais un cycle parfaitement répétitif. */
@keyframes hw-witch-fly {
  0%, 93% { opacity: 0; transform: translate(0, 0) rotate(-2deg); }
  95% { opacity: 0.9; }
  98% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(calc(100vw + 340px), -60px) rotate(-6deg); }
}
@media (max-width: 700px) { .hw-witch { width: 100px; height: 38px; } }
@media (prefers-reduced-motion: reduce) { .hw-witch { display: none; } }

/* --- Scène du bas : butte de terre, tombes, squelette, chaudron -------
   Même mécanique que la congère de Noël : posée dans #season-front pour
   être VUE par-dessus le pied de page, jamais sur un élément interactif —
   la place est réservée plus bas via le padding de main/footer. */
.hw-ground {
  position: absolute; left: 0; right: 0; bottom: 0; height: 36px;
  color: #2a2418;
}
:root[data-theme="dark"] .hw-ground { color: #191510; }
.hw-ground svg { width: 100%; height: 36px; display: block; }

.hw-pose {
  position: absolute; bottom: 0;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25));
}
.hw-pose svg { width: 100%; height: auto; display: block; }
@media (max-width: 1100px) { .hw-pose { display: none; } }

.hw-cauldron-wrap { position: relative; width: 100%; }
.hw-cauldron-wrap svg { width: 100%; height: auto; display: block; }

/* Bulles à la surface de la potion : montent et s'estompent, décalées. */
.hw-bulle { animation: hw-bulle-monte 2.4s ease-in infinite; }
.hw-bulle.b2 { animation-delay: 0.7s; animation-duration: 2.1s; }
.hw-bulle.b3 { animation-delay: 1.4s; animation-duration: 2.7s; }
@keyframes hw-bulle-monte {
  0% { opacity: 0; transform: translateY(3px) scale(0.6); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-6px) scale(1.15); }
}

/* Volutes de fumée : trois pastilles floutées qui montent et se dissipent. */
.hw-smoke {
  position: absolute; left: 50%; top: -4px;
  width: 10px; height: 10px; margin-left: -5px;
  border-radius: 50%;
  background: rgba(180, 180, 190, 0.5);
  filter: blur(2px);
  opacity: 0;
  animation: hw-smoke-monte 3.6s ease-in infinite;
}
.hw-smoke.s2 { left: 42%; width: 8px; height: 8px; animation-delay: 1.1s; animation-duration: 4.2s; }
.hw-smoke.s3 { left: 60%; width: 7px; height: 7px; animation-delay: 2.1s; animation-duration: 3.9s; }
@keyframes hw-smoke-monte {
  0% { opacity: 0; transform: translate(0, 0) scale(0.7); }
  20% { opacity: 0.5; }
  100% { opacity: 0; transform: translate(6px, -34px) scale(1.4); }
}

/* Réserve la place de la scène du bas, comme pour Noël (en plus modeste :
   pas de bonhommes, la butte de terre est plus basse que la congère). */
:root[data-season="halloween"] main.container { padding-bottom: 84px; }
:root[data-season="halloween"] .site-footer { padding-bottom: 84px; }
@media (max-width: 900px) {
  :root[data-season="halloween"] main.container { padding-bottom: 48px; }
  :root[data-season="halloween"] .site-footer { padding-bottom: 48px; }
  .hw-ground { height: 22px; }
  .hw-ground svg { height: 22px; }
}

/* ==================================================================
   NOËL / YULE
   ================================================================== */
/* La boule du logo se balance doucement, accrochée par son attache. */
:root[data-season="noel"] .brand-o > svg {
  transform-origin: 50% 8%;
  animation: nl-bauble 4.2s ease-in-out infinite;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28));
}
@keyframes nl-bauble {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(6deg); }
}

/* Guirlande tendue juste sous le bandeau haut. */
/* Les ampoules pulsent au lieu de s'éteindre : un clignotement franc dans
   le champ de vision fatigue vite quand on lit des cotes. */
/* Stalactites accrochées sous la guirlande. */
.nl-icicles {
  position: absolute; top: 22px; left: 0; right: 0; height: 22px;
  color: rgba(214, 235, 250, 0.75);
}
:root[data-theme="dark"] .nl-icicles { color: rgba(160, 200, 235, 0.4); }
.nl-icicles svg { width: 100%; height: 22px; display: block; }

/* Neige : trois couches de profondeur, peu de flocons. */
.nl-snow { position: absolute; inset: 0; }
.nl-flake {
  position: absolute; top: -12px;
  border-radius: 50%;
  background: #fff;
  animation-name: nl-fall;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
.nl-flake.l0 { opacity: 0.35; }
.nl-flake.l1 { opacity: 0.55; }
.nl-flake.l2 { opacity: 0.8; filter: blur(0.4px); }
@keyframes nl-fall {
  from { transform: translate(0, -12px); }
  to { transform: translate(var(--drift), 105vh); }
}

/* Congères au ras du bas de l'écran. */
/* ==================================================================
   Mouvement réduit : le décor reste, il cesse de bouger.
   ================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root[data-season] .brand-o > svg,
  .hw-hang, .hw-spider, .hw-flyer, .hw-flyer .hw-wing, .nl-bulb, .nl-flake {
    animation: none;
  }
  .hw-flyer, #season-front { display: none; }
  .hw-spider { transform: translateY(0); }
}

/* ==================================================================
   Décors saisonniers : deux couches, deux rôles.

   #season-fx    — FOND. z-index -1 : derrière tout le contenu, au-dessus
                   du fond de page. Lune, neige, chauves-souris, araignée.
                   Rien ici ne doit avoir besoin d'être lu.
   .season-head  — accroché au HEADER lui-même, et qui déborde vers le bas.
                   C'est ce qui « pend du haut » : toiles, guirlande,
                   stalactites. Posé en plein écran, ça venait barrer le
                   texte du bandeau sponsor ; accroché au header, ça pend
                   toujours au bon endroit quelle que soit la hauteur du
                   bandeau au-dessus.
   ================================================================== */
#season-fx { z-index: -1; }

/* z-index négatif : le décor accroché au header (toiles, guirlande...) doit
   TOUJOURS peindre sous le contenu de la barre (logo, liens, solde), jamais
   dessus. `.bar` et ses enfants ne sont pas positionnés : sans cette règle,
   `.season-head` (positionné, donc mis en avant par défaut) passait devant
   eux et rendait la nav illisible là où il chevauchait le logo ou les liens. */
.season-head {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  pointer-events: none;
  z-index: -1;
}
/* La barre elle-même reste au-dessus : #site-header est déjà en z-index 40
   par rapport au RESTE de la page, ce qui précède ne fait que réordonner ce
   qui se passe À L'INTÉRIEUR de la barre. */
.site-header .bar { position: relative; z-index: 1; }
/* La barre ne doit pas rogner ce qui pend en dessous. */
.site-header { overflow: visible; }

/* Toiles : dans les coins de la barre, elles débordent un peu vers le bas. */
.season-head .hw-web { top: 0; }

/* Une saison qui pend a besoin de place : on decale le contenu, plutot que
   de laisser le decor et le titre se disputer les memes pixels. */
:root[data-season="noel"] main.container { padding-top: 52px; }
:root[data-season="halloween"] main.container { padding-top: 28px; }

/* Stalactites collées au bord bas de la barre, guirlande juste en dessous.
   Ensemble elles occupent ~34px : c est la place qu on reserve plus bas
   avec le padding de main, pour qu elles ne mordent jamais sur le titre. */
.season-head .nl-icicles { top: 100%; height: 14px; }
.season-head .nl-icicles svg { height: 14px; }
.season-head .nl-garland { top: calc(100% + 10px); }

/* ==================================================================
   Décors saisonniers — couche AVANT et habillage des cartes.
   ================================================================== */

/* La neige passe devant le contenu. Transparente aux clics : un flocon
   n'intercepte jamais un bouton de cote. */
#season-front {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 80;
  overflow: hidden;
}

/* Neige accumulée sur le bord HAUT de la barre de navigation. */
.nl-crust {
  position: absolute; left: 0; right: 0; top: -9px; height: 10px;
  color: #eef6ff;
}
:root[data-theme="dark"] .nl-crust { color: #cfe2f5; }
.nl-crust svg { width: 100%; height: 10px; display: block; }

/* ==================================================================
   HALLOWEEN — habillage des cartes
   Les décors de carte sont en ::before / ::after avec des SVG en data:
   URI : aucune requête réseau, et rien à changer dans le rendu JS.
   Tout est en pointer-events:none et reste dans les coins.
   ================================================================== */

/* Fond de page franchement plus marqué en thème clair : sans ça, la saison
   ne se voyait qu'au logo et aux toiles du header. */
:root[data-season="halloween"]:not([data-theme="dark"]) {
  --bg: #f3e9f3;
  --surface-2: #faf3f7;
  --surface-3: #f0e4ee;
  --border: #e6d6e6;
  --border-strong: #cbb2cb;
  --depth-1: rgba(255, 138, 31, 0.16);
  --depth-2: rgba(139, 92, 246, 0.14);
  --depth-3: rgba(255, 138, 31, 0.10);
}

/* Toile dans l'angle haut-droit de chaque carte de pari. */
:root[data-season="halloween"] .bet-card,
:root[data-season="halloween"] .clip-card,
:root[data-season="halloween"] .shop-item { position: relative; overflow: hidden; }

:root[data-season="halloween"] .bet-card::before,
:root[data-season="halloween"] .clip-card::before {
  content: '';
  position: absolute; top: 0; right: 0;
  width: 74px; height: 74px;
  pointer-events: none;
  opacity: 0.3;
  background: no-repeat top right / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%238b5cf6' stroke-width='1.6'%3E%3Cpath d='M100 0 L0 58 M100 0 L42 100 M100 0 L16 84 M100 0 L72 100 M100 0 L0 26'/%3E%3Cpath d='M80 5 Q85 15 95 20'/%3E%3Cpath d='M62 11 Q73 27 89 38'/%3E%3Cpath d='M44 17 Q62 38 83 56'/%3E%3Cpath d='M26 23 Q50 50 77 74'/%3E%3C/svg%3E");
}
:root[data-season="halloween"][data-theme="dark"] .bet-card::before,
:root[data-season="halloween"][data-theme="dark"] .clip-card::before { opacity: 0.22; }

/* Les cartes « à la une » prennent une citrouille en filigrane dans l'angle
   bas-gauche, là où il n'y a jamais de texte. */
/* Le filigrane est un ::after, donc dernier enfant : sans z-index il se
   peindrait PAR-DESSUS les boutons de cote et les ternirait. On le force
   sous la rangee d issues (qui passe en z-index 1 juste apres). */
:root[data-season="halloween"] .bet-card.featured::after {
  z-index: 0;
  content: '';
  /* Dans l angle bas-droit, a l interieur de la carte : celle-ci est en
     overflow:hidden pour la toile, un debordement serait rogne. */
  position: absolute; right: 10px; bottom: 6px;
  width: 56px; height: 56px;
  pointer-events: none;
  opacity: 0.18;
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 34'%3E%3Cellipse cx='10.4' cy='20' rx='5.6' ry='8.2' fill='%23ff8a1f'/%3E%3Cellipse cx='23.6' cy='20' rx='5.6' ry='8.2' fill='%23ff8a1f'/%3E%3Cellipse cx='17' cy='20' rx='7.4' ry='8.8' fill='%23ff8a1f'/%3E%3Cpath d='M17 6.5c.3-2.3 1.7-3.9 3.9-4.5-.6 1.9-.4 3.4.7 4.6' fill='none' stroke='%233f7d34' stroke-width='2.6'/%3E%3C/svg%3E");
}
:root[data-season="halloween"][data-theme="dark"] .bet-card.featured::after { opacity: 0.2; }

/* Titres de section : une petite citrouille devant. */
:root[data-season="halloween"] .cat-title::before {
  content: '🎃';
  margin-right: 6px;
  font-size: 0.9em;
  filter: saturate(1.1);
}

/* L'icône ronde en tête de carte prend un halo orange. */
:root[data-season="halloween"] .bet-card .o-ico,
:root[data-season="halloween"] .bet-card > .bet-head > span:first-child {
  box-shadow: 0 0 0 2px rgba(255, 138, 31, 0.25);
}

:root[data-season] .bet-card > .outcomes,
:root[data-season] .bet-card > .bet-head,
:root[data-season] .bet-card > .bet-foot,
:root[data-season] .bet-card > .match-line,
:root[data-season] .bet-card > h3,
:root[data-season] .bet-card > p { position: relative; z-index: 1; }

/* ==================================================================
   NOËL — habillage des cartes
   ================================================================== */

/* Neige posée sur le bord haut de chaque carte. */
:root[data-season="noel"] .bet-card,
:root[data-season="noel"] .clip-card,
:root[data-season="noel"] .shop-item { position: relative; }

:root[data-season="noel"] .bet-card::before,
:root[data-season="noel"] .clip-card::before {
  content: '';
  position: absolute; left: 8px; right: 8px; top: -5px;
  height: 8px;
  pointer-events: none;
  background: no-repeat center / 100% 100%
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 8' preserveAspectRatio='none'%3E%3Cpath d='M0 8V4q7-3 14-1t11 0 10-2 12 2 11-1 13 2 12-3 11 2 12-1 14 2v4z' fill='%23cfe2f5'/%3E%3C/svg%3E");
  opacity: 0.9;
}
:root[data-season="noel"][data-theme="dark"] .bet-card::before,
:root[data-season="noel"][data-theme="dark"] .clip-card::before { opacity: 0.55; }

/* Houx dans l'angle haut-droit des cartes à la une. */
:root[data-season="noel"] .bet-card.featured::after {
  z-index: 0;
  content: '';
  position: absolute; top: 6px; right: 8px;
  width: 34px; height: 26px;
  pointer-events: none;
  opacity: 0.85;
  background: no-repeat center / contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 32'%3E%3Cpath d='M22 6q7-6 14-2-3 7-10 8 6 2 7 9-8 1-12-5-4 6-12 5 1-7 7-9-7-1-10-8 7-4 14 2z' fill='%232f7d4f'/%3E%3Ccircle cx='20' cy='23' r='4' fill='%23d8453c'/%3E%3Ccircle cx='27' cy='25' r='3.4' fill='%23c0392b'/%3E%3C/svg%3E");
}

/* Titres de section : un flocon devant. */
:root[data-season="noel"] .cat-title::before {
  content: '❄';
  margin-right: 6px;
  color: #7fb3e0;
}

/* Une carte à la une porte un liseré doré plutôt qu'orange : c'est plus
   Noël, et ça reste la même hiérarchie visuelle. */
:root[data-season="noel"] .bet-card.featured { border-color: var(--nl-gold); }

/* ==================================================================
   NOËL / YULE — version « rouge dominant »
   Le fond de page devient rouge profond et les cartes passent en crème :
   du texte posé directement sur du rouge se lit mal, alors que du texte
   sombre sur une carte claire qui ressort du rouge se lit très bien.
   Conséquence assumée : la saison force la palette de SURFACES claires
   même en mode sombre — sinon on aurait du texte clair sur des cartes
   claires. Le mode sombre garde son rouge plus profond et ses cartes
   ivoire plutôt que blanches, pour rester moins lumineux.
   ================================================================== */
:root[data-season="noel"] {
  --nl-red: #d8453c;
  --nl-red-deep: #a82c25;
  --nl-green: #1f7a45;
  --nl-green-soft: #2fbf5a;
  --nl-gold: #e0b23c;

  --accent: var(--nl-red);
  --action: var(--nl-red);
  --action-strong: var(--nl-red-deep);
  --special: var(--nl-green);

  /* Textes : sombres, puisqu'ils vivent sur des cartes claires. */
  --text: #241014;
  --text-soft: #55383c;
  --text-dim: #85696d;

  /* Vert sapin en complément, pour que tout ne soit pas rouge. */
  --good: #1f7a45;  --good-wash: #e3f5ea;  --good-ink: #14603a;  --good-line: #b6e2c6;
  --bad: #c0392b;   --bad-wash: #fdecea;   --bad-ink: #8f2820;      --bad-line: #f2c2bc;
  --brand-wash: #e2f6f5;
  --action-wash: #fdeceb;
  --action-ink: #8f2820;
  --toast-bg: #241014; --toast-fg: #fff7ef;
  --shine: rgba(255, 255, 255, 0.8);
  --scroll-thumb: #b4726d;
  --scroll-thumb-hover: #96544f;
}

/* Thème clair : rouge sapin, cartes blanc crème. */
:root[data-season="noel"]:not([data-theme="dark"]) {
  --bg: #8c1c1c;
  --surface: #fffaf3;
  --surface-2: #f7efe4;
  --surface-3: #efe4d5;
  --border: #e4d5c4;
  --border-strong: #c9b39c;
  --header-bg: rgba(122, 22, 22, 0.95);
  --header-line: #e0b23c;
  --depth-1: rgba(255, 255, 255, 0.06);
  --depth-2: rgba(224, 178, 60, 0.10);
  --depth-3: rgba(31, 122, 69, 0.08);
}

/* Thème sombre : même idée, rouge plus profond et cartes ivoire. */
:root[data-season="noel"][data-theme="dark"] {
  --bg: #4a0d10;
  --surface: #f6ece0;
  --surface-2: #ece0d1;
  --surface-3: #e0d2c0;
  --border: #d2c1ae;
  --border-strong: #b39c85;
  --header-bg: rgba(48, 8, 11, 0.96);
  --header-line: #c8922e;
  --depth-1: rgba(255, 255, 255, 0.04);
  --depth-2: rgba(224, 178, 60, 0.08);
  --depth-3: rgba(31, 122, 69, 0.07);
}

/* Le header est rouge soutenu : son contenu doit repasser en clair, sinon
   du texte sombre sur du rouge sombre devient illisible. */
:root[data-season="noel"] .site-header,
:root[data-season="noel"] .site-header a,
:root[data-season="noel"] .site-header .brand { color: #fff6ea; }
:root[data-season="noel"] .site-header .site-nav a { color: #f3dcc8; }
:root[data-season="noel"] .site-header .site-nav a:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }
:root[data-season="noel"] .site-header .site-nav a.active { color: #fff; background: rgba(255, 255, 255, 0.16); }
:root[data-season="noel"] .site-header .icon-btn,
:root[data-season="noel"] .site-header .notif-bell,
:root[data-season="noel"] .site-header .btn {
  color: #fff6ea;
  border-color: rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
}
:root[data-season="noel"] .site-header .balance-chip {
  color: #fff6ea;
  border-color: var(--nl-gold);
  background: rgba(255, 255, 255, 0.1);
}
:root[data-season="noel"] .site-header .btn-primary {
  background: var(--nl-green); border-color: var(--nl-green); color: #fff;
}
/* Bandeau sponsor : même bande rouge que le header, pour une seule masse
   de couleur en haut plutôt que deux teintes qui se cognent. */
:root[data-season="noel"] .sponsor-banner {
  background: var(--header-bg); color: #f3dcc8; border-bottom-color: rgba(255, 255, 255, 0.12);
}

/* Touches de vert sapin, pour que ce ne soit pas du rouge partout. */
:root[data-season="noel"] .bet-card { border-left: 3px solid var(--nl-green); }
:root[data-season="noel"] .bet-card.featured { border-color: var(--nl-gold); border-left-color: var(--nl-gold); }
:root[data-season="noel"] .badge { border-color: var(--nl-green); }
:root[data-season="noel"] .cat-title { color: #f6e3c9; }

/* --- Bonnet posé sur le « T » final ------------------------------- */
.brand-t { position: relative; display: inline-block; }
.brand-t > svg { display: none; }
:root[data-season="noel"] .brand-t > svg {
  display: block;
  position: absolute;
  left: -42%; bottom: 68%;
  width: 168%; height: auto;
  transform: rotate(-12deg);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
}

/* --- Guirlande : ampoules 50 % plus grosses, avec vraie lueur ------ */
.nl-bulb {
  position: absolute;
  width: 11px; height: 15px;         /* 7x10 auparavant */
  margin-left: -5.5px;
  border-radius: 50% 50% 46% 46%;
  background: radial-gradient(circle at 38% 32%, #fff, var(--bulb) 62%);
  /* Deux ombres : un halo serré et un flou large — c'est le second qui
     donne l'impression que la lumière rayonne au lieu d'être un disque. */
  box-shadow: 0 0 7px 1px var(--bulb), 0 0 20px 6px var(--bulb);
  animation-name: nl-twinkle;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
/* La douille, pour que l'ampoule ait l'air accrochée au fil. */
.nl-bulb::before {
  content: '';
  position: absolute; left: 50%; top: -4px;
  width: 4px; height: 5px; margin-left: -2px;
  border-radius: 1px;
  background: #4a3520;
}
/* Les non-clignotantes respirent doucement. */
@keyframes nl-twinkle {
  0%, 100% { opacity: 0.82; box-shadow: 0 0 6px 1px var(--bulb), 0 0 14px 4px var(--bulb); }
  50% { opacity: 1; box-shadow: 0 0 9px 2px var(--bulb), 0 0 24px 8px var(--bulb); }
}
/* Une sur six clignote franchement — mais jamais jusqu'à l'extinction
   totale : une guirlande qui s'éteint dans le champ de vision accroche
   l'œil en permanence. */
.nl-bulb.blink { animation-name: nl-blink; }
@keyframes nl-blink {
  0%, 44%, 100% { opacity: 1; box-shadow: 0 0 9px 2px var(--bulb), 0 0 24px 8px var(--bulb); }
  52%, 76% { opacity: 0.4; box-shadow: 0 0 3px 0 var(--bulb); }
}
.nl-garland { height: 32px; }
.nl-garland svg { height: 32px; }

/* --- Congère du bas + bonhommes de neige --------------------------- */
.nl-drift {
  position: absolute; left: 0; right: 0; bottom: 0; height: 74px;
  color: #fbfeff;
}
:root[data-season="noel"][data-theme="dark"] .nl-drift { color: #e8f2fa; }
.nl-drift svg { width: 100%; height: 74px; display: block; }

.nl-snowman {
  position: absolute; bottom: 0;
  width: 96px;
  /* Enfoncé dans la congère : seuls le buste et la tête dépassent. */
  margin-bottom: 14px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.18));
}
.nl-snowman svg { width: 100%; height: auto; display: block; }
.nl-snowman.left { left: 2%; }
.nl-snowman.right { right: 2%; transform: scaleX(-1); }
/* Sous 900 px la congère mange trop d'écran : on garde la neige, on retire
   les bonhommes. */
@media (max-width: 900px) {
  .nl-snowman { display: none; }
  .nl-drift, .nl-drift svg { height: 46px; }
}

/* La congère est décorative mais occupe de la place : on la réserve, sinon
   elle passerait derrière le dernier bloc de contenu et le coupon mobile. */
:root[data-season="noel"] main.container { padding-bottom: 112px; }
@media (max-width: 900px) {
  :root[data-season="noel"] main.container { padding-bottom: 72px; }
}

/* --- Traîneau qui traverse de temps en temps ----------------------- */
/* Le traîneau vit dans la couche AVANT : il passe devant les cartes de
   pari, comme demandé. Il reste transparent aux clics (#season-front est
   en pointer-events:none), donc il ne gêne aucune mise au passage.
   Sa hauteur et son délai sont tirés au hasard à chaque chargement — un
   passage toujours identique au même endroit se remarquerait comme un
   défaut plutôt que comme une surprise. */
.nl-sleigh {
  position: absolute;
  top: var(--sleigh-top, 22%);
  left: -200px;
  width: 168px; height: 63px;   /* ratio du viewBox 160x60 */
  opacity: 0;
  animation: nl-fly var(--sleigh-dur, 34s) linear infinite;
  animation-delay: var(--sleigh-delay, 0s);
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}

/* Longue attente, passage rapide : on le remarque une fois, on ne le subit
   pas. La trajectoire monte légèrement, comme un décollage. */
/* Longue attente, passage rapide : on le remarque une fois, on ne le subit
   pas. La trajectoire monte légèrement, comme un décollage. */
@keyframes nl-fly {
  0%, 86% { opacity: 0; transform: translate(0, 0) rotate(-2deg); }
  88% { opacity: 1; }
  96% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(100vw + 360px), -90px) rotate(-7deg); }
}
@media (max-width: 700px) { .nl-sleigh { width: 110px; } }

@media (prefers-reduced-motion: reduce) {
  .nl-sleigh { display: none; }
  .nl-bulb { animation: none; }
}

/* Sur fond rouge, les flocons restent blancs (le bleu pale ne ressort pas). */
:root[data-season="noel"] .nl-flake { background: #fff; }

/* Texte posé DIRECTEMENT sur le rouge : il doit être clair. Celui des cartes
   reste sombre — un seul --text global ne peut pas servir les deux, puisque
   la page et les cartes ont désormais des fonds opposés. */
:root[data-season="noel"] .page-head h1,
:root[data-season="noel"] .page-head p,
:root[data-season="noel"] .page-head .muted,
:root[data-season="noel"] main.container > h1,
:root[data-season="noel"] main.container > p,
:root[data-season="noel"] main.container > .muted,
:root[data-season="noel"] .col-main > h1,
:root[data-season="noel"] .col-main > p,
:root[data-season="noel"] .cat-title {
  color: #fff3e2;
}
:root[data-season="noel"] .page-head .muted,
:root[data-season="noel"] main.container > .muted,
:root[data-season="noel"] .col-main > p.muted { color: #f0d7bd; }

/* Fil d'Ariane et liens hors carte. */
:root[data-season="noel"] .crumbs,
:root[data-season="noel"] .crumbs a,
:root[data-season="noel"] .crumbs .sep { color: #f0d7bd; }
:root[data-season="noel"] .crumbs a:hover { color: #fff; }

/* Boutons d'appel posés sur le rouge : contour clair pour qu'ils se voient. */
:root[data-season="noel"] #home-cta .btn:not(.btn-primary) {
  color: #fff3e2;
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.1);
}

/* ------------------------------------------------------------------
   La congère (Noël) et la scène de cimetière (Halloween) sont fixées au bas
   de l'écran et passent DEVANT (sinon le pied de page les masquerait
   entièrement). Il faut donc leur laisser la place : tout ce qui vit en bas
   remonte au-dessus, ou se décale. Généralisé à [data-season] plutôt que
   limité à "noel", puisque les deux saisons ont désormais un décor de bas
   de page en avant-plan. */

/* Coupon mobile : barre fixe en bas, interactive. Elle doit rester
   au-dessus du décor, jamais dessous. */
:root[data-season] #ticket .tk-bar,
:root[data-season] #ticket .ticket-panel,
:root[data-season] #ticket .tk-backdrop { z-index: 95; }

/* Pied de page : son contenu remonte au-dessus de la congère. */
:root[data-season="noel"] .site-footer { padding-bottom: 112px; }
@media (max-width: 900px) {
  :root[data-season="noel"] .site-footer { padding-bottom: 56px; }
}

/* Toast : il apparaît en bas, il doit rester lisible. */
:root[data-season] .toast { z-index: 96; }

/* ------------------------------------------------------------------
   Noël — lisibilité du header.
   Le rouge du bandeau et le rouge des textes d'accent étaient la même
   famille : le solde ressortait à 1,32 de contraste, autant dire rien.
   Le bandeau descend d'un ton, et tout ce qui s'y pose passe en crème.
   ------------------------------------------------------------------ */
:root[data-season="noel"]:not([data-theme="dark"]) { --header-bg: rgba(92, 15, 15, 0.96); }
:root[data-season="noel"][data-theme="dark"] { --header-bg: rgba(58, 8, 10, 0.97); }

/* Le solde : .balance-chip .amount force --action-ink (rouge foncé) plus haut
   dans la feuille. C'est CETTE règle qu'il faut battre, pas celle du jeton. */
:root[data-season="noel"] .site-header .balance-chip .amount,
:root[data-season="noel"] .site-header .balance-chip.bump .amount { color: #ffe6b8; }
:root[data-season="noel"] .site-header .balance-chip {
  border-color: var(--nl-gold);
  background: rgba(255, 255, 255, 0.12);
}

/* Le « Bet » du logo était en teal sur rouge : 2,95 de contraste. En or, il
   reste distinct du « Odin » crème tout en se lisant sur le bandeau. */
:root[data-season="noel"] .site-header .brand .dot { color: #ffd98a; }
:root[data-season="noel"] .site-header .brand { color: #fffaf2; }

/* Cloche, thème, menu : même traitement crème. */
:root[data-season="noel"] .site-header .notif-bell,
:root[data-season="noel"] .site-header .icon-btn,
:root[data-season="noel"] .site-header .nav-toggle { color: #fff6ea; }

/* ------------------------------------------------------------------
   Guirlandes : remontées contre la barre, et prolongées sur les côtés.
   ------------------------------------------------------------------ */
/* Elle mordait 10 px sous le header ; elle s'y accroche maintenant. */
.season-head .nl-garland { top: calc(100% - 4px); }
.season-head .nl-icicles { top: calc(100% - 2px); }

/* Brins verticaux le long des bords. Ils vivent dans la couche de FOND :
   dans les marges ils se voient, et sur un écran étroit ils passent
   simplement derrière le contenu au lieu de le gêner. */
.nl-garland-side {
  position: absolute; top: 0; bottom: 0;
  width: 40px;
  display: none;
}
.nl-garland-side svg { width: 40px; height: 100%; display: block; }
.nl-garland-side.left { left: 6px; }
.nl-garland-side.right { right: 6px; transform: scaleX(-1); }
/* Le contenu fait 1180 px : en dessous de ~1280 il ne reste plus de marge. */
@media (min-width: 1280px) { .nl-garland-side { display: block; } }

/* ------------------------------------------------------------------
   Noël — la scène du bas : congère, bonhommes, sapins et cadeaux.
   ------------------------------------------------------------------ */
.nl-drift, .nl-drift svg { height: 62px; }

/* Un décor posé sur la neige. margin-bottom l'enfonce plus ou moins dans
   la congère : identiques et alignés, ils feraient frise de papier peint. */
.nl-pose {
  position: absolute; bottom: 0;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.16));
}
.nl-pose svg { width: 100%; height: auto; display: block; }

/* Sous 1100 px, la scène se réduit aux bonhommes ; en dessous de 900 il ne
   reste que la neige. Entassés sur un écran étroit, ils se chevauchent. */
@media (max-width: 1100px) { .nl-pose { display: none; } }

/* ==================================================================
   Calendrier de l'avent (/avent)
   Grille de cases : une par jour. Quatre états distincts, lisibles sans
   couleur seule — le numéro, le gain et l'étiquette portent l'information.
   ================================================================== */
.av-entete { margin-bottom: 18px; }
.av-entete h1 { margin: 0 0 6px; }
.av-actions { margin-top: 14px; }
.av-bilan { margin: 10px 0 0; font-size: 0.86rem; }

.av-grille {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
}
.av-case {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; min-height: 96px; padding: 12px 8px;
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--surface); box-shadow: var(--shadow-sm);
}
.av-jour { font-size: 0.72rem; color: var(--text-dim); letter-spacing: 0.02em; }
.av-num { font-size: 1.7rem; font-weight: 900; line-height: 1; }
.av-gain { font-size: 1rem; font-weight: 800; color: var(--good-ink); }
.av-etiquette {
  position: absolute; top: -8px; right: 8px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 0.66rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--rar-legendary-wash); color: var(--rar-legendary-ink);
  border: 1px solid var(--rar-legendary);
}

/* Pas encore arrivée : présente mais clairement en retrait. */
.av-a-venir { background: var(--surface-2); }
.av-a-venir .av-num { color: var(--text-dim); }

/* Ratée : fermée pour de bon. Barrée, pour que ce soit sans ambiguïté. */
.av-ratee { background: var(--surface-2); opacity: 0.55; }
.av-ratee .av-num { color: var(--text-dim); text-decoration: line-through; }

/* Ouverte : le gain remplace le numéro. */
.av-ouverte { background: var(--good-wash); border-color: var(--good-line); }

/* Celle du jour : la seule sur laquelle on peut agir. */
.av-aujourdhui {
  background: var(--action-wash); border-color: var(--rar-legendary);
  box-shadow: 0 0 0 2px var(--rar-legendary-wash), var(--shadow);
}
.av-aujourdhui .av-num { color: var(--action-ink); }
.av-aujourdhui::after {
  content: 'À ouvrir';
  position: absolute; bottom: 6px;
  font-size: 0.64rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--action-ink);
}
.av-aujourdhui .av-num { margin-bottom: 10px; }

/* Dernière case : celle du jour du tournoi. */
.av-finale { border-color: var(--rar-legendary); }

.av-vient-ouvrir { animation: av-pop 0.5s ease; }
.av-gagnante { box-shadow: 0 0 0 2px var(--good), var(--shadow); }
@keyframes av-pop {
  0% { transform: scale(0.86); }
  55% { transform: scale(1.06); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { .av-vient-ouvrir { animation: none; } }

@media (max-width: 480px) {
  .av-grille { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
  .av-case { min-height: 82px; }
  .av-num { font-size: 1.4rem; }
}

/* ==================================================================
   Panel admin — Statistiques
   Pas de bibliotheque de graphiques (CSP scriptSrc 'self') : les courbes
   et histogrammes sont du SVG genere par admin.js, mis en forme ici.
   ================================================================== */
.stat-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px; margin-top: 12px;
}
.stat-kpi {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 4px;
}
.stat-kpi-label { font-size: 0.74rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.03em; }
.stat-kpi-value { font-size: 1.3rem; font-weight: 900; color: var(--text); font-variant-numeric: tabular-nums; }

.stat-subtabs { margin-top: 18px; }

.stat-period { margin: 10px 0 4px; }

.stat-chart { display: block; color: var(--text-dim); }
.stat-chart-labels {
  display: flex; justify-content: space-between;
  font-size: 0.74rem; margin-top: 2px;
}

#stats-body h3 { margin: 22px 0 8px; font-size: 0.98rem; }
#stats-body h3:first-child { margin-top: 4px; }
