:root {
  /* Strict NoBaK palette - black/white base, lime as the single rare
     accent. Surfaces are derived only as white-alpha layers over black, no
     invented colors, no decorative gradients. */
  --nbk-black: #000000;
  --nbk-white: #ffffff;
  --nbk-lime: #c7f33c;
  --nbk-lime-soft: #e1f2ae;

  /* ===== CANAL D'ENCRE =====
     120 couleurs de la feuille étaient écrites `rgba(255,255,255,α)` : les
     surfaces, les bordures, les filets, les textes secondaires. Toutes disent
     la même chose - « éclaircir le fond de α » - ce qui n'a de sens que sur
     un fond sombre. Elles passent par ce canal, qui s'inverse avec le thème :
     une seule ligne à changer plutôt que 120.
     Format `R G B` séparé par des espaces, pour être consommé en
     `rgb(var(--ink-rgb) / α)`.
     Les noirs translucides ne basculent PAS : sur 46, trente sont des ombres
     et des voiles posés sur des photos - une ombre reste sombre en thème
     clair, et un voile qui rend un texte lisible sur une image aussi. */
  --ink-rgb: 255 255 255;

  --bg: var(--nbk-black);
  --text: var(--nbk-white);
  /* Fond de la barre de navigation : le seul aplat noir de la feuille qui
     décrive une surface d'interface et non un voile. */
  --nav-bg: rgb(0 0 0 / 0.85);
  /* Surface OPAQUE - pour ce qui ne peut pas être translucide : en-tête de
     tableau collant (les lignes défilent dessous), liste d’options d’un
     select. Un jeton distinct de --surface-1, qui lui est translucide. */
  --surface-solid: #0b0d0a;
  /* Fond des champs de saisie. Distinct de --surface-solid : un champ est
     plus profond que la surface qui le porte en thème sombre, plus clair
     qu’elle en thème clair. */
  --field-bg: #000000;

  /* Fond du bandeau d'en-tête des pages intérieures. Un aplat, pas une surface
     translucide : l'inversion du canal d'encre ne peut rien pour lui, il lui
     faut sa propre valeur par thème. */
  --page-hero-bg: linear-gradient(180deg, #000 0%, #060806 62%, #000 100%);
  --page-hero-glow: rgba(199, 243, 60, 0.09);

  /* Couleurs de statut (disponible / indisponible / à surveiller). Elles
     étaient écrites en dur dans des teintes pâles, réglées pour un fond noir :
     sur papier, du menthe clair et du rose clair sont invisibles. */
  --status-ok: #baffd4;
  --status-ko: #ffb3c1;
  --status-warn: #ffc86e;

  --text-secondary: rgb(var(--ink-rgb) / 0.62);
  /* 0.47 et non 0.40. À 0.40, ces deux jetons passaient sous le seuil AA de
     4.5:1 sur tous les fonds du site - mesuré entre 3.66 (sur le noir) et
     3.83 (sur les panneaux) - et ils portent à eux seuls 350 des 383 textes
     non conformes relevés sur les 23 pages : légendes, libellés de formulaire,
     dates d'historique, indices de carte joueur.
     0.47 est le plus petit alpha qui tienne 4.5:1 sur le fond le plus clair
     employé ici (rgb(36,36,36) → 4.55). L'écart avec --text-secondary (0.62)
     reste franc, donc la hiérarchie de lecture ne bouge pas. */
  --text-tertiary: rgb(var(--ink-rgb) / 0.47);
  --muted: rgb(var(--ink-rgb) / 0.47);

  --surface-1: rgb(var(--ink-rgb) / 0.04);
  --surface-2: rgb(var(--ink-rgb) / 0.07);
  --border: rgb(var(--ink-rgb) / 0.1);
  --border-strong: rgb(var(--ink-rgb) / 0.18);

  --accent: var(--nbk-lime);
  --accent-2: var(--nbk-lime-soft);
  --accent-glow: rgba(199, 243, 60, 0.5);
  --accent-gradient: linear-gradient(to right, var(--nbk-lime), var(--nbk-lime-soft));
  --danger: #ff5c7a;
  --gold: var(--nbk-lime);
  --gold-soft: rgba(199, 243, 60, 0.14);
  --neon: var(--nbk-lime-soft);
  --green: var(--nbk-lime);
  --green-dark: #a3c92f;
  --green-glow: rgba(199, 243, 60, 0.35);

  /* "Primary" means white, not a color - nav, buttons, panels, forms, cards
     all read mostly in white-on-black. See the handful of solid white-fill
     components (.account-avatar, .auth-switch-indicator) for the deliberate
     black-text-on-white treatment; everything else uses translucent white
     borders/backgrounds so text stays white throughout. */
  --primary: #ffffff;
  --primary-2: #ffffff;
  --primary-dark: #d6d6d6;
  --primary-glow: rgb(var(--ink-rgb) / 0.3);
  --primary-soft: rgb(var(--ink-rgb) / 0.1);

  /* Chakra Petch plutôt que Space Grotesk : coins tronqués sur plusieurs
     glyphes (A, M, N, V...), qui font écho aux équerres HUD des tuiles
     (.home-grid-cell, .panel::after) au lieu d'être un choix neutre. Space
     Grotesk est nommée explicitement dans le guide de design d'Anthropic
     comme nouveau défaut "sûr" que les IA convergent à répéter - remplacée
     pour cette raison, le 2026-09-05. */
  --font-display: 'Chakra Petch', Helvetica, Arial, sans-serif;
  --font-body: 'DM Sans', Helvetica, Arial, sans-serif;

  /* Échelle typographique - chaque pas tombe sur un pixel entier à
     racine 16px. Avant, 47 tailles distinctes cohabitaient, dont dix-neuf
     entre 0,58 et 0,96rem : des écarts invisibles à l'œil (0,85 contre
     0,86rem, soit 0,16px) qui ne produisaient aucune hiérarchie lisible,
     et des valeurs fractionnaires qui rendent le texte flou. */
  --text-3xs: 0.625rem;
  --text-2xs: 0.6875rem;
  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-md: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;
  --text-4xl: 2.75rem;

  /* Echelle des rayons. Trois valeurs, chacune avec un role, plutot que les
     quinze valeurs distinctes que la feuille avait accumulees - dont 12px et
     14px, les plus employees du site, qui n'etaient declarees nulle part. */
  --radius: 4px;                    /* controles : champs, boutons, puces */
  --radius-card: 8px;               /* surfaces : cartes, lignes, groupes */
  --radius-lg: 16px;                /* grandes surfaces : modales, panneaux */

  /* Anneau de focus. Il existait en sept variantes (3, 4 ou 6 px, alpha de
     0.1 a 0.2) pour la meme interaction. Une seule valeur, et surtout une
     valeur qui suit le theme : du lime a 0.2 sur du papier ne se voyait pas,
     donc le focus etait invisible en clair. */
  --ring: 0 0 0 3px rgba(199, 243, 60, 0.28);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Horizontal padding of .app, as a token rather than a literal, because
     the full-bleed .page-hero cancels it with an equal negative margin. When the
     two were hardcoded separately they drifted: .app dropped to 16px at
     900px but .hero kept its -28px until 640px, so every viewport in the
     641-900px band (tablets, small laptop windows) had the hero sticking
     12px past the viewport on both sides - clipped edges, since
     `html { overflow-x: hidden }` below hides the resulting scrollbar
     rather than the overflow itself. Anything that needs to bleed past the
     app gutter should use calc(-1 * var(--app-pad-x)), never a literal. */
  --app-pad-x: 28px;

  /* Elevation tokens - layered on top of the flat black/white/lime base to
     give cards/panels a bit more depth without inventing new colors. */
  --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 12px 32px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, 0.55);
  --shadow-glow: 0 0 0 1px rgba(199, 243, 60, 0.25), 0 12px 40px rgba(199, 243, 60, 0.12);
}

/* ===========================================================================
   THÈME CLAIR
   ---------------------------------------------------------------------------
   Le canal d'encre s'inverse, ce qui retourne d'un coup les 120 surfaces,
   bordures et filets de la feuille. Ne restent à redéfinir ici que les
   couleurs qui ne peuvent pas se déduire d'une inversion.

   Le lime ne bouge pas - c'est la marque. Mais #c7f33c sur blanc ne fait que
   1.6:1 : en thème clair il ne peut plus porter de texte ni servir de filet
   fin. `--accent-ink` est donc le lime « lisible » (assombri jusqu'à passer
   AA sur le fond du thème), réservé au texte et aux traits ; le lime pur reste
   pour les aplats, où c'est le texte noir posé dessus qui porte le contraste.

   Les ombres restent noires : une ombre est une absence de lumière, elle ne
   s'inverse pas.
   =========================================================================== */
:root[data-theme="light"] {
  --ink-rgb: 0 0 0;

  --bg: #f4f5f1;
  --text: #10120d;
  --nav-bg: rgb(244 245 241 / 0.88);

  /* Sur fond clair, les surfaces translucides se posent sur du papier :
     les alphas issus du canal donnent des gris trop lavés pour séparer une
     carte de son fond. On les remonte d'un cran. */
  --surface-1: rgb(var(--ink-rgb) / 0.035);
  --surface-2: rgb(var(--ink-rgb) / 0.06);
  --border: rgb(var(--ink-rgb) / 0.14);
  --border-strong: rgb(var(--ink-rgb) / 0.26);

  /* Lime assombri : 4.6:1 sur #f4f5f1, donc utilisable pour du texte. */
  --accent-ink: #4a6100;
  --accent-glow: rgba(122, 158, 0, 0.35);
  --gold-soft: rgba(122, 158, 0, 0.16);
  --green-glow: rgba(122, 158, 0, 0.25);

  --danger: #b3123a;

  /* Le « primaire » du thème sombre était le blanc ; sur papier c'est l'encre. */
  --primary: #10120d;
  --primary-2: #10120d;
  --primary-dark: #000000;

  --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.10);
  --shadow-md: 0 12px 32px rgba(0, 0, 0, 0.13);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, 0.16);
  --shadow-glow: 0 0 0 1px rgba(122, 158, 0, 0.3), 0 12px 40px rgba(122, 158, 0, 0.14);
  --surface-solid: #ffffff;

  /* Le fond de .auth-card se creusait vers rgba(0,0,0,0.86) en dur : sur
     papier la carte devenait un pave presque noir, avec son texte sombre
     par-dessus. Sur fond clair la carte se souleve du papier au lieu de s'y
     enfoncer. */
  --card-deep: rgba(255, 255, 255, 0.92);
  --hud-line: rgba(74, 97, 0, 0.30);

  /* Papier un peu plus dense que le fond de page, pour que le bandeau se
     détache sans virer à la bande grise. */
  --page-hero-bg: linear-gradient(180deg, #eceee6 0%, #e4e7dc 62%, #eceee6 100%);
  --page-hero-glow: rgba(122, 158, 0, 0.16);
  --field-bg: #ffffff;

  --status-ok: #0b6b34;
  --status-ko: #a3113a;
  --status-warn: #7a4a00;

  /* 0.56 et non 0.47 : sur papier, le noir translucide monte moins vite que le
     blanc ne descendait sur le noir. Mesuré 3.44 à 0.47, 4.65 à 0.56 sur le
     plus clair des fonds employés. */
  --text-tertiary: rgb(var(--ink-rgb) / 0.57);
  --muted: rgb(var(--ink-rgb) / 0.57);

  --ring: 0 0 0 3px rgba(74, 97, 0, 0.24);
}

/* En thème sombre, le lime est déjà lisible : le jeton « encre » lui est égal.
   Défini ici et non dans :root pour rester à côté de son homologue clair. */
:root {
  --accent-ink: var(--nbk-lime);

  /* Homologues sombres de --card-deep / --hud-line, definis ici pour rester
     a cote de leur version claire. Le rendu sombre ne change pas. */
  --card-deep: rgba(0, 0, 0, 0.86);
  --hud-line: rgba(199, 243, 60, 0.22);

  /* Rendu natif des selecteurs de date et d'heure. Il etait force a "dark"
     quel que soit le theme : le calendrier s'ouvrait en noir sur une page
     blanche. */
  --field-scheme: dark;
}

:root[data-theme="light"] {
  --field-scheme: light;
}

/* L'overlay de diffusion est incrusté dans OBS, par-dessus une capture de jeu :
   il est toujours sombre, quel que soit le thème choisi pour le site. On
   ré-épingle les jetons sur <body> - plus spécifique que :root - plutôt que
   d'exclure la classe de chaque règle. */
body.obs-overlay-mode {
  --ink-rgb: 255 255 255;
  --bg: var(--nbk-black);
  --text: var(--nbk-white);
  --accent-ink: var(--nbk-lime);
  --primary: #ffffff;
  --primary-2: #ffffff;
  --danger: #ff5c7a;
  --surface-solid: #0b0d0a;
  --field-bg: #000000;
}

html {
  min-height: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
}

/* `html` is the sole scroll owner (above). `body` used to also declare
   `height: 100%; overflow-y: auto`, which made it a SECOND, independent
   scroll container nested inside html's. Something (most likely the
   browser's native fragment-scroll for the "#page-accueil" hash the SPA
   sets on load) was scrolling that inner body box by itself, leaving
   `window.scrollY`/`document.documentElement.scrollTop` at 0 while body's
   own content silently shifted up by ~90px - cutting the top of the hero
   title off under the sticky nav on load, on every page, every viewport
   width. Dropping height/overflow-y here isn't enough on its own, though:
   per the CSS Overflow spec, declaring `overflow-x` as anything other than
   `visible` forces the UA to compute the *other* axis as `auto` too, even
   when not written - so a leftover `overflow-x: hidden` here was silently
   re-creating the exact same second scroll container. html already has
   `overflow-x: hidden`, so body doesn't need its own. */
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  background: var(--bg);
  color: var(--text);
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.03em;
  margin: 0;
}

h2 {
  text-transform: uppercase;
}

.caption,
.section-eyebrow,
.eyebrow {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

:focus-visible {
  outline: 2px solid var(--nbk-lime);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

* {
  box-sizing: border-box;
}

.app {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: min(1600px, 94vw);
  min-height: 100vh;
  margin: 0 auto;
  padding: 24px var(--app-pad-x) 36px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

@media (max-width: 900px) {
  :root {
    --app-pad-x: 16px;
  }

  .app {
    max-width: 100%;
  }
}

.page-section {
  display: none;
  width: 100%;
  overflow: visible;
}

.page-section.active {
  display: block;
}

.page-section .panel,
.page-section .overlay-panel,
.page-section .team-cards,
.page-section .maps-grid,
.page-section .panel.actions,
.page-section .panel.rules-panel,
.page-section .panel.maps-panel,
.page-section .panel.ban-summary,
.page-section .panel.result-panel {
  overflow: hidden;
}

@media (max-width: 900px) {
  .app {
    padding: 18px var(--app-pad-x) 20px;
  }
}

/* ===== NAVIGATION ===== */
.main-nav {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: 20px;
  padding: 14px 28px;
  border-bottom: 1px solid transparent;
  background: var(--nav-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: border-color 0.2s var(--ease);
}

.main-nav.is-scrolled {
  border-bottom-color: var(--border);
}

.nav-brand {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--text);
  font-size: var(--text-base);
  font-weight: 700;
}

.brand-link {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: inherit;
  text-decoration: none;
  transition: transform 0.3s ease;
}

.brand-link:hover {
  transform: translateX(4px);
}

.nav-logo {
  width: 44px;
  height: 44px;
  display: inline-block;
  object-fit: cover;
  border-radius: var(--radius-card);
  box-shadow: 0 6px 18px rgba(0,0,0,0.45), 0 0 0 1px rgb(var(--ink-rgb) / 0.25);
  background: transparent;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s ease;
}

.brand-link:hover .nav-logo {
  transform: rotate(-8deg) scale(1.08);
  box-shadow: 0 8px 24px rgb(var(--ink-rgb) / 0.45), 0 0 0 1px rgb(var(--ink-rgb) / 0.6);
}

.brand-social-links {
  display: flex;
  align-items: center;
  gap: 6px;
}

.brand-social-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--text);
  background: rgb(var(--ink-rgb) / 0.06);
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.brand-social-icon:hover {
  transform: translateY(-1px) scale(1.06);
}

.brand-social-twitch:hover {
  background: rgba(145, 70, 255, 0.25);
  color: #b794ff;
}

.brand-social-youtube:hover {
  background: rgba(255, 0, 0, 0.2);
  color: #ff6b6b;
}

.brand-social-tiktok:hover {
  background: rgb(var(--ink-rgb) / 0.15);
  color: #25f4ee;
}

.brand-social-discord:hover {
  background: rgba(88, 101, 242, 0.25);
  color: #8b95ff;
}

@media (max-width: 560px) {
  .brand-social-links {
    display: none;
  }
}

/* Screen-reader only */
.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius);
  background: transparent;
  border: 1px solid var(--border);
  cursor: pointer;
}

.nav-toggle .hamburger {
  width: 18px;
  height: 2px;
  background: var(--text);
  display: block;
  position: relative;
  transition: background 0.15s var(--ease);
}
.nav-toggle .hamburger::before,
.nav-toggle .hamburger::after {
  content: '';
  position: absolute;
  left: 0;
  width: 18px;
  height: 2px;
  background: var(--text);
  transition: transform 0.2s var(--ease), top 0.2s var(--ease);
}
.nav-toggle .hamburger::before { top: -6px; }
.nav-toggle .hamburger::after { top: 6px; }

/* Morph into an X when the drawer is open, so it's obvious it now closes it */
.nav-toggle[aria-expanded="true"] .hamburger {
  background: transparent;
}
.nav-toggle[aria-expanded="true"] .hamburger::before {
  top: 0;
  transform: rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .hamburger::after {
  top: 0;
  transform: rotate(-45deg);
}

.nav-brand {
  flex: none;
}

.nav-links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-width: 0;
  gap: 16px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  margin: 0;
  padding: 0 2px;
  list-style: none;
  mask-image: linear-gradient(to right, transparent, black 12px, black calc(100% - 12px), transparent);
}

.nav-links::-webkit-scrollbar {
  display: none;
}

.nav-links li {
  margin: 0;
  flex: none;
}

.nav-links a {
  position: relative;
  color: var(--text-secondary);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color 0.18s var(--ease);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 2px;
}

.nav-links a svg {
  flex: none;
  width: 16px;
  height: 16px;
  transition: color 0.18s var(--ease);
}

.nav-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--nbk-lime);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.18s var(--ease);
}

.nav-links a:hover,
.nav-links a:focus-visible {
  color: var(--text);
}

.nav-links a.active {
  color: var(--text);
}

.nav-links a.active::after {
  transform: scaleX(1);
}

.nav-link-label {
  display: inline;
}

@media (max-width: 900px) {
  /* The SPA sets `location.hash = '#page-accueil'` (and every in-app nav
     link is itself a `#page-xxx` fragment link), so the browser's native
     fragment-scroll runs on every navigation. Below 900px .main-nav is a
     sticky top bar (~88px incl. padding) rather than the desktop left
     rail, so without a scroll offset that native scroll aligns the target
     section's top edge with the viewport's top edge - right behind the
     bar - clipping the hero title (or whichever section) under the nav on
     load and on every mobile nav tap. */
  .page-section {
    scroll-margin-top: 88px;
  }

  .main-nav {
    flex-wrap: wrap;
    justify-content: space-between;
  }

  /* .main-nav's backdrop-filter creates a new containing block for any
     fixed-position descendant (CSS spec quirk), so .nav-links.open's
     `position: fixed; inset: 0` was resolving against the nav bar's own
     ~70px-tall box instead of the viewport - the mobile menu rendered as a
     tiny sliver at the top with the page bleeding through underneath it,
     instead of a proper full-screen overlay. Dropping backdrop-filter for
     as long as the drawer is open removes that containing block so inset:0
     goes back to meaning "the whole viewport".
  */
  .main-nav:has(.nav-links.open) {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .nav-toggle {
    display: inline-flex;
    position: relative;
    z-index: 1;
  }
  .nav-links {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 50;
    background: var(--field-bg);
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: 88px 20px 24px;
    overflow-y: auto;
    mask-image: none;
  }
  .nav-links.open {
    display: flex;
  }
  .nav-links li {
    width: 100%;
    border-bottom: 1px solid var(--border);
  }
  .nav-links li:first-child {
    border-top: 1px solid var(--border);
  }
  .nav-links a {
    position: relative;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 16px;
    justify-content: flex-start;
    padding: 16px 8px;
    border-left: 3px solid transparent;
    font-size: var(--text-base);
    min-height: 52px;
    transition: background 0.15s var(--ease), border-color 0.15s var(--ease), padding-left 0.15s var(--ease);
  }
  .nav-links a svg {
    width: 20px;
    height: 20px;
  }
  .nav-links a:active {
    background: var(--surface-2);
  }
  .nav-links a::after {
    display: none;
  }
  .nav-links a.active {
    color: var(--accent-ink);
    border-left-color: var(--accent-ink);
    padding-left: 16px;
    background: var(--surface-1);
  }
  .nav-link-label {
    font-size: var(--text-base);
  }
}

/* Desktop: the nav becomes a fixed left icon rail instead of a horizontal
   top bar, freeing up vertical space and giving every page more width.
   Labels are hidden (nav-tooltip below shows the name on hover/focus
   instead) - mobile is untouched, it keeps the top bar + drawer above. */
@media (min-width: 901px) {
  .main-nav {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 60;
    width: 96px;
    height: 100vh;
    flex-direction: column;
    justify-content: flex-start;
    padding: 20px 0;
    gap: 22px;
    border-right: 1px solid transparent;
    border-bottom: none;
  }

  .main-nav.is-scrolled {
    border-right-color: var(--border);
    border-bottom-color: transparent;
  }

  body {
    padding-left: 96px;
  }

  .nav-brand {
    flex-direction: column;
    gap: 10px;
  }

  /* .brand-link itself stays row-direction (logo + wordmark) everywhere
     else on the site - only stack it here, on the rail. */
  .brand-link {
    flex-direction: column;
    gap: 6px;
  }

  .nav-brand strong {
    font-size: var(--text-md);
  }

  /* Social icons move into a flyout off the logo instead of sitting
     permanently under it - reclaims rail height for the actual nav links.
     Opens on hovering/focusing anywhere in .nav-brand (the logo+wordmark),
     stays open while the pointer is over the flyout itself since it's
     still a descendant of .nav-brand. */
  .brand-social-links {
    position: absolute;
    left: 100%;
    top: 0;
    margin-left: 14px;
    flex-direction: column;
    background: rgba(10, 14, 11, 0.95);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 8px;
    opacity: 0;
    pointer-events: none;
    transform: translateX(-8px);
    transition: opacity 0.15s var(--ease), transform 0.15s var(--ease);
  }

  .nav-brand:hover .brand-social-links,
  .nav-brand:focus-within .brand-social-links {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0);
  }

  .nav-links {
    flex: 1 1 auto;
    flex-direction: column;
    justify-content: flex-start;
    overflow-x: hidden;
    overflow-y: auto;
    mask-image: none;
    gap: 4px;
    padding: 0;
  }

  .nav-links li {
    width: 100%;
  }

  .nav-links a {
    flex-direction: column;
    width: 100%;
    padding: 10px 4px;
    gap: 2px;
  }

  .nav-link-label {
    display: none;
  }

  .nav-links a svg {
    width: 22px;
    height: 22px;
  }

  .nav-cart-btn {
    width: 100%;
    margin: auto 0 0;
    border-left: none;
    border-top: 1px solid var(--border);
    padding-left: 0;
    padding-top: 12px;
  }

  .nav-cart-btn svg {
    width: 22px;
    height: 22px;
  }

  /* Logged-in "Compte" pill (avatar + "Espace joueur - <pseudo>") is sized
     for the horizontal bar - on the rail, keep just the avatar so it stays
     as compact as every other icon. */
  .nav-compte-profile {
    padding: 0;
  }

  .nav-compte-username {
    display: none;
  }
}

.page-section {
  display: none;
  width: 100%;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.page-section.active {
  display: block;
  opacity: 1;
  transform: translateY(0);
}

.nav-brand strong {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}

/* Hover/focus bubble showing a nav link's name - was kept in the DOM but
   disabled while nav labels were always visible in the horizontal top bar.
   Only relevant now on the desktop rail (min-width: 901px, see the nav rail
   rules above), which hides labels down to icons only; below that, the
   mobile drawer already shows full labels, so the bubble stays off there.
   JS positions it to the right of the hovered icon (script.js,
   showNavTooltip). */
.nav-tooltip {
  display: none;
}

@media (min-width: 901px) {
  .nav-tooltip {
    display: block;
    position: fixed;
    z-index: 70;
    transform: translate(0, -50%);
    padding: 6px 10px;
    border-radius: var(--radius);
    background: rgba(10, 14, 11, 0.95);
    border: 1px solid var(--border);
    color: var(--text);
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s var(--ease);
  }

  .nav-tooltip.visible {
    opacity: 1;
  }
}

/* Compte nav item: once logged in, swap the generic person icon for the
   account's avatar + pseudo so it reads like "you", not just a menu entry. */
.nav-compte-profile {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 4px;
}

.nav-compte-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  flex-shrink: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-2xs);
  font-weight: 700;
  color: #0d0a1a;
  background: linear-gradient(135deg, rgb(var(--ink-rgb) / 0.9), rgb(var(--ink-rgb) / 0.7));
}

.nav-compte-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nav-compte-username {
  font-size: var(--text-sm);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 600;
  font-size: var(--text-xs);
}

.eyebrow:empty {
  display: none;
}

/* ===== STATS BAR - le relevé qui reçoit le vol =====
   Le hero se termine sur une ligne de télémétrie (SCN / PROF / %). Cette barre
   est la première chose sous lui : elle en reprend la grammaire - index
   numérotés, chiffres à chasse fixe, filet lime - pour que la sortie du monde
   et l'entrée dans la page se lisent comme une seule séquence. */
.stats-bar {
  display: flex;
  position: relative;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 32px;
}

/* Un filet lime court sur toute la longueur du bord supérieur : c'est la
   ligne d'horizon du monde qui se prolonge dans la page. */
.stats-bar::before {
  content: '';
  position: absolute;
  inset: -1px 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, rgba(199, 243, 60, 0.55), rgba(199, 243, 60, 0.08) 60%, transparent);
  pointer-events: none;
}

.stat-item {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 22px 24px;
  border-left: 1px solid var(--border);
  overflow: hidden;
  transition: background 0.2s var(--ease);
}

.stat-item:first-child {
  border-left: none;
}

.stat-item:hover {
  background: var(--surface-1);
}

.stat-item::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--nbk-lime);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s var(--ease);
}

.stat-item:hover::before {
  transform: scaleX(1);
}

.stat-icon {
  color: var(--text-tertiary);
  margin-bottom: 6px;
  transition: color 0.2s var(--ease);
}

.stat-item:hover .stat-icon {
  color: var(--accent-ink);
}

.stat-number {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.8rem, 3.4vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .stats-bar {
    flex-wrap: wrap;
  }
  .stat-item {
    flex: 1 1 50%;
    border-left: none;
    border-top: 1px solid var(--border);
    padding: 16px;
  }
  .stat-item:nth-child(odd) {
    border-right: 1px solid var(--border);
  }
  .stat-item:first-child,
  .stat-item:nth-child(2) {
    border-top: none;
  }
}

/* ===== HOME GRID ===== */
.home-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
  margin-bottom: 32px;
  /* Sans ca, chaque case s'etire a la hauteur de la plus remplie de sa
     rangee : le Tournoi, qui tient en une phrase et un bouton, se retrouvait
     avec 180 px de vide sous son bouton parce que les News d'a cote etaient
     hautes. Chaque case prend desormais la hauteur de son contenu. */
  align-items: start;
}

.home-grid-cell {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  /* Les huit premières couches sont les équerres HUD (cf. .panel::after) :
     elles vivent ici, dans le fond, parce que ::before et ::after de cette
     tuile sont déjà pris. Positionnement en quatre valeurs (`right 9px`) pour
     accrocher chaque barre au bon bord.
     Ensuite la lumière, orientée en haut à gauche comme dans le monde du
     hero, pour que toutes les tuiles aient la même source. */
  --hud-c: var(--hud-line);
  --hud-s: 13px;
  background:
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px top 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px top 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px top 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px top 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px bottom 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px bottom 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px bottom 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px bottom 9px / var(--hud-s) 1px no-repeat,
    radial-gradient(120% 90% at 0% 0%, rgba(199, 243, 60, 0.05), transparent 55%),
    linear-gradient(160deg, var(--surface-2), var(--surface-1));
  padding: 26px 26px 24px;
  overflow: hidden;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.home-grid-cell::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--accent-gradient);
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}

.home-grid-cell:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  --hud-c: rgba(199, 243, 60, 0.5);
}

.home-grid-cell:hover::before {
  opacity: 1;
}

.home-grid-news { grid-column: span 8; }
.home-grid-tournoi { grid-column: span 4; }
.home-grid-roster { grid-column: span 6; }
.home-grid-boutique { grid-column: span 6; }

.home-grid .section-heading { margin: 0 0 16px; }
.home-grid .news-grid { gap: 14px; }

.home-teaser-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
}

.home-teaser-card p {
  margin: 0;
  color: var(--text-secondary);
}

.home-grid-cta {
  margin-top: 16px;
}

.home-roster-preview,
.home-boutique-preview {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.home-roster-preview .player-card {
  width: 84px;
  flex: none;
  cursor: default;
}

.home-roster-preview .player-card:hover,
.home-roster-preview .player-card:focus-visible {
  transform: none;
}

/* The monogram is a real element now (.player-card-monogram, sized for this
   thumbnail further down) - ::after on the card is the top edge highlight,
   which must keep its own geometry here. */

.home-boutique-preview .boutique-card {
  width: 140px;
  flex: none;
  cursor: default;
}

@media (max-width: 1024px) {
  .home-grid-news,
  .home-grid-tournoi,
  .home-grid-roster,
  .home-grid-boutique {
    grid-column: span 12;
  }
}

/* ===== PAGE HERO - en-tête des pages intérieures =====
   L'accueil ouvre sur un monde traversé à la molette ; les pages intérieures
   ne peuvent pas se le permettre - on y arrive pour faire quelque chose. Elles
   en gardent donc les signes, pas le dispositif : la grille technique en fond,
   le filet lime, les équerres, la même échelle typographique. */
.page-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 52px 42px 48px;
  margin: 0 calc(-1 * var(--app-pad-x)) 8px;
  border-bottom: 1px solid var(--border);
  /* Le bandeau tirait un dégradé noir en dur : en thème clair, son titre
     devenait sombre sur sombre. Il passe par des jetons dédiés, parce qu'une
     inversion du canal d'encre ne suffit pas ici - c'est un aplat, pas une
     surface translucide. */
  background:
    radial-gradient(circle at 82% 12%, var(--page-hero-glow), transparent 46%),
    var(--page-hero-bg);
  overflow: hidden;
}

/* La même trame que le sol du monde, en fond : c'est le raccord visuel entre
   l'accueil et le reste du site. */
.page-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, rgba(199, 243, 60, 0.05) 1px, transparent 1px),
    linear-gradient(180deg, rgba(199, 243, 60, 0.05) 1px, transparent 1px);
  background-size: 64px 64px, 64px 64px;
  mask-image: radial-gradient(120% 90% at 20% 0%, #000, transparent 72%);
  -webkit-mask-image: radial-gradient(120% 90% at 20% 0%, #000, transparent 72%);
  pointer-events: none;
}

.page-hero > * { position: relative; }

.page-hero h1 {
  margin: 0;
  max-width: 18ch;
  font-family: var(--font-display);
  font-size: clamp(2rem, 4.6vw, 3.4rem);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  text-wrap: balance;
}

.page-hero-lede {
  margin: 0;
  max-width: 58ch;
  color: var(--text-secondary);
  font-size: var(--text-lg);
  line-height: 1.6;
}

.page-hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 10px;
}

@media (max-width: 640px) {
  .page-hero { padding: 36px 22px 32px; }
}

/* ===== ORGANISATION (page de vente) ===== */
.org-sales-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
  margin: 24px 0 32px;
}

.org-sales-feature {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: linear-gradient(160deg, var(--surface-2), var(--surface-1));
  padding: 26px 26px 24px;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}

.org-sales-feature:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.org-sales-feature h3 {
  margin: 8px 0 10px;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.org-sales-feature p {
  margin: 0;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* Les étapes portent leur propre compteur lime plutôt que les puces natives :
   c'est une marche à suivre, pas une énumération. */
.org-sales-steps {
  margin: 0 0 32px;
  padding: 0;
  list-style: none;
  counter-reset: orgstep;
  display: grid;
  gap: 12px;
}

.org-sales-steps li {
  position: relative;
  margin: 0;
  padding: 16px 20px 16px 62px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-1);
  color: var(--text-secondary);
  line-height: 1.6;
}

.org-sales-steps li::before {
  counter-increment: orgstep;
  content: '0' counter(orgstep);
  position: absolute;
  left: 20px;
  top: 15px;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ===== DISCORD BANNER ===== */
.discord-banner {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 40px 42px;
  margin-bottom: 8px;
  border-radius: var(--radius-card);
  background: var(--nbk-lime);
  overflow: hidden;
  box-shadow: var(--shadow-glow);
}

.discord-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.05) 0 2px, transparent 2px 18px);
  pointer-events: none;
}

/* Le wordmark en très grand, débordant à droite et à peine plus sombre que le
   fond : la bande devient une pièce imprimée plutôt qu'un rectangle de
   couleur. Il déborde volontairement du cadre - un mot coupé se lit comme une
   marque, un mot centré comme un titre. */
.discord-banner::after {
  content: 'NOBAK';
  position: absolute;
  right: -0.06em;
  bottom: -0.28em;
  color: rgba(0, 0, 0, 0.07);
  font-family: var(--font-display);
  font-size: clamp(5rem, 15vw, 11rem);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}

.discord-banner h2 {
  position: relative;
}

.discord-banner .btn {
  position: relative;
}

.discord-banner h2 {
  margin: 0;
  color: var(--nbk-black);
  text-transform: uppercase;
  font-size: clamp(1.4rem, 2.4vw, 2rem);
}

.discord-banner .btn {
  background: var(--nbk-black);
  color: var(--accent-ink);
}

.discord-banner .btn:hover {
  background: #111;
}

@media (max-width: 640px) {
  .discord-banner {
    padding: 28px 24px;
  }
}

/* ===== OVERLAY DOWNLOAD PAGE - SmartScreen warning ===== */
.overlay-warning-box {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 24px;
  margin: 24px 0 32px;
  border: 1px solid #ff8c00;
  border-radius: var(--radius-card);
  background: rgba(255, 140, 0, 0.1);
}
.overlay-warning-box svg {
  flex-shrink: 0;
  color: #ff8c00;
}
.overlay-warning-box h3 {
  margin: 0 0 8px;
  color: var(--status-warn);
  font-size: var(--text-base);
}
.overlay-warning-box p {
  margin: 0 0 8px;
  color: var(--text-secondary);
  line-height: 1.6;
}
.overlay-warning-box p:last-child {
  margin-bottom: 0;
}
.overlay-warning-box strong {
  color: var(--text);
}

/* ===== OVERLAY DOWNLOAD PAGE - pricing plans ===== */
.overlay-plans-intro {
  max-width: 560px;
  margin: 0 0 24px;
  color: var(--text-secondary);
  line-height: 1.55;
}
.overlay-plans {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  margin-bottom: 8px;
}
@media (max-width: 1180px) {
  .overlay-plans { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 760px) {
  .overlay-plans { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .overlay-plans { grid-template-columns: 1fr; }
}
.overlay-plan {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 28px 22px 24px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.overlay-plan:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}
.overlay-plan-highlight {
  border-color: var(--accent-ink);
}
.overlay-plan-tag {
  position: absolute;
  top: -11px;
  left: 22px;
  padding: 4px 10px;
  background: var(--nbk-lime);
  color: var(--nbk-black);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  border-radius: var(--radius);
}
.overlay-plan-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
}
.overlay-plan-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.overlay-plan-price .amount {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 700;
  letter-spacing: -0.5px;
}
.overlay-plan-price .cycle {
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  font-weight: 500;
}
.overlay-plan-features {
  flex: 1;
  list-style: none;
  margin: 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.overlay-plan-features li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: var(--text-md);
  color: var(--text-secondary);
  line-height: 1.4;
}
.overlay-plan-features li::before {
  content: '';
  width: 14px;
  height: 14px;
  margin-top: 2px;
  flex-shrink: 0;
  background: var(--nbk-lime);
  clip-path: polygon(38% 76%, 15% 53%, 5% 63%, 38% 96%, 96% 38%, 86% 28%);
}
.overlay-plan-note {
  margin: -8px 0 0;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.overlay-plan .btn {
  margin-top: auto;
  text-align: center;
}

/* ===== BUTTONS =====
   Two archetypes, matching 404.html: a solid gradient pill for primary
   actions (.btn), and a glass outline pill for secondary/neutral ones
   (.btn.reset) - same distinction as that page's gradient "LOG IN" button
   vs its translucent "Return to Main Page" liquid-glass button. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: var(--nbk-lime);
  color: var(--nbk-black);
  padding: 0.9rem 1.5rem;
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
  min-height: 44px;
}

.btn:hover {
  background: var(--nbk-lime-soft);
  transform: translateY(-2px);
  box-shadow: 0 10px 28px rgba(199, 243, 60, 0.28);
}

/* Presses back down under the cursor instead of staying lifted - without
   it a click had no physical read at all. */
.btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(199, 243, 60, 0.2);
}

.btn.reset {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border-strong);
}

.btn.reset:hover {
  background: rgba(199, 243, 60, 0.06);
  border-color: var(--accent-ink);
  color: var(--accent-ink);
  box-shadow: none;
}

.btn.reset:active {
  background: rgba(199, 243, 60, 0.12);
  box-shadow: none;
}

.btn:disabled,
.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Destructive actions: the one deliberate exception to the lime/black/white
   palette - red for delete buttons only, everywhere in the app. */
.btn[class*="delete"] {
  border-color: var(--danger);
  color: var(--danger);
}

.btn[class*="delete"]:hover {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--nbk-black);
}

/* Panels wrap nearly every section on every page, so their treatment sets
   the perceived quality of the whole site. They were a flat fill with a
   1px border - correct, but weightless. A hairline highlight on the top
   edge plus a soft drop shadow gives them a sense of being lit and lifted
   off the page, the same language as the player cards. */
.panel {
  position: relative;
  width: 100%;
  margin-top: 24px;
  padding: 28px 32px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
  box-shadow: var(--shadow-sm);
}

.panel::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: linear-gradient(90deg, transparent, rgb(var(--ink-rgb) / 0.16) 22%, rgb(var(--ink-rgb) / 0.16) 78%, transparent);
  pointer-events: none;
}

/* ===== ÉQUERRES HUD =====
   Quatre marques d'angle, en un seul pseudo-élément : huit dégradés d'un pixel
   posés aux quatre coins. C'est le même signe que porte le cadre du monde
   scroll-scrubbé du hero (voir scroll-world.css) - le reprendre ici est ce qui
   rattache les pages au hero sans avoir à les redessiner une par une.
   Volontairement discret : à 0.22 d'opacité c'est une texture, pas un ornement.
   Sur .panel c'est ::after parce que ::before porte déjà le filet supérieur ;
   les tuiles de l'accueil, dont les deux pseudo-éléments sont déjà pris (barre
   lime au survol, halo suivant le pointeur), portent les mêmes équerres dans
   leur propre `background` - voir .home-grid-cell. */
.panel::after {
  content: '';
  position: absolute;
  inset: 9px;
  pointer-events: none;
  --hud-c: var(--hud-line);
  --hud-s: 13px;
  background:
    linear-gradient(var(--hud-c), var(--hud-c)) 0 0 / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 0 0 / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 100% 0 / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 100% 0 / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 0 100% / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 0 100% / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 100% 100% / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) 100% 100% / var(--hud-s) 1px no-repeat;
}

.panel:hover::after {
  --hud-c: rgba(199, 243, 60, 0.5);
}

/* #page-team/#page-tournoi carry .panel directly on the <section> itself
   (not a child), hence the ID-only selectors rather than descendants;
   #page-mapban's panels are nested children; #page-compte uses .auth-card
   instead of .panel. Admin/Régie/Coach/Planning panels use the same flat
   surface as everywhere else now that there's no background video to
   differentiate against. */
#page-team,
#page-tournoi,
#page-mapban .panel {
  background: var(--surface-1);
}

/* `#page-compte .auth-card` aplatissait la carte pour neutraliser son ancien
   dégradé blanchâtre. Le style de base porte désormais les bonnes surfaces et
   les équerres HUD (dans son `background`) : garder cette surcharge d'ID les
   effaçait. */

/* ===== SECTION HEADING - reusable eyebrow+title pattern used across
   Équipe / Calendrier / Compte / Admin so those pages read as intentional
   sections rather than bare <h2>s. ===== */
.section-heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 6px 4px 2px;
}

.section-heading .caption,
.section-heading .section-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.section-heading .caption::before,
.section-heading .section-eyebrow::before {
  content: '';
  width: 16px;
  height: 2px;
  background: var(--nbk-lime);
  flex: none;
}

/* Section titles carry every page on this site, so they get display weight
   and a fluid scale rather than the near-body-size step they used to sit at
   - a 1.4rem heading under a 12px eyebrow read as a label, not a title.
   Raised here, at the shared primitive, so every page moves together
   instead of each one growing its own override. */
.section-heading h2 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 18px;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.028em;
  text-transform: uppercase;
}

/* Le titre tire un filet jusqu'au bord de son conteneur. La Boutique portait
   un soulignement de 64 px qui lui était propre ; il est remplacé par ce
   filet-ci, pour que toutes les pages titrent de la même façon. */
.section-heading h2::after {
  content: '';
  flex: 1;
  height: 1px;
  min-width: 24px;
  background: linear-gradient(90deg, rgba(199, 243, 60, 0.45), rgba(199, 243, 60, 0));
}

/* ===== NEWS (Accueil) ===== */
.news-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 20px;
}

.news-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 220px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.92) 78%), var(--nbk-black);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}

.news-card:hover {
  border-color: var(--accent-ink);
  background-color: var(--surface-2);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.news-card-body {
  padding: 16px 18px 18px;
}

.news-card-date {
  display: inline-block;
  font-family: var(--font-display);
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: var(--text-xs);
  font-weight: 700;
  margin-bottom: 6px;
}

.news-card-title {
  margin: 0 0 6px;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
}

.news-card-desc {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.4;
}

/* Etat vide des actualites.
   L'ancienne version etait un encadre en pointilles avec une ligne de gris au
   centre. Le pointille est l'idiome du "contenu manquant" : il fait lire la
   case comme cassee plutot que comme vide a dessein. Et son icone, dessinee
   dans un data-URI referencant var(--ink-rgb), ne s'est jamais affichee - une
   variable CSS ne se resout pas a l'interieur d'une data-URI, l'image echouait
   au chargement. Elle est maintenant en clair dans le HTML.

   Le fond n'annonce plus une absence, il indique ou ca se passe. */
.news-empty-msg {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 4px 0 8px;
  color: var(--text-secondary);
  font-size: var(--text-md);
}

.news-empty-msg__icone {
  display: inline-flex;
  margin-bottom: 2px;
  color: var(--accent-ink);
}

.news-empty-msg__titre {
  margin: 0;
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--text-lg, 1.0625rem);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.news-empty-msg__sous {
  margin: 0;
  max-width: 46ch;
  line-height: 1.55;
}

.news-empty-msg__lien {
  margin-top: 6px;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}

.news-empty-msg__lien:hover { color: var(--text); }

/* Sur une case large, l'etat vide se pose en ligne plutot qu'en colonne :
   un bloc etroit centre dans 735 px de large se lirait comme un oubli.
   La classe est posee par renderNewsGrid(). */
.home-grid-news.is-vide .news-empty-msg {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 4px 16px;
  padding: 2px 0 4px;
}

/* Placement explicite : sans ca les quatre elements se rangeaient dans
   l'ordre du flux et le lien tombait sous le titre, ou son soulignement
   s'etirait sur toute la colonne. */
.home-grid-news.is-vide .news-empty-msg__icone { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
.home-grid-news.is-vide .news-empty-msg__titre { grid-column: 2; grid-row: 1; align-self: end; }
.home-grid-news.is-vide .news-empty-msg__sous  { grid-column: 2; grid-row: 2; align-self: start; max-width: none; }
.home-grid-news.is-vide .news-empty-msg__lien  { grid-column: 3; grid-row: 1 / span 2; align-self: center; margin-top: 0; }

/* Le soulignement doit epouser le texte, pas la cellule qui le contient. */
.news-empty-msg__lien { align-self: flex-start; width: fit-content; }

@media (max-width: 720px) {
  .home-grid-news.is-vide .news-empty-msg {
    grid-template-columns: auto 1fr;
    gap: 6px 12px;
  }
  .home-grid-news.is-vide .news-empty-msg__lien { grid-column: 2; grid-row: 3; margin-top: 6px; }
}

/* Un catalogue de un ou deux produits laissait un trou a droite : les cartes
   s'etirent pour occuper la rangee au lieu de rester calees a 140 px. */
.home-boutique-preview .boutique-card {
  flex: 1 1 140px;
  max-width: 210px;
}

.partners-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}

.partner-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 220px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.92) 78%), var(--surface-2);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}

.partner-card:hover {
  border-color: var(--accent-ink);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.partner-card-body {
  padding: 16px 18px 18px;
}

.partner-card-name {
  margin: 0 0 6px;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
}

.partner-card-desc {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.4;
}

/* ===== BOUTIQUE ===== */
.boutique-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}

.boutique-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 1 / 1;
  min-height: 260px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.92) 78%), var(--nbk-black);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  cursor: pointer;
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}

.boutique-card:hover {
  border-color: var(--accent-ink);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.boutique-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 1;
  background: linear-gradient(90deg, var(--nbk-lime), transparent 75%);
  opacity: 0;
  transition: opacity 0.18s var(--ease);
}

.boutique-card:hover::before,
.boutique-card:focus-visible::before {
  opacity: 1;
}

.boutique-card::after {
  content: "Voir le produit →";
  position: absolute;
  inset: auto 0 0 0;
  padding: 10px 18px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--nbk-black);
  background: var(--nbk-lime);
  transform: translateY(100%);
  transition: transform 0.18s var(--ease);
}

.boutique-card:hover::after,
.boutique-card:focus-visible::after {
  transform: translateY(0);
}

/* Carries its own scrim. The card declares a darkening gradient in its
   `background` shorthand, but the product photo is set as an inline
   background-image, which replaces that whole layer - so a product shot on
   a light background (the white studio shot of the jersey, say) left the
   title and price as white-on-white. Putting the gradient on the text block
   itself cannot be overridden by the card's image. */
.boutique-card-body {
  position: relative;
  padding: 64px 18px 18px;
  background: linear-gradient(0deg, rgba(3, 8, 5, 0.97) 0%, rgba(3, 8, 5, 0.9) 38%, rgba(3, 8, 5, 0.5) 70%, transparent 100%);
}

.boutique-card-title {
  margin: 0 0 6px;
  font-size: var(--text-lg);
  font-weight: 700;
}

.boutique-card-price {
  margin: 0;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
}

.boutique-card-badge {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 1;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--nbk-black);
  border: 1px solid var(--border);
}

.boutique-product-image {
  width: 100%;
  height: 340px;
  border-radius: var(--radius);
  background-color: var(--surface-2);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  margin-bottom: 16px;
  border: 1px solid var(--border);
  padding: 22px;
  box-sizing: border-box;
}

.boutique-product-desc {
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.5;
  margin: 10px 0 18px;
  white-space: pre-line;
}

.boutique-size-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}

.boutique-size-btn {
  padding: 8px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  font-weight: 700;
  font-size: var(--text-md);
  cursor: pointer;
  transition: border-color 0.18s var(--ease), color 0.18s var(--ease);
}

.boutique-size-btn:hover {
  border-color: var(--accent-ink);
}

.boutique-size-btn--oos,
.boutique-size-btn:disabled {
  color: var(--text-tertiary);
  border-color: var(--border);
  text-decoration: line-through;
  cursor: not-allowed;
}

.boutique-size-btn--oos:hover,
.boutique-size-btn:disabled:hover {
  border-color: var(--border);
}

.auth-field-hint {
  color: var(--text-tertiary);
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  font-size: var(--text-xs);
}

.boutique-size-btn.active {
  background: var(--nbk-lime);
  border-color: var(--accent-ink);
  color: var(--nbk-black);
}

/* ===== LIVE STREAM EMBED - module docked to the right of the hero title. ===== */
.hero-stream {
  position: relative;
  z-index: 1;
  /* Was a flat 340px regardless of screen size - a lot of unused space next
     to it on a real desktop viewport. Scales with the viewport now, capped
     both ends. */
  flex: 0 0 clamp(360px, 30vw, 520px);
  width: clamp(360px, 30vw, 520px);
  max-width: 100%;
  align-self: center;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}

/* Le module live était un enfant flex du hero, calé à droite du titre. Depuis
   que le hero est devenu le monde scroll-scrubbé (#scrollWorld), il est un
   bloc autonome posé juste sous la scène : `align-self`/`flex` n'ont plus de
   conteneur flex pour les lire, donc le centrage passe par la marge. */
#page-accueil > .hero-stream {
  margin: 0 auto 8px;
}

@media (max-width: 900px) {
  .hero-stream {
    flex-basis: auto;
    width: 100%;
    align-self: stretch;
  }
}

.hero-stream-label {
  display: inline-block;
  font-family: var(--font-display);
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: var(--text-xs);
  font-weight: 600;
}

.stream-embed-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--field-bg);
  overflow: hidden;
}

.stream-embed-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.stream-offline-card {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: radial-gradient(circle at center, rgb(var(--ink-rgb) / 0.05), transparent 70%);
}

.stream-offline-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-tertiary);
}

.stream-offline-text {
  margin: 0;
  color: var(--text-secondary);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.stream-offline-link {
  color: var(--accent-ink);
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
}

.stream-offline-link:hover {
  color: var(--accent-ink);
  text-decoration: underline;
}

@media (max-width: 640px) {
  .hero-stream {
    width: 100%;
  }
}

/* Planner enhancements - champs de formulaire bien lisibles
   (fond sombre + texte clair, y compris les listes déroulantes) */
.planner-panel .panel-title h2 { margin: 0; }
.panel form input, .panel form select, .panel form textarea,
#page-admin .panel form input,
#page-admin .panel form select,
#page-admin .panel form textarea,
#page-org-coach form input,
#page-org-coach form select,
#page-org-coach form textarea,
#page-org-roster form input,
#page-org-roster form select,
#page-org-roster form textarea {
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 10px 12px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: normal;
  -webkit-appearance: none;
  appearance: none;
}

/* Texte des options des listes déroulantes - évite le blanc sur blanc.
   Pas limité à "form select" : le sélecteur de match et le select Agent du
   tableau de score coach vivent hors d'un <form> mais doivent être lisibles
   pareil. */
/* Même correction que pour le survol et le focus plus bas : la liste
   énumérait les pages, donc tout `select` hors d'un `<form>` sur une page
   absente gardait le gris système du navigateur - mesuré à 3.88:1, sous le
   seuil AA. C'était le cas du sélecteur de méthode de calcul d'Org-coach. */
.app :where(select) option,
.cart-drawer-overlay :where(select) option,
.beta-modal-overlay :where(select) option {
  /* Jeton opaque et non --nbk-black : en thème clair, un fond noir en dur
     laissait 176 options en texte sombre sur sombre. */
  background: var(--surface-solid);
  color: var(--text);
}

/* ===== APPARENCE DE BASE DES CHAMPS - la meme correction que pour le survol
   et le focus plus bas, appliquee cette fois au style de base.

   La regle ci-dessus enumere `.panel form` et quatre identifiants de page.
   Tout champ hors de cette liste gardait donc l'apparence native du
   navigateur : bordure grise de 2 px, coins carres, aucun padding. C'etait le
   cas du formulaire d'absence de l'espace Compte, qui vit dans
   `.account-indispo` - ni un `.panel`, ni un `<form>`.

   `:where()` ne compte pas dans la specificite : la regle pese exactement une
   classe (0-1-0). Elle passe donc devant les defauts du navigateur et derriere
   tout ce qui existe deja, `.panel form input` (0-1-2) comme les traitements
   sur mesure. Elle n'habille que les champs qui n'avaient rien.

   Cases a cocher, boutons radio, curseurs, selecteurs de fichier et de
   couleur sont exclus : `appearance: none` les effacerait sans rien mettre a
   la place - la meme erreur que celle corrigee plus bas pour les cases.

   Les `<select>` le sont aussi, pour la meme raison : `appearance: none`
   supprime la fleche du navigateur, et le site n'en dessine pas de
   remplacement. Vingt menus deroulants hors de la liste enumeree seraient
   devenus des boites muettes. Ils gardent donc leur rendu natif, comme
   avant - c'est une incoherence a traiter en lui donnant un chevron, pas en
   effacant celui du navigateur. */
.app :where(input:not([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="image"]), textarea),
.cart-drawer-overlay :where(input:not([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="image"]), textarea),
.beta-modal-overlay :where(input:not([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="image"]), textarea) {
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 10px 12px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--text-md);
  text-transform: none;
  letter-spacing: normal;
  -webkit-appearance: none;
  appearance: none;
}

/* Les listes deroulantes et leurs options sont exclues de la regle ci-dessus
   (leur fleche native disparaitrait), mais elles souffrent du meme defaut de
   typographie : c'est le plus gros contingent, 154 options et 24 listes. */
.app :where(select, option),
.cart-drawer-overlay :where(select, option),
.beta-modal-overlay :where(select, option) {
  font-family: var(--font-body);
  font-size: var(--text-md);
}

/* Rendu natif du calendrier et de l'horloge. `dark` etait force en dur, donc
   le selecteur s'ouvrait en noir sur une page blanche ; il suit le theme. */
.app :where(input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"]),
.panel form input[type="date"],
.panel form input[type="time"],
#page-admin .panel form input[type="date"],
#page-admin .panel form input[type="time"],
#page-org-coach form input[type="date"],
#page-org-coach form input[type="datetime-local"],
#page-org-coach form input[type="time"] {
  color-scheme: var(--field-scheme);
}

/* ===== ÉTAT DES CHAMPS - une seule règle pour tout le site =====
   Le survol et le focus étaient énumérés page par page (#page-admin,
   #page-org-coach, #page-org-roster, #page-tournoi). Toute page absente de la
   liste n'avait donc aucun anneau de focus lime : Compte, Planning, Mapban,
   Historique, Coach, Dashboard, Régie, Shop-admin et le tunnel de commande -
   c'est-à-dire la majorité des formulaires du site, dont celui où l'on paie.

   `:where()` ne compte pas dans la spécificité : la règle pèse exactement une
   classe + une pseudo-classe, assez pour battre les styles de base des champs
   (`.panel form input`, 0-1-2) et pas assez pour écraser un traitement sur
   mesure comme `.access-control input:focus` (0-2-1), qui reste prioritaire.

   Les trois portées couvrent le site entier : `.app` pour les pages, et les
   deux conteneurs de dialogue qui vivent hors de `.app` (panier, modales de
   commande). */
.app :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):hover,
.cart-drawer-overlay :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):hover,
.beta-modal-overlay :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):hover {
  border-color: var(--border-strong);
}

.app :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):focus,
.cart-drawer-overlay :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):focus,
.beta-modal-overlay :where(input:not([type="button"], [type="submit"], [type="reset"]), select, textarea):focus {
  outline: none;
  border-color: var(--accent-ink);
  box-shadow: var(--ring);
}

/* ===== CASES À COCHER ET BOUTONS RADIO =====
   La règle des champs ci-dessus applique `appearance: none` à tout `input`
   d'un formulaire de panneau, cases à cocher comprises - sans rien mettre à la
   place. Résultat : huit cases rendues en rectangles noirs de 26×22 px, sans
   coche ni état visible, dont le consentement obligatoire du formulaire de
   tournoi et l'acceptation des CGV. On ne pouvait pas voir ce qu'on avait coché.

   Spécificité 0-2-1, juste ce qu'il faut pour reprendre la main sur
   `.panel form input` (0-1-2) sans écraser un traitement sur mesure. */
.app input[type="checkbox"],
.app input[type="radio"],
.cart-drawer-overlay input[type="checkbox"],
.cart-drawer-overlay input[type="radio"],
.beta-modal-overlay input[type="checkbox"],
.beta-modal-overlay input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  display: inline-grid;
  place-content: center;
  width: 18px;
  height: 18px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border-strong);
  background: var(--field-bg);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.app input[type="checkbox"],
.cart-drawer-overlay input[type="checkbox"],
.beta-modal-overlay input[type="checkbox"] { border-radius: var(--radius); }

.app input[type="radio"],
.cart-drawer-overlay input[type="radio"],
.beta-modal-overlay input[type="radio"] { border-radius: 50%; }

.app input[type="checkbox"]:hover,
.app input[type="radio"]:hover,
.cart-drawer-overlay input[type="checkbox"]:hover,
.cart-drawer-overlay input[type="radio"]:hover,
.beta-modal-overlay input[type="checkbox"]:hover,
.beta-modal-overlay input[type="radio"]:hover {
  border-color: var(--accent-ink);
}

/* Coché : la case se remplit en lime et porte une coche noire ; le bouton
   radio garde son fond et prend un point lime. Deux formes distinctes, parce
   qu'une case et un radio ne promettent pas la même chose. */
.app input[type="checkbox"]:checked,
.cart-drawer-overlay input[type="checkbox"]:checked,
.beta-modal-overlay input[type="checkbox"]:checked {
  border-color: var(--accent-ink);
  background: var(--nbk-lime);
}

.app input[type="checkbox"]:checked::after,
.cart-drawer-overlay input[type="checkbox"]:checked::after,
.beta-modal-overlay input[type="checkbox"]:checked::after {
  content: '';
  width: 11px;
  height: 11px;
  background: var(--field-bg);
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6 9 17l-5-5' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.app input[type="radio"]:checked,
.cart-drawer-overlay input[type="radio"]:checked,
.beta-modal-overlay input[type="radio"]:checked {
  border-color: var(--accent-ink);
}

.app input[type="radio"]:checked::after,
.cart-drawer-overlay input[type="radio"]:checked::after,
.beta-modal-overlay input[type="radio"]:checked::after {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--nbk-lime);
}

/* Flèche personnalisée pour les selects - même portée, même raison. */
.app select,
.cart-drawer-overlay select,
.beta-modal-overlay select {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23ffffff' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 34px;
}

.btn {
  transition: transform 0.14s ease, box-shadow 0.14s ease, background 0.14s ease;
}
.btn:active { transform: translateY(1px) scale(0.997); }

.match-card {
  display:flex;justify-content:space-between;align-items:center;padding:12px;border-radius:var(--radius-card);background:linear-gradient(180deg, rgba(199, 243, 60, 0.03), transparent);
  border:1px solid rgba(199, 243, 60, 0.08);
  animation: cardIn 300ms ease;
}
.match-card .muted { color: var(--muted); font-size: var(--text-md); }

@keyframes cardIn {
  from { transform: translateY(6px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.match-item { list-style:none; }

/* ===== OVERLAY ===== */
.overlay-panel {
  position: relative;
  width: 100%;
  margin-top: 0;
  padding: 36px 44px 36px;
  border-radius: 36px;
  overflow: hidden;
  border: 1px solid rgba(0, 230, 118, 0.18);
  background: rgba(4, 10, 6, 0.95);
  backdrop-filter: blur(26px);
  box-shadow: 0 22px 90px rgba(0, 0, 0, 0.4);
}

.overlay-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at top left, rgba(0, 230, 118, 0.12), transparent 18%),
    radial-gradient(circle at top right, rgba(0, 255, 157, 0.10), transparent 15%);
  pointer-events: none;
}

.overlay-teams {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(300px, 1fr) auto minmax(300px, 1fr);
  align-items: center;
  gap: 18px;
}

.overlay-team {
  position: relative;
  border-radius: 30px;
  padding: 30px 38px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 150px;
  background: rgba(6, 14, 9, 0.96);
  border: 1px solid rgba(0, 230, 118, 0.14);
  box-shadow: inset 0 0 0 1px rgba(0, 255, 157, 0.03);
}

.overlay-team-label {
  display: block;
  margin-bottom: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: var(--text-xs);
}

.overlay-team h2 {
  margin: 0;
  font-size: clamp(2.3rem, 2.5vw, 3.2rem);
  letter-spacing: 0.12em;
}

/* Team logos float right next to the VS in the center */
.team-logo-wrap {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 130px;
  height: 130px;
  z-index: 3;
}

.overlay-team-a .team-logo-wrap {
  right: 8px;
}

.overlay-team-b .team-logo-wrap {
  left: 8px;
}

.team-logo {
  width: 110px;
  height: 110px;
  object-fit: contain;
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  background: rgba(4, 10, 6, 0.9);
  padding: 6px;
  border: 1px solid rgba(0, 230, 118, 0.25);
}

.overlay-ban-list {
  display: flex;
  gap: 3px;
  flex-wrap: wrap;
  justify-content: center;
  overflow-x: auto;
  padding-bottom: 12px;
}

.overlay-ban-list::-webkit-scrollbar {
  height: 10px;
}

.overlay-ban-list::-webkit-scrollbar-thumb {
  background: rgba(0, 230, 118, 0.3);
  border-radius: 999px;
}

.overlay-vs {
  position: relative;
  z-index: 1;
  color: var(--accent-ink);
  font-size: var(--text-base);
  font-weight: 700;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  text-align: center;
  text-shadow: 0 0 20px rgba(0, 230, 118, 0.5);
}

.overlay-ban {
  position: relative;
  z-index: 1;
  margin-top: 28px;
  border-radius: 30px;
  padding: 28px 32px;
  background: rgba(6, 14, 9, 0.98);
  border: 1px solid rgba(0, 230, 118, 0.14);
}

.overlay-ban-title {
  margin: 0 0 16px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: var(--text-md);
}

.overlay-ban-list {
  display: flex;
  gap: 3px;
  overflow-x: auto;
  padding-bottom: 12px;
}

.overlay-ban-list::-webkit-scrollbar {
  height: 8px;
}

.overlay-ban-list::-webkit-scrollbar-thumb {
  background: rgba(0, 230, 118, 0.2);
  border-radius: 999px;
}

.overlay-ban-item {
  position: relative;
  min-height: 500px;
  width: 370px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 18px;
  color: var(--text);
  background-color: #050a06;
  background-size: cover;
  background-position: center;
  box-shadow: inset 0 0 0 1px rgb(var(--ink-rgb) / 0.05);
  transition: transform 0.35s ease, box-shadow 0.35s ease;
  filter: saturate(1.25) brightness(1.1);
  flex: 0 0 370px;
}

.overlay-ban-item.status-pending {
  background: linear-gradient(180deg, rgba(4, 8, 5, 0.08) 0%, rgba(3, 6, 4, 0.12) 100%);
  box-shadow: inset 0 0 0 1px rgb(var(--ink-rgb) / 0.04);
}

.overlay-ban-item.status-pending::before {
  background: linear-gradient(180deg, rgba(0,0,0,0.03) 0%, rgba(0,0,0,0.18) 100%);
}

.overlay-ban-item.status-pending .overlay-card-label {
  color: rgba(234, 255, 241, 0.7);
}

.overlay-ban-item.animate {
  animation: overlay-pop 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes overlay-pop {
  0% { transform: scale(0.92); filter: brightness(0.8); }
  40% { transform: scale(1.04); filter: brightness(1.15); }
  100% { transform: scale(1); filter: brightness(1); }
}

.overlay-ban-item::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.02) 0%, rgba(0,0,0,0.14) 100%);
}

.overlay-ban-item .overlay-ban-header,
.overlay-ban-item .overlay-ban-meta {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 4px;
  justify-items: center;
  text-align: center;
  width: 100%;
}

.overlay-ban-item .overlay-card-label {
  font-size: var(--text-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(234, 255, 241, 0.65);
  letter-spacing: 0.26em;
}

.overlay-ban-item .overlay-card-title {
  font-size: clamp(1.2rem, 1.6vw, 1.8rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.85);
}

.overlay-ban-item .overlay-card-subtitle {
  font-size: var(--text-sm);
  color: rgba(234, 255, 241, 0.72);
  letter-spacing: 0.12em;
}

.overlay-ban-item.status-pick {
  box-shadow: inset 0 0 0 3px rgba(0, 230, 118, 0.75);
}

.overlay-ban-item.status-pick::before {
  background: linear-gradient(180deg, rgba(0, 230, 118, 0.2) 0%, rgba(0, 150, 80, 0.14) 45%, rgba(0, 20, 10, 0.45) 100%);
}

/* Red gradient overlay + cross for banned cards on the overlay */
.overlay-ban-item.status-ban::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(200, 20, 35, 0.25) 0%, rgba(150, 10, 25, 0.18) 45%, rgba(20, 2, 4, 0.45) 100%);
  z-index: 1;
}

.overlay-ban-item.status-ban::after {
  content: "×";
  position: absolute;
  inset: 20px;
  /* Hors échelle : taille d'affichage unique, pas un pas de système. */
  font-size: 4.4rem;
  line-height: 1;
  color: rgba(255, 25, 45, 0.98);
  display: flex;
  align-items: center;
  justify-content: center;
  text-shadow: 0 0 20px rgba(0, 0, 0, 0.9), 0 0 45px rgba(255, 30, 50, 0.85);
  transform: rotate(25deg) scale(1);
  opacity: 1;
  z-index: 2;
}

.overlay-ban-item.animate.status-ban::after {
  animation: overlay-ban-cross 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes overlay-ban-cross {
  0% { opacity: 0; transform: scale(0.2) rotate(-40deg); filter: brightness(2); }
  55% { opacity: 1; transform: scale(1.18) rotate(10deg); filter: brightness(1.4); }
  100% { opacity: 1; transform: scale(1) rotate(25deg); filter: brightness(1); }
}

/* Team/side badge on pick / decider */
.overlay-ban-item.status-pick .overlay-card-subtitle,
.overlay-ban-item.status-decider .overlay-card-subtitle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 10px 16px;
  border-radius: 14px;
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #001a0c;
  background: linear-gradient(135deg, rgba(0, 230, 118, 0.95), rgba(0, 255, 157, 0.8));
  border: 1px solid rgb(var(--ink-rgb) / 0.25);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), 0 0 18px rgba(0, 230, 118, 0.4);
}

.overlay-ban-item.animate.status-pick .overlay-card-subtitle,
.overlay-ban-item.animate.status-decider .overlay-card-subtitle {
  animation: overlay-team-badge 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.overlay-ban-item.status-decider .overlay-card-subtitle {
  background: linear-gradient(135deg, rgba(0, 255, 157, 0.98), rgba(0, 230, 118, 0.9));
  color: #001a0c;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), 0 0 22px rgba(0, 230, 118, 0.6);
}

@keyframes overlay-team-badge {
  0% { opacity: 0; transform: translateY(12px) scale(0.7); }
  60% { opacity: 1; transform: translateY(-3px) scale(1.05); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* ===== PICK CHOICE ===== */
.pick-choice {
  margin-top: 24px;
  padding: 18px 22px;
  border-radius: 22px;
  background: rgba(6, 12, 8, 0.94);
  border: 1px solid rgba(199, 243, 60, 0.12);
}

/* !important is deliberate: .hidden must always win regardless of source
   order against any other single-class rule that sets its own `display`
   (e.g. .admin-layout { display: flex }) - without it, whichever rule
   happens to be declared later in this file wins, which silently left the
   Admin panel content visible to logged-out visitors (only the "reserved to
   Admin" message was gated, not the actual content behind it). */
.hidden {
  display: none !important;
}

.pick-choice.hidden {
  display: none;
}

/* ===== ADMIN LAYOUT (sidebar navigation) ===== */
.admin-layout {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

#page-planning .admin-layout,
#page-coach .admin-layout {
  margin-top: 8px;
  width: 100%;
}

.admin-sidebar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 0 0 220px;
  position: sticky;
  top: 88px;
  padding: 10px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
}

.admin-sidebar-link {
  text-align: left;
  padding: 10px 14px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}

.admin-sidebar-group-title {
  padding: 10px 14px 2px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.7;
}

.admin-sidebar-group-title:first-child {
  padding-top: 0;
}

.admin-sidebar-link:hover {
  color: var(--text);
  background: var(--surface-2);
}

.admin-sidebar-link.active {
  background: var(--nbk-lime);
  color: var(--nbk-black);
}

.admin-sections {
  flex: 1;
  min-width: 0;
}

.admin-section {
  display: none;
}

.admin-section.active {
  display: block;
}

@media (max-width: 900px) {
  .admin-layout {
    flex-direction: column;
  }

  .admin-sidebar {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
  }
}

/* ===== ACCESS / ADMIN ===== */
.access-control {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.access-control input {
  flex: 1;
  min-width: 180px;
  border: 1px solid rgba(199, 243, 60, 0.2);
  border-radius: var(--radius);
  padding: 16px 18px;
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
}

.access-control input:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.9);
  box-shadow: var(--ring);
  transform: translateY(-1px);
}

.access-control button {
  min-width: 140px;
  padding: 16px 18px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, #00b35f, #007a3d);
  color: #fff;
  border: none;
  box-shadow: 0 18px 30px rgba(0, 0, 0, 0.24);
  transition: transform 0.25s ease, box-shadow 0.25s ease, opacity 0.25s ease;
}

.access-control button:hover {
  transform: translateY(-2px);
  box-shadow: 0 22px 32px rgba(199, 243, 60, 0.3);
}

.access-control button:active {
  transform: translateY(0);
}

.access-message {
  margin-top: 12px;
  color: var(--text);
  font-weight: 600;
  letter-spacing: 0.02em;
}

.access-message.error {
  color: #ff6b6b;
}

.access-message.success {
  color: #7dff97;
}

.access-panel {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: linear-gradient(145deg, rgba(8, 16, 10, 0.96), rgba(4, 8, 5, 0.98));
  transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease;
}

.access-panel.success {
  border-color: rgba(125, 255, 151, 0.8);
  box-shadow: 0 0 0 2px rgba(125, 255, 151, 0.12), 0 24px 60px rgba(0, 0, 0, 0.32);
}

.access-panel.error {
  border-color: rgba(255, 107, 107, 0.9);
  animation: access-shake 0.45s ease;
}

@keyframes access-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-10px); }
  40% { transform: translateX(10px); }
  60% { transform: translateX(-8px); }
  80% { transform: translateX(8px); }
}

.access-panel.unlocking {
  animation: access-unlock 0.8s ease forwards;
}

@keyframes access-unlock {
  0% { opacity: 1; transform: scale(1); }
  40% { opacity: 1; transform: scale(1.03); filter: brightness(1.4); }
  60% { opacity: 0.95; transform: scale(1.02); }
  100% { opacity: 0; transform: scale(1.08); filter: brightness(1); }
}

/* Success checkmark shown while the panel unlocks */
.access-panel.unlocking::after {
  content: "✓";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0);
  /* Hors échelle : taille d'affichage unique, pas un pas de système. */
  font-size: 5rem;
  font-weight: 800;
  color: #30ff8a;
  text-shadow: 0 0 30px rgba(199, 243, 60, 0.9), 0 0 70px rgba(199, 243, 60, 0.6);
  z-index: 5;
  pointer-events: none;
  animation: unlock-check 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes unlock-check {
  0% { transform: translate(-50%, -50%) scale(0) rotate(-90deg); opacity: 0; }
  45% { transform: translate(-50%, -50%) scale(1.3) rotate(0deg); opacity: 1; }
  70% { transform: translate(-50%, -50%) scale(0.9) rotate(0deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1) rotate(0deg); opacity: 1; }
}

/* Enhanced unlock success glow for Admin / Régie panels */
.access-panel.success {
  border-color: rgba(125, 255, 151, 0.9);
  box-shadow:
    0 0 0 2px rgba(125, 255, 151, 0.15),
    0 0 18px rgba(199, 243, 60, 0.35),
    0 0 60px rgba(199, 243, 60, 0.25),
    0 24px 60px rgba(0, 0, 0, 0.32);
}

.access-panel.success::after {
  content: "✔";
  position: absolute;
  top: 18px;
  right: 22px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: linear-gradient(135deg, #c7f33c, #e1f2ae);
  color: #001a0c;
  font-size: var(--text-xl);
  font-weight: 800;
  box-shadow: 0 0 24px rgba(199, 243, 60, 0.6);
  animation: unlock-check-corner 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes unlock-check-corner {
  0% { opacity: 0; transform: scale(0.2) rotate(-30deg); }
  60% { opacity: 1; transform: scale(1.2) rotate(8deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

.pick-choice-text {
  color: var(--text);
  margin-bottom: 16px;
  font-size: var(--text-base);
}

.pick-choice-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.side-selector {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

/* ----- Side (Attaque / Défense) picker cards ----- */
.side-selector .side-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 150px;
  padding: 18px 20px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text);
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}

.side-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 30% 20%, rgba(199, 243, 60, 0.18), transparent 40%);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.side-card input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.side-card:hover {
  border-color: var(--accent-ink);
}

.side-card:has(input:checked) {
  border-color: var(--accent-ink);
  background: var(--surface-2);
  animation: side-select-pop 0.3s var(--ease);
}

.side-card:has(input:checked)::before {
  opacity: 1;
}

.side-card-icon {
  font-size: var(--text-2xl);
  line-height: 1;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.4));
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.side-card:has(input:checked) .side-card-icon {
  transform: translateY(-3px) scale(1.15);
  animation: side-icon-bounce 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.side-card-label {
  font-weight: 800;
  font-size: var(--text-base);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.side-card-sub {
  color: var(--muted);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
}

/* Attack card accent */
.side-attack:has(input:checked) {
  border-color: #ff8a3c;
  background: linear-gradient(160deg, rgba(255, 138, 60, 0.2), rgba(0, 0, 0, 0.3));
  box-shadow: 0 0 0 2px rgba(255, 138, 60, 0.35), 0 0 30px rgba(255, 138, 60, 0.3), 0 18px 40px rgba(0, 0, 0, 0.3);
}

/* Defense card accent */
.side-defense:has(input:checked) {
  border-color: #4aa3ff;
  background: linear-gradient(160deg, rgba(74, 163, 255, 0.2), rgba(0, 0, 0, 0.3));
  box-shadow: 0 0 0 2px rgba(74, 163, 255, 0.35), 0 0 30px rgba(74, 163, 255, 0.3), 0 18px 40px rgba(0, 0, 0, 0.3);
}

@keyframes side-select-pop {
  0% { transform: scale(0.96); }
  50% { transform: scale(1.04); }
  100% { transform: scale(1); }
}

@keyframes side-icon-bounce {
  0% { transform: translateY(0) scale(1); }
  40% { transform: translateY(-6px) scale(1.2); }
  100% { transform: translateY(-3px) scale(1.15); }
}

/* ===== LIVE OVERLAY (AUTO) - companion-app-fed in-game overlay ===== */
.live-overlay-tools-panel .live-overlay-status {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 14px;
  color: var(--muted);
  font-size: var(--text-md);
}

.live-overlay-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 80, 80, 0.85);
  box-shadow: 0 0 8px rgba(255, 80, 80, 0.5);
  flex: 0 0 auto;
}

.live-overlay-dot.connected {
  background: rgba(0, 230, 118, 0.9);
  box-shadow: 0 0 10px rgba(0, 230, 118, 0.6);
}

.live-overlay-hint {
  margin-top: 14px;
  color: var(--muted);
  font-size: var(--text-md);
  line-height: 1.5;
}

.live-overlay-hint code {
  background: rgb(var(--ink-rgb) / 0.08);
  padding: 2px 6px;
  border-radius: 6px;
}

.overlay-live-panel {
  position: relative;
  width: 100%;
  margin-top: 20px;
  padding: 32px 40px;
  border-radius: 36px;
  overflow: hidden;
  border: 1px solid rgba(0, 230, 118, 0.18);
  background: rgba(4, 10, 6, 0.95);
  backdrop-filter: blur(26px);
  box-shadow: 0 22px 90px rgba(0, 0, 0, 0.4);
  text-align: center;
}

.live-phase-banner {
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: 0.3em;
  font-size: var(--text-base);
  font-weight: 700;
  text-shadow: 0 0 20px rgba(0, 230, 118, 0.5);
}

.live-map-mode {
  margin-top: 8px;
  color: var(--muted);
  font-size: var(--text-base);
  letter-spacing: 0.08em;
}

.live-teams {
  margin-top: 24px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.live-team {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 18px;
  border-radius: 24px;
  background: rgba(6, 14, 9, 0.96);
  border: 1px solid rgba(0, 230, 118, 0.14);
}

.live-team-blue {
  border-color: rgba(80, 170, 255, 0.35);
}

.live-team-red {
  border-color: rgba(255, 90, 90, 0.35);
}

.live-player-slot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 10px;
  border-radius: 14px;
  background: rgb(var(--ink-rgb) / 0.03);
}

.live-player-slot.empty {
  opacity: 0.25;
}

.live-player-agent-icon,
.live-player-agent-icon-placeholder {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  object-fit: cover;
  background: rgb(var(--ink-rgb) / 0.08);
  flex: 0 0 auto;
}

.live-player-name {
  font-size: var(--text-base);
  letter-spacing: 0.02em;
  text-align: left;
  flex: 1 1 auto;
}

.live-player-slot.dead {
  opacity: 0.4;
}

.live-player-slot.dead .live-player-name {
  text-decoration: line-through;
}

.live-player-kda {
  font-size: var(--text-sm);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

.live-player-money {
  font-size: var(--text-sm);
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
  min-width: 3.5em;
  text-align: right;
}

.live-score {
  margin-top: 6px;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: 0.04em;
}

.live-score-blue { color: #5aa0ff; }
.live-score-red { color: #ff5a5a; }
.live-score-sep { color: var(--muted); }

.live-kill-feed {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  min-height: 0;
}

.live-kill-entry {
  font-size: var(--text-md);
  padding: 4px 12px;
  border-radius: 10px;
  background: rgba(6, 14, 9, 0.85);
  border: 1px solid rgba(0, 230, 118, 0.12);
}

.live-kill-killer { color: #fff; font-weight: 600; }
.live-kill-victim { color: var(--muted); }
.live-kill-weapon { color: var(--muted); font-size: 0.8em; }

.live-kill-hs {
  color: #ffcf4d;
  font-weight: 700;
  font-size: 0.75em;
}

/* Two OBS sources share body.obs-overlay-mode (?overlay=true#obs) but must
   never both render: the classic map-ban one, and this one, distinguished
   by .obs-live-mode (?liveOverlayToken=… - see checkObsOverlayMode()). The
   base .hidden class alone can't do this job here, since the full-bleed
   rules below already override display with !important. */
body.obs-overlay-mode:not(.obs-live-mode) #page-regie .overlay-live-panel {
  display: none !important;
}

body.obs-overlay-mode.obs-live-mode #page-regie .overlay-live-panel {
  display: flex !important;
  flex-direction: column;
  justify-content: center;
  height: 100vh !important;
  width: 100vw !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  margin: 0 !important;
}

@media (max-width: 720px) {
  .live-teams {
    grid-template-columns: 1fr;
  }
}

/* ===== MAP CARDS ===== */
.map-card.pick-candidate {
  box-shadow: inset 0 0 0 3px rgba(199, 243, 60, 0.6);
}

.overlay-ban-item.status-decider {
  box-shadow: inset 0 0 0 3px rgba(0, 255, 157, 0.75);
}

.overlay-ban-item.status-decider::before {
  background: linear-gradient(180deg, rgba(255, 200, 0, 0.2) 0%, rgba(220, 150, 0, 0.14) 45%, rgba(20, 14, 0, 0.45) 100%);
}

@media (max-width: 980px) {
  .overlay-teams {
    grid-template-columns: 1fr;
  }

  .overlay-vs {
    margin: 0 auto;
  }
}

@media (max-width: 720px) {
  .app {
    padding: 18px var(--app-pad-x) 24px;
  }
  /* `.hero` retiré : le hero d’accueil est devenu le monde scroll-scrubbé et
     les en-têtes de pages intérieures sont passées à .page-hero, qui porte son
     propre rythme. Le rayon suit le jeton plutôt que 24px : un panneau n’a pas
     de raison de changer de forme selon la largeur de la fenêtre. */
  .overlay-panel,
  .panel {
    padding: 20px 22px;
    border-radius: var(--radius-card);
  }
  .overlay-ban-item {
    width: 200px;
  }
}

#page-regie .access-panel,
#page-regie .admin-panel,
#page-regie .overlay-panel {
  text-align: center;
}

#page-regie .admin-grid {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.admin-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  margin-top: 18px;
}

.admin-grid label {
  display: grid;
  gap: 10px;
  color: var(--text);
}

.admin-grid input {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  border: 1px solid rgba(199, 243, 60, 0.12);
  border-radius: var(--radius);
  background: rgb(var(--ink-rgb) / 0.04);
  color: var(--text);
  padding: 0.95rem 1rem;
}

@media (max-width: 600px) {
  .admin-grid {
    grid-template-columns: 1fr;
  }
}

.admin-grid input:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.5);
  box-shadow: var(--ring);
}

.rules-panel ul {
  margin: 0;
  padding-left: 18px;
  color: var(--muted);
}

.rules-panel li {
  margin-bottom: 8px;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.control {
  display: grid;
  gap: 10px;
}

.control label {
  color: var(--muted);
  font-size: var(--text-base);
}

.control select {
  appearance: none;
  border: 1px solid rgba(199, 243, 60, 0.16);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  background: rgb(var(--ink-rgb) / 0.04);
  color: var(--text);
  box-shadow: inset 0 0 0 1px rgba(225, 242, 174, 0.02);
}

.control select:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.6);
  box-shadow: var(--ring);
}

/* ===== MAPS GRID ===== */
.maps-grid {
  display: grid;
  gap: 3px;
  margin-top: 24px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.map-card {
  position: relative;
  width: 100%;
  min-width: 0;
  aspect-ratio: 16 / 9;
  min-height: 260px;
  padding: 24px;
  overflow: hidden;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: #050a06;
  cursor: pointer;
  transition: border-color 0.2s var(--ease);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}

.map-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.25) 100%);
  opacity: 1;
  transition: filter 0.3s var(--ease), opacity 0.3s var(--ease);
}

.map-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: none;
  pointer-events: none;
  opacity: 0;
}

.map-card:hover {
  border-color: var(--accent-ink);
  z-index: 2;
}

.map-card.banned {
  border-color: var(--border);
}

.map-card.banned::before {
  filter: grayscale(1) brightness(0.6);
  opacity: 0.35;
}

.map-card.banned .map-card__label {
  color: #ff8095;
}

/* Banned overlay - keep map image visible */
.map-card.banned {
  background-image: linear-gradient(180deg, rgba(255, 45, 60, 0.10) 0%, rgba(150, 8, 25, 0.18) 45%, rgba(4, 5, 6, 0.55) 100%);
}
.map-card.banned .map-card__meta::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-card);
  background: linear-gradient(180deg, rgba(255, 45, 60, 0.08) 0%, rgba(150, 8, 25, 0.15) 45%, rgba(4, 5, 6, 0.5) 100%);
  z-index: -1;
}

/* Big animated cross that pops in */
.map-card.banned::after {
  content: "×";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Hors échelle : taille d'affichage unique, pas un pas de système. */
  font-size: 7.5rem;
  font-weight: 200;
  line-height: 1;
  color: rgba(255, 60, 80, 0.95);
  text-shadow: 0 0 28px rgba(255, 30, 50, 0.95), 0 0 65px rgba(255, 30, 50, 0.55);
  background: radial-gradient(circle at center, rgba(255, 50, 70, 0.22) 0%, transparent 58%);
  opacity: 0;
  animation: ban-cross 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  pointer-events: none;
  z-index: 1;
}

@keyframes ban-cross {
  0% { opacity: 0; transform: scale(0.2) rotate(-40deg); filter: brightness(2); }
  55% { opacity: 1; transform: scale(1.18) rotate(6deg); filter: brightness(1.4); }
  100% { opacity: 1; transform: scale(1) rotate(25deg); filter: brightness(1); }
}

.map-card.ban-anim {
  animation: ban-pulse 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes ban-pulse {
  0% { transform: translateY(0) scale(1); filter: brightness(1); }
  35% { transform: translateY(-8px) scale(1.04); filter: brightness(1.35) saturate(1.4); }
  70% { transform: translateY(0) scale(0.97); filter: brightness(0.9); }
  100% { transform: translateY(0) scale(1); filter: brightness(1); }
}

.map-card .map-card__meta {
  position: relative;
  z-index: 2;
  padding-bottom: 10px;
  text-align: center;
  width: 100%;
}

.map-card .map-card__label {
  display: inline-block;
  margin-bottom: 10px;
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: var(--text-xs);
}

.map-card h3 {
  margin: 0 0 6px;
  font-size: clamp(1.5rem, 2.4vw, 2.6rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.85);
}

.map-card p {
  margin: 0;
  color: #c9f5d8;
  font-size: var(--text-base);
}

.map-card.ascent::before { background-image: url('https://media.valorant-api.com/maps/7eaecc1b-4337-bbf6-6ab9-04b8f06b3319/stylizedbackgroundimage.png'); }
.map-card.breeze::before { background-image: url('https://media.valorant-api.com/maps/2fb9a4fd-47b8-4e7d-a969-74b4046ebd53/stylizedbackgroundimage.png'); }
.map-card.haven::before { background-image: url('https://media.valorant-api.com/maps/2bee0dc9-4ffe-519b-1cbd-7fbe763a6047/stylizedbackgroundimage.png'); }
.map-card.lotus::before { background-image: url('https://media.valorant-api.com/maps/2fe4ed3a-450a-948b-6d6b-e89a78e680a9/stylizedbackgroundimage.png'); }
.map-card.split::before { background-image: url('https://media.valorant-api.com/maps/d960549e-485c-e861-8d71-aa9d1aed12a2/stylizedbackgroundimage.png'); }
.map-card.summit::before { background-image: url('https://media.valorant-api.com/maps/756da597-416b-c0f2-f47b-afbdf28670bc/stylizedbackgroundimage.png'); }
.map-card.sunset::before { background-image: url('https://media.valorant-api.com/maps/92584fbe-486a-b1b2-9faa-39b0f486b498/stylizedbackgroundimage.png'); }

.panel-title {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

/* .panel-title and .section-heading are the site's two title primitives -
   roughly half the pages use each. They carried different type scales, so
   Tournoi/Historique/Admin read a step smaller than Équipe/Boutique for no
   reason other than which wrapper they happened to use. Same scale for
   both. */
.panel-title h2 {
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  line-height: 1;
  letter-spacing: -0.028em;
}

/* Même filet que .section-heading h2::after : c'était la dernière différence
   d'ornement entre les deux primitifs. Pour qu'il ait de la place où courir,
   le bloc de titre prend la largeur restante - ce qui se trouve à droite du
   .panel-title (souvent un bouton) reste calé au bout. */
/* `> :first-child` et pas `> div:first-child` : sur 34 .panel-title, 29
   portent le <h2> en enfant direct et 5 l'enveloppent dans un <div>. Les deux
   formes doivent prendre la largeur restante, sinon le filet se réduit à son
   minimum dans la majorité des cas. */
.panel-title > :first-child {
  flex: 1;
  min-width: 0;
}

.panel-title h2::after {
  content: '';
  flex: 1;
  height: 1px;
  min-width: 24px;
  background: linear-gradient(90deg, rgba(199, 243, 60, 0.45), rgba(199, 243, 60, 0));
}

/* Sub-line under a panel title: was plain body text at full contrast,
   competing with the title it explains. */
.panel-title > div > p {
  margin: 10px 0 0;
  max-width: 68ch;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* Le soulignement de 64 px propre au Tournoi est remplacé par le filet
   commun ci-dessus - c'était la même intention, écrite deux fois. */

/* ===== MISE EN PAGE DES FORMULAIRES DE PANNEAU =====
   Les formulaires d'Admin, de Régie, de Coach et des pages org portaient leur
   mise en page dans 70 attributs `style` écrits à la main, pour 27 déclarations
   distinctes dont onze répétitions du même `display:flex;flex-direction:column`.
   Trois formulaires de création de match étaient recopiés à l'identique d'une
   page à l'autre.

   Les classes ci-dessous reprennent ces déclarations telles quelles - même
   propriétés, mêmes valeurs - pour que la conversion ne change rien au rendu.
   L'intérêt n'est pas cosmétique : tant que ces règles vivaient dans le HTML,
   aucune ne pouvait être ajustée depuis la feuille de style, et rien ne pouvait
   les rendre responsives. */
.form-row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.form-row-wrap { flex-wrap: wrap; }
.form-row-next { margin-top: 10px; }
.form-row-next-lg { margin-top: 16px; }

.form-field {
  display: flex;
  flex-direction: column;
}

.form-field-grow { flex: 1; min-width: 160px; }
.form-field-wide { flex: 1; min-width: 180px; }

.form-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.form-textarea {
  width: 100%;
  margin-top: 10px;
  min-height: 60px;
}

/* Zone de retour d'un formulaire (« Match créé », « Erreur… ») : gris, pour
   ne pas parler plus fort que le formulaire lui-même tant qu'elle est vide. */
.form-status { color: var(--muted); }

.form-gap-sm { margin-top: 8px; }
.form-gap-md { margin-top: 12px; }
.form-gap-xl { margin-top: 40px; }
.form-gap-none { margin-top: 0; }
.form-gap-sm-below { margin-bottom: 8px; }

.form-subhead { margin: 0 0 6px; }

.form-input-narrow { max-width: 120px; }
.form-input-medium { max-width: 160px; }

/* Champs de code (code d'accès boutique, code d'invitation d'organisation) :
   saisis en majuscules parce que c'est ainsi qu'ils sont communiqués. */
.form-input-code { text-transform: uppercase; }

/* Colonne d'authentification qui prend le double de la place : e-mail et mot
   de passe à côté de champs courts. */
.auth-field-wide { flex: 2; }

/* Éléments uniques : une règle sur l'identifiant plutôt qu'une classe inventée
   pour une seule occurrence. */
#adminDevTestEmail { width: 220px; }

#orgRosterForm { max-width: 360px; }

#compteTotpQr {
  max-width: 180px;
  border-radius: var(--radius-card);
}

/* ===== PAGES LÉGALES =====
   Quatre documents longs (CGU, CGV, mentions, confidentialité) qu'on ne lit
   jamais en entier : on y cherche une clause. Leurs titres de section
   pesaient exactement le même poids que le corps de texte - un blanc, un gras,
   et rien d'autre - donc le document ne se parcourait pas du regard, il se
   lisait ligne à ligne. C'est le seul vrai défaut de ces pages. */
.legal-content {
  /* Mesure en `ch` plutôt qu'en pixels : c'est la longueur de ligne qui rend
     un texte lisible, et elle se compte en caractères, pas en écran. */
  max-width: 68ch;
  margin-top: 24px;
  color: var(--text-secondary);
  line-height: 1.7;
}

.legal-content h3 {
  position: relative;
  color: var(--text);
  margin: 42px 0 12px;
  padding-top: 18px;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

/* Filet lime au-dessus de chaque section : il découpe le document en blocs
   repérables au défilement rapide, sans ajouter de bruit dans le texte. */
.legal-content h3::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 32px;
  height: 2px;
  background: var(--nbk-lime);
}

.legal-content h3:first-child {
  margin-top: 0;
}

.legal-content p {
  margin: 0 0 14px;
}

.legal-content ul {
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
}

.legal-content li {
  position: relative;
  margin-bottom: 8px;
  padding-left: 20px;
}

/* Puce lime plutôt que le disque natif : dans une énumération de clauses, la
   puce sert de point d'accroche pour l'œil qui balaie. */
.legal-content li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.7em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--nbk-lime);
  opacity: 0.7;
}

.legal-content a {
  color: var(--accent-ink);
}

.toggle-text a {
  color: var(--accent-ink);
}

.action-info {
  margin: 12px 0 0;
  color: var(--muted);
}

.turn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.8rem 1rem;
  border-radius: 999px;
  border: 1px solid rgba(199, 243, 60, 0.42);
  background: rgba(199, 243, 60, 0.12);
  color: var(--status-ok);
  font-weight: 700;
  box-shadow: 0 0 18px rgba(199, 243, 60, 0.15);
}

.ban-summary {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 26px;
  margin-top: 24px;
}

.team-card {
  position: relative;
  padding: 24px 26px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
  overflow: hidden;
}

.team-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--accent-gradient);
}

/* Scoped to the Équipe page specifically - .team-card is reused unstyled by
   the map-ban summary panel, which must not pick up this accent/badge. */
.team-panel .team-card {
  position: relative;
  overflow: hidden;
}

.team-panel .team-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--nbk-lime), transparent 75%);
}

.team-header {
  position: relative;
}

.team-header-rule {
  height: 2px;
  width: 64px;
  background: var(--nbk-lime);
  margin: 16px 0 22px;
  transform-origin: left;
}

/* Stat bar: hairline-separated columns rather than three loose text pairs,
   so the counts read as one deliberate strip of numbers. */
.team-header-stats {
  display: flex;
  gap: 0;
  flex-wrap: wrap;
}

.team-header-stat {
  padding: 0 26px;
  border-left: 1px solid var(--border);
}

.team-header-stat:first-child {
  padding-left: 0;
  border-left: none;
}

.team-header-stat b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--accent-ink);
}

.team-header-stat span {
  display: block;
  margin-top: 3px;
  font-size: var(--text-3xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.team-card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* Count sits with the title instead of being pushed to the far edge by
   space-between, where a wide card left it stranded metres from the name it
   belongs to. */
.team-panel .team-card-top {
  justify-content: flex-start;
  gap: 14px;
}

/* Team name carried the same weight as the surrounding body copy, so each
   squad read as a paragraph heading rather than the start of a section.
   Display face, larger, tighter - and a short lime rule beneath to anchor
   it, echoing .team-header-rule at the page level. */
.team-panel .team-card-top h3 {
  position: relative;
  margin: 0 0 12px;
  padding-bottom: 10px;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

.team-panel .team-card-top h3::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 34px;
  height: 2px;
  background: var(--nbk-lime);
}

.team-card-count {
  font-family: var(--font-display);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 4px 11px;
}

.team-card + .team-card {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

.team-card h2 {
  margin: 0 0 10px;
  text-transform: uppercase;
}

.team-note {
  margin: 0 0 16px;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
}

/* A team with no coach assigned used to still render its label, leaving a
   dangling "Coach :" with nothing after it. Collapse the whole line instead
   of showing a half-finished one. */
.team-note-coach:has(span:empty) {
  display: none;
}

.team-a,
.team-b {
  background: var(--surface-1);
  border-color: var(--border);
}

/* ===== PLAYER CARDS (Équipe) - grid of square-ish cards, agent portrait as
   background art, role/tracker/rank revealed on hover or keyboard focus. ===== */
.player-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 18px;
}

/* Two per row on phones. At the 190px track above, a 375px screen fits a
   single column, and a portrait-ratio card that wide is ~500px tall - one
   player per screenful, so reading a 7-man roster became a long scroll. */
@media (max-width: 640px) {
  .player-grid {
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: 10px;
  }

  .player-card-monogram {
    font-size: var(--text-4xl);
  }

  .player-card-main {
    padding: 10px 9px 11px;
  }

  .player-card-name {
    font-size: var(--text-xs);
  }

  /* Dropped on phones: there is no hover there, so it is the one element in
     the bottom block that earns nothing on touch, and at this card width it
     would crowd the role badge onto a second line. Tapping the card still
     opens the profile. */
  .player-card-hint {
    display: none;
  }

  /* Same reason: a name plus three stream icons cannot share a 112px row, so
     they wrapped to a second line - and only on the players who have them,
     leaving the grid with visibly uneven card footers. The profile that
     opens on tap carries the same links. */
  .player-card .roster-stream-icons {
    display: none;
  }

  /* Off entirely on phones. There is no real hover to trigger it, but touch
     browsers still fire :hover on tap, and its agent/rank/tracker rows do
     not fit a 112px card - they wrapped over the index and the name. Tapping
     opens the profile modal, which carries all of it and more. */
  .player-card-hover {
    display: none;
  }
}

.player-card {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: linear-gradient(180deg, rgb(var(--ink-rgb) / 0.06), rgba(0, 0, 0, 0.9)), var(--surface-2);
  color: var(--text);
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}

/* Hairline highlight along the top edge - catches the light the way a
   physical card would, so the frame stops reading as a flat cutout against
   the black page. */
.player-card::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgb(var(--ink-rgb) / 0.22) 28%, rgb(var(--ink-rgb) / 0.22) 72%, transparent);
  z-index: 4;
  pointer-events: none;
}

/* Portrait layer. Sits under the name/role block and the hover panel, with
   the monogram behind it as the fallback when there is no agent linked or
   the third-party portrait fails to load (see renderPlayerCard). */
.player-card-media {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.player-card-portrait {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  transition: transform 0.35s var(--ease);
}

.player-card:hover .player-card-portrait,
.player-card:focus-visible .player-card-portrait {
  transform: scale(1.04);
}

/* Large, centred and low-contrast: reads as deliberate cover art for a
   player with no portrait yet, rather than the small floating chip in dead
   space it used to be. Outlined rather than filled so it sits as a graphic
   mark instead of a washed-out letter. */
.player-card-monogram {
  font-family: var(--font-display);
  /* Hors échelle : taille d'affichage unique, pas un pas de système. */
  font-size: 5rem;
  font-weight: 700;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgb(var(--ink-rgb) / 0.16);
  user-select: none;
  transition: -webkit-text-stroke-color 0.25s var(--ease), transform 0.35s var(--ease);
}

.player-card:hover .player-card-monogram,
.player-card:focus-visible .player-card-monogram {
  -webkit-text-stroke-color: rgba(199, 243, 60, 0.32);
  transform: scale(1.04);
}

/* Roster index - the small ordinal esport rosters carry. Deliberately
   quiet: it should register as craft when you look for it, not compete
   with the player's name. */
.player-card-index {
  position: absolute;
  top: 10px;
  left: 11px;
  z-index: 3;
  font-family: var(--font-display);
  font-size: var(--text-3xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-tertiary);
  transition: color 0.25s var(--ease);
}

.player-card:hover .player-card-index,
.player-card:focus-visible .player-card-index {
  color: var(--accent-ink);
}

/* Rank emblem, mirroring the roster index across the top of the card. Stays
   out of the layout until it actually has an emblem in it, so a player with
   no Riot ID linked leaves no empty box behind. */
.player-card-rank-badge {
  position: absolute;
  top: 8px;
  right: 9px;
  z-index: 3;
  display: none;
  width: 30px;
  height: 30px;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.75));
  transition: transform 0.25s var(--ease);
}

.player-card-rank-badge.is-loaded {
  display: block;
}

.player-card-rank-badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.player-card:hover .player-card-rank-badge,
.player-card:focus-visible .player-card-rank-badge {
  transform: scale(1.08);
}

@media (max-width: 640px) {
  .player-card-rank-badge {
    top: 6px;
    right: 7px;
    width: 22px;
    height: 22px;
  }
}

/* Keeps the name/role block legible over any portrait, while letting the
   agent art itself breathe. The falloff is deliberately tight and bottom-
   weighted: the previous curve still sat at 45% opacity across the middle
   of the card, which greyed out the very illustration the card exists to
   show. Opaque where the text is, gone by the upper third. */
.player-card-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(0deg, rgba(3, 8, 5, 0.97) 0%, rgba(3, 8, 5, 0.88) 14%, rgba(3, 8, 5, 0.3) 38%, transparent 58%),
    linear-gradient(180deg, rgba(3, 8, 5, 0.45) 0%, transparent 30%);
}

.player-card:hover,
.player-card:focus-visible {
  border-color: rgba(199, 243, 60, 0.5);
  outline: none;
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(199, 243, 60, 0.12);
}

.player-card::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--nbk-lime);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.2s var(--ease);
  z-index: 2;
}

.player-card:hover::before,
.player-card:focus-visible::before {
  transform: scaleX(1);
}

.player-card-main {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 12px 13px;
}

.player-card-main-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 6px;
}

.player-card-name {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-base);
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-card-hint {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: var(--text-3xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  transition: color 0.18s var(--ease);
}

.player-card:hover .player-card-hint,
.player-card:focus-visible .player-card-hint {
  color: var(--accent-ink);
}

/* Role sits in the bottom block next to the "voir le profil" hint. It used
   to be absolutely positioned at a hardcoded top:60px - tuned to sit under
   the old monogram chip, but left stranded mid-card for players who had a
   portrait (where that chip never rendered), which is what made the roster
   read as two unrelated card designs. One block, one position, both states. */
.player-card-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.player-card-role-static {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: rgb(var(--ink-rgb) / 0.06);
  font-family: var(--font-display);
  font-size: var(--text-3xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

/* The same card component, shrunk to ~84px thumbnails on the home page:
   drop the bottom meta row, scale the monogram to the smaller box, and drop
   the stream icons that would otherwise truncate the name to "ADLI…". The
   full roster is one click away. */
.home-roster-preview .player-card-sub,
.home-roster-preview .roster-stream-icons,
.home-roster-preview .player-card-index {
  display: none;
}

.home-roster-preview .player-card-monogram {
  font-size: var(--text-3xl);
}

.home-roster-preview .player-card-main {
  padding: 8px 8px 9px;
}

/* Stops above the name block rather than covering the whole card: the panel
   used to span inset:0, so hovering a player replaced their name with their
   agent/rank - you could read the stats but no longer see whose they were.
   The name/role block stays put and the details fill the space above it. */
.player-card-hover {
  position: absolute;
  inset: 0 0 74px 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 6px;
  padding: 14px 12px 10px;
  background: linear-gradient(0deg, rgba(3, 8, 5, 0.88) 45%, rgba(3, 8, 5, 0.45) 78%, transparent 100%);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}

.player-card:hover .player-card-hover,
.player-card:focus-visible .player-card-hover {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.player-card-role,
.player-card-agent {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.player-card-agent {
  background: var(--nbk-lime-soft);
  color: var(--nbk-black);
  border: none;
}

.player-card-role {
  background: rgb(var(--ink-rgb) / 0.08);
  color: var(--text);
  border: 1px solid var(--border);
}

.player-card-rank {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-weight: 600;
}

.player-card-tracker {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--accent-ink);
  text-decoration: none;
}

.player-card-tracker:hover {
  text-decoration: underline;
}

.roster-stream-icons {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.roster-stream-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  color: var(--text);
  background: rgb(var(--ink-rgb) / 0.06);
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.roster-stream-icon:hover {
  transform: translateY(-1px) scale(1.06);
}

.roster-stream-twitch:hover {
  background: rgba(145, 70, 255, 0.25);
  color: #b794ff;
}

.roster-stream-youtube:hover {
  background: rgba(255, 0, 0, 0.2);
  color: #ff6b6b;
}

.roster-stream-tiktok:hover {
  background: rgb(var(--ink-rgb) / 0.15);
  color: #25f4ee;
}

.result-panel ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.result-panel li {
  margin-bottom: 10px;
  padding: 14px 16px;
  border-radius: var(--radius-card);
  background: rgba(199, 243, 60, 0.04);
  color: var(--text);
}

/* ===== PICK / DECIDER STATES ===== */
.map-card.picked-a,
.map-card.picked-b {
  border-color: var(--accent-ink);
  background: linear-gradient(180deg, rgba(199, 243, 60, 0.18), transparent 60%);
  animation: pick-pop 0.4s var(--ease) forwards;
}

@keyframes pick-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.02); }
  100% { transform: scale(1); }
}

/* Decider - pulsing lime border */
.map-card.decider {
  border-color: var(--accent-ink);
  background: linear-gradient(180deg, rgba(199, 243, 60, 0.18), transparent 60%);
  animation: badgePulse 2.2s var(--ease) infinite;
}

@media (max-width: 720px) {
  .panel {
    padding: 18px;
  }

  .maps-grid,
  .ban-summary {
    grid-template-columns: 1fr;
  }
}

/* ===========================================================================
   HISTORIQUE NBK - matchs joués par les équipes Nobak
   =========================================================================== */
/* Scoped to .active (not bare .historique-panel) - a bare `display: flex`
   here has the same specificity as, and is declared after, the generic
   `.page-section { display: none }` gate above, so it silently won and
   kept the Historique panel (and its match cards, live and clickable)
   visible on every page regardless of which page was actually active. On
   sparse pages like Accueil it rendered right below the hero text. */
.historique-panel.active {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
  min-height: 0;
}

.historique-panel .panel-title {
  flex: 0 0 auto;
}

.historique-global-stats:empty {
  display: none;
}

.historique-global-stats {
  flex: 0 0 auto;
  margin-bottom: 20px;
}

.historique-month-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.historique-month-header .player-profile-section-title {
  margin: 0;
}

/* Les deux sélecteurs de mois (Vue d'ensemble + Statistiques de l'équipe)
   vivent hors d'un <form> : ils échappaient donc au bloc "Planner
   enhancements" plus haut et restaient au style natif du navigateur, blanc
   sur panel sombre. Même recette que les autres selects autonomes du panel
   Coach (.player-tracking-controls select), avec la flèche maison. */
.historique-month-header select {
  padding: 8px 34px 8px 12px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background-color: rgb(var(--ink-rgb) / 0.03);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23ffffff' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  color: var(--text);
  font-family: inherit;
  font-size: var(--text-md);
  color-scheme: dark;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.historique-month-header select:hover {
  border-color: rgba(199, 243, 60, 0.45);
}

.historique-month-header select:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

.historique-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  flex: 1 1 auto;
  min-height: 0;
  align-content: start;
}

.historique-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 22px 24px;
  border-radius: var(--radius-card);
  background-size: cover;
  background-position: center;
  border: 1px solid var(--border);
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

/* Léger effet de zoom progressif sur l'image de fond */
.historique-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.9));
  z-index: 0;
}

.historique-card__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.historique-card:hover {
  border-color: var(--accent-ink);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.historique-card::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  z-index: 2;
}

.historique-win::before {
  background: var(--nbk-lime);
}

.historique-loss::before {
  background: var(--text-tertiary);
}

.historique-teams {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.historique-nobak {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text);
}

.historique-vs {
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.historique-opponent {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text);
}

.historique-meta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: var(--text-md);
  color: var(--text-secondary);
}

.historique-map,
.historique-datetime,
.historique-type {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.historique-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.historique-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.badge-win {
  background: transparent;
  color: var(--accent-ink);
  border: 1px solid var(--nbk-lime);
}

.badge-loss {
  background: transparent;
  color: var(--text-tertiary);
  border: 1px solid var(--border);
}

.historique-score {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.historique-admin-panel {
  margin-top: 16px;
}

/* ===========================================================================
   RÉGIE / OVERLAY - tenir tout à l'écran au zoom 100%
   L'overlay (panneau de diffusion) s'adapte à la hauteur du viewport pour
   que tous les éléments (équipes + maps) soient visibles sans défilement,
   même à 100% de zoom.
   =========================================================================== */
#page-regie .overlay-panel {
  height: calc(100vh - 150px);
  min-height: 0;
  max-height: none;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  overflow: hidden;
}

#page-regie .overlay-teams {
  flex: 0 0 auto;
}

#page-regie .overlay-ban {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin-top: 16px;
}

#page-regie .overlay-ban-title {
  flex: 0 0 auto;
}

#page-regie .overlay-ban-list {
  flex: 1 1 auto;
  min-height: 0;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  align-items: stretch;
}

#page-regie .overlay-ban-item {
  min-height: 0;
  height: 100%;
  max-height: 100%;
  width: 44vw;
  max-width: 300px;
  flex: 1 1 0;
}

/* Sur petits écrans, laisser la liste s'organiser en grille compacte */
@media (max-width: 900px) {
  #page-regie .overlay-panel {
    height: auto;
    max-height: none;
    display: block;
  }
  #page-regie .overlay-ban-item {
    width: 200px;
    height: 320px;
  }
}

/* ===========================================================================
   OBS BROADCAST, TOAST NOTIFICATIONS & COPY BADGES
   =========================================================================== */

/* --- Broadcast / OBS Tools Box --- */
.obs-tools-panel {
  border: 1px solid rgba(199, 243, 60, 0.3);
  background: linear-gradient(135deg, rgba(8, 20, 14, 0.85) 0%, rgba(12, 32, 22, 0.85) 100%);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), inset 0 0 16px rgba(199, 243, 60, 0.05);
  margin-bottom: 24px;
}

.obs-tools-header h2 {
  font-size: var(--text-lg);
  margin-bottom: 6px;
  color: var(--accent-ink);
  display: flex;
  align-items: center;
  gap: 8px;
}

.obs-tools-header p {
  color: var(--muted, #a0aec0);
  font-size: var(--text-md);
  margin-bottom: 16px;
}

.obs-tools-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.btn-obs {
  background: linear-gradient(135deg, #c7f33c 0%, #e1f2ae 100%);
  color: #040906 !important;
  font-weight: 700;
  border: none;
  box-shadow: 0 4px 15px rgba(199, 243, 60, 0.4);
  transition: transform 0.2s, box-shadow 0.2s;
}

.btn-obs:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(199, 243, 60, 0.6);
}

.btn-secondary {
  background: rgb(var(--ink-rgb) / 0.08);
  /* Le fond suit le canal d’encre : le texte doit suivre le même thème,
     sinon il reste blanc sur un bouton devenu clair. */
  color: var(--text);
  border: 1px solid rgb(var(--ink-rgb) / 0.15);
}

.btn-secondary:hover {
  background: rgb(var(--ink-rgb) / 0.16);
  border-color: rgb(var(--ink-rgb) / 0.3);
}

/* --- Standalone OBS Overlay Mode (Transparent OBS Browser Source) --- */
body.obs-overlay-mode {
  background: transparent !important;
  background-color: transparent !important;
  overflow: hidden !important;
  margin: 0 !important;
  padding: 0 !important;
}

body.obs-overlay-mode .main-nav,
body.obs-overlay-mode .page-section:not(#page-regie),
body.obs-overlay-mode #page-regie #regieAccessMessage,
body.obs-overlay-mode #page-regie .obs-tools-panel,
body.obs-overlay-mode #page-regie .live-overlay-tools-panel,
body.obs-overlay-mode #page-regie .admin-panel,
body.obs-overlay-mode #page-regie .planner-panel {
  display: none !important;
}

body.obs-overlay-mode .app {
  padding: 0 !important;
  margin: 0 !important;
  max-width: 100% !important;
  background: transparent !important;
  box-shadow: none !important;
}

body.obs-overlay-mode #page-regie {
  display: block !important;
  padding: 0 !important;
  margin: 0 !important;
  background: transparent !important;
}

body.obs-overlay-mode.obs-live-mode #page-regie .overlay-panel {
  display: none !important;
}

body.obs-overlay-mode:not(.obs-live-mode) #page-regie .overlay-panel {
  display: flex !important;
  height: 100vh !important;
  width: 100vw !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 16px 24px !important;
  margin: 0 !important;
  border-radius: 0 !important;
  justify-content: center;
}

body.obs-overlay-mode:not(.obs-live-mode) #page-regie .overlay-teams {
  flex: 0 0 auto;
}

body.obs-overlay-mode:not(.obs-live-mode) #page-regie .overlay-ban {
  width: 100%;
  flex: 1 1 auto;
  margin-top: 16px;
}

body.obs-overlay-mode:not(.obs-live-mode) #page-regie .overlay-panel {
  flex-direction: column;
}

body.obs-overlay-mode .overlay-panel::before {
  display: none !important;
}

/* --- Toast Notifications --- */
.toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  background: rgba(10, 18, 14, 0.95);
  border: 1px solid var(--accent-green, #c7f33c);
  color: #ffffff;
  padding: 12px 18px;
  border-radius: var(--radius-card);
  font-weight: 600;
  font-size: var(--text-md);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6), 0 0 15px rgba(199, 243, 60, 0.25);
  display: flex;
  align-items: center;
  gap: 10px;
  animation: toast-in 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* La bordure et l'icone disent la meme chose que le texte. Avant, tout etait
   vert : un echec s'annoncait avec une bordure verte. */
.toast__icone {
  display: inline-flex;
  flex: none;
  color: var(--toast-teinte, var(--status-ok));
}

.toast { border-color: var(--toast-teinte, var(--status-ok)); }
.toast--ok   { --toast-teinte: var(--status-ok); }
.toast--ko   { --toast-teinte: var(--status-ko); }
.toast--warn { --toast-teinte: var(--status-warn); }

.toast.toast-out {
  animation: toast-out 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes toast-in {
  0% { opacity: 0; transform: translateY(20px) scale(0.92); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes toast-out {
  0% { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(20px) scale(0.92); }
}

.btn-icon-sm {
  padding: 4px 8px;
  font-size: var(--text-sm);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* ===== PLANNING ===== */
.planning-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin: 14px 0 4px;
  color: var(--muted);
  font-size: var(--text-md);
}

.planning-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.planning-swatch {
  width: 14px;
  height: 14px;
  border-radius: var(--radius);
  display: inline-block;
  border: 1px solid rgb(var(--ink-rgb) / 0.08);
}

.planning-swatch.planning-dispo { background: rgba(199, 243, 60, 0.5); border-color: rgba(199, 243, 60, 0.7); }
.planning-swatch.planning-indispo { background: rgba(255, 92, 122, 0.5); border-color: rgba(255, 92, 122, 0.7); }
.planning-swatch.planning-empty { background: rgb(var(--ink-rgb) / 0.06); }

.planning-team .panel-title {
  margin-bottom: 0;
}

.planning-day-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
}

.planning-day-tab {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.25);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.planning-day-tab:hover {
  transform: translateY(-1px);
  border-color: rgb(var(--ink-rgb) / 0.55);
}

.planning-day-tab.active {
  background: rgb(var(--ink-rgb) / 0.14);
  color: var(--text);
  border-color: rgb(var(--ink-rgb) / 0.65);
}

.planning-window-nav {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
}

.planning-window-arrow {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  border: 1px solid rgb(var(--ink-rgb) / 0.35);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease;
}

.planning-window-arrow:hover {
  background: var(--primary-soft);
  transform: translateY(-1px);
}

.planning-window-range {
  color: var(--text);
  font-weight: 700;
  font-size: var(--text-md);
  letter-spacing: 0.01em;
}

.planning-window-today {
  padding: 7px 12px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.4);
  background: var(--primary-soft);
  color: var(--primary-2);
  font-weight: 700;
  font-size: var(--text-xs);
  text-transform: uppercase;
  cursor: pointer;
}

.planning-table-scroll {
  overflow-x: auto;
  margin-top: 12px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  /* Le collage de l'en-tête a besoin d'un conteneur de défilement qui borne
     la hauteur ; sans plafond, `position: sticky` n'a rien à quoi se
     raccrocher et l'en-tête sort du cadre avec le reste. Le plafond est en
     `dvh` pour ne pas se faire manger par la barre d'URL sur mobile. */
  overflow-y: auto;
  max-height: min(72vh, 760px);
}

@supports (height: 100dvh) {
  .planning-table-scroll { max-height: min(72dvh, 760px); }
}

.planning-table {
  border-collapse: collapse;
  width: 100%;
  table-layout: fixed;
  font-variant-numeric: tabular-nums;
}

.planning-table th,
.planning-table td {
  padding: 10px 6px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-md);
}

/* L'en-tête reste collé en haut pendant qu'on parcourt la grille. Sur un
   planning hebdomadaire, perdre le nom des colonnes après trois lignes de
   défilement oblige à remonter pour savoir quel jour on regarde.
   `background` opaque et non `--surface-1` translucide : une en-tête collée
   qui laisse voir les lignes défiler dessous est illisible. */
.planning-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--surface-solid);
  box-shadow: inset 0 -1px 0 rgba(199, 243, 60, 0.28);
}

/* Survol de ligne : sur une grille dense de cases, savoir quelle ligne on
   pointe vaut plus que n'importe quel ornement. */
.planning-table tbody tr:hover td {
  background: rgba(199, 243, 60, 0.035);
}

.planning-table tbody tr:last-child td {
  border-bottom: none;
}

.planning-table th:first-child,
.planning-slot-time {
  width: 96px;
}

.planning-slot-time {
  text-align: left;
  padding-left: 16px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.planning-cell {
  padding: 5px !important;
}

.planning-cell-btn {
  width: 100%;
  min-width: 0;
  padding: 14px 4px;
  border-radius: var(--radius);
  border: 1px solid rgb(var(--ink-rgb) / 0.08);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  user-select: none;
  touch-action: none;
}

.planning-cell-btn:hover:not(:disabled) {
  transform: translateY(-1px);
}

.planning-cell-btn:disabled {
  cursor: not-allowed;
}

.planning-cell-btn.planning-empty {
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--muted);
  border-color: rgb(var(--ink-rgb) / 0.08);
}

.planning-cell-btn.planning-dispo {
  background: rgba(199, 243, 60, 0.22);
  color: var(--status-ok);
  border-color: rgba(199, 243, 60, 0.5);
}

.planning-cell-btn.planning-indispo {
  background: rgba(255, 92, 122, 0.18);
  color: var(--status-ko);
  border-color: rgba(255, 92, 122, 0.45);
}

/* ===== ADMIN ROSTER ===== */
.roster-admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  margin-top: 8px;
}

.roster-admin-team h3 {
  margin: 0 0 12px;
}

.roster-admin-hint {
  margin: -6px 0 12px;
  color: var(--muted);
  font-size: var(--text-sm);
  line-height: 1.4;
}

.roster-admin-list {
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.roster-admin-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: rgb(var(--ink-rgb) / 0.03);
  font-weight: 700;
}

.roster-link-select {
  flex: 1;
  min-width: 0;
  max-width: 200px;
  padding: 6px 8px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.25);
  background: rgba(4, 10, 6, 0.9);
  color: var(--text);
  font-weight: 600;
  font-size: var(--text-sm);
}

.roster-admin-empty {
  color: var(--muted);
  font-weight: 400;
  font-style: italic;
  padding: 4px 2px;
}

.roster-admin-add {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.roster-admin-add input {
  flex: 1;
  min-width: 140px;
}

/* ===== BETA NOTICE MODAL ===== */
.beta-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(4, 2, 9, 0.75);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 1;
  transition: opacity 0.22s var(--ease);
}

.beta-modal-overlay.hidden {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition: opacity 0.18s var(--ease), visibility 0s 0.18s;
}

.beta-modal-card,
.player-profile-card {
  transform: scale(1);
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}

.beta-modal-overlay.hidden .beta-modal-card,
.beta-modal-overlay.hidden .player-profile-card {
  transform: scale(0.96);
  opacity: 0;
}

.beta-modal-card {
  width: 100%;
  max-width: 480px;
  padding: 36px 32px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--field-bg);
  text-align: center;
}

.beta-modal-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--accent-ink);
}

.beta-modal-eyebrow {
  display: block;
  font-family: var(--font-display);
  color: var(--accent-ink);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  margin-bottom: 10px;
}

.beta-modal-title {
  margin: 0 0 14px;
  font-size: var(--text-xl);
}

.beta-modal-text {
  margin: 0 0 24px;
  color: var(--muted);
  line-height: 1.55;
}

.beta-modal-card .btn + .btn {
  margin-top: 10px;
}

.beta-modal-card .btn {
  width: 100%;
}

/* ===== PLAYER PROFILE MODAL ===== */
.player-profile-card {
  position: relative;
  width: 100%;
  max-width: 620px;
  max-height: 85vh;
  overflow-y: auto;
  padding: 32px;
  border-radius: var(--radius-card);
  border: 1px solid rgb(var(--ink-rgb) / 0.35);
  background: rgba(12, 9, 22, 0.98);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5), 0 0 40px rgb(var(--ink-rgb) / 0.1);
  text-align: left;
}

/* The scoreboard modals (Admin edit + public match view) hold a wide
   multi-column table - give them more room than the plain player-profile
   stats modal so columns aren't cramped. */
.scoreboard-modal-card {
  max-width: 900px;
}

.player-profile-close {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 2;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid rgb(var(--ink-rgb) / 0.14);
  background: rgb(var(--ink-rgb) / 0.04);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.player-profile-close:hover {
  background: rgba(255, 92, 122, 0.16);
  border-color: rgba(255, 92, 122, 0.5);
}

.player-profile-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 22px;
}

.player-profile-avatar {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xl);
  font-weight: 800;
  color: #04160c;
  background: linear-gradient(135deg, rgba(199, 243, 60, 0.9), rgba(225, 242, 174, 0.7));
  overflow: hidden;
}

.player-profile-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.player-profile-name {
  margin: 0;
  font-size: var(--text-xl);
}

/* .boutique-card-badge is positioned absolute for its usual home (a grid
   tile) - reused inline here for the product modal's title, it was
   floating to the modal's top-right corner and landing on the close
   button. Neutralize that positioning in this one context only. */
.player-profile-name .boutique-card-badge {
  position: static;
  display: inline-block;
  vertical-align: middle;
  margin-left: 8px;
}

.player-profile-team {
  margin: 2px 0 0;
  color: var(--muted);
  font-size: var(--text-md);
}

.player-profile-links {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.player-profile-section-title {
  margin: 22px 0 10px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.player-profile-matches {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.player-profile-match {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--radius-card);
  background: rgb(var(--ink-rgb) / 0.03);
  font-size: var(--text-md);
}

.player-profile-match-info {
  color: var(--muted);
}

.player-profile-empty {
  color: var(--muted);
  font-size: var(--text-md);
}

/* ===== TREND CHARTS (player profile / Compte / Suivi joueur) ===== */
.trend-chart-wrap {
  padding: 12px 14px 8px;
  border-radius: var(--radius-card);
  background: rgb(var(--ink-rgb) / 0.03);
  border: 1px solid rgba(199, 243, 60, 0.1);
}

.trend-chart {
  display: block;
  width: 100%;
  height: auto;
}

.chart-grid-line {
  stroke: rgb(var(--ink-rgb) / 0.08);
  stroke-width: 1;
}

.chart-axis-label {
  fill: var(--muted);
  font-size: var(--text-3xs);
}

.chart-avg-line {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}

.chart-line {
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chart-line-impact {
  stroke: var(--accent);
}

.chart-line-kills {
  stroke: var(--accent);
}

.chart-line-deaths {
  stroke: var(--danger);
}

.chart-line-assists {
  stroke: #5cc8ff;
}

/* Invisible larger circle layered under each visible dot so hovering/tapping
   near a point (not just its tiny painted pixels) triggers the tooltip -
   the dots themselves stay small and clean, only the hit area grows. */
.chart-dot-hit {
  fill: transparent;
  pointer-events: all;
  cursor: pointer;
}

.chart-dot {
  stroke: var(--surface);
  stroke-width: 1;
  fill: var(--muted);
  pointer-events: none;
}

.chart-dot.positive {
  fill: var(--accent);
}

.chart-dot.negative {
  fill: var(--danger);
}

.chart-dot-sm {
  stroke: var(--surface);
  stroke-width: 1;
  pointer-events: none;
}

.chart-dot-sm.chart-line-kills {
  fill: var(--accent);
}

.chart-dot-sm.chart-line-deaths {
  fill: var(--danger);
}

.chart-dot-sm.chart-line-assists {
  fill: #5cc8ff;
}

.chart-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 8px;
  padding: 0 2px;
}

.chart-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--muted);
}

.chart-legend-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.chart-legend-dot.chart-line-kills {
  background: var(--accent);
}

.chart-legend-dot.chart-line-deaths {
  background: var(--danger);
}

.chart-legend-dot.chart-line-assists {
  background: #5cc8ff;
}

/* ===== ACCOUNTS & ROLES ===== */
/* ===== ACCÈS RESTREINT =====
   Cinq pages protégées affichent ce panneau. Son <h2> n'appartenait ni à
   `.panel-title` ni à `.section-heading` : c'était le troisième motif de titre
   du site, resté au style par défaut du navigateur pendant que les 55 autres
   étaient unifiés. Il rejoint le même traitement - et le panneau porte un
   cadenas lime, pour que l'écran se lise comme une porte fermée plutôt que
   comme une page vide. */
.role-gate-message h2 {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.028em;
  text-transform: uppercase;
}

.role-gate-message h2::after {
  content: '';
  flex: 1;
  height: 1px;
  min-width: 24px;
  background: linear-gradient(90deg, rgba(199, 243, 60, 0.45), rgba(199, 243, 60, 0));
}

/* Le cadenas est accroché au titre et non au panneau : sur `.panel`, ::before
   porte déjà le filet de crête et ::after les équerres HUD. */
.role-gate-message h2::before {
  content: '';
  flex: none;
  width: 24px;
  height: 24px;
  background: var(--nbk-lime);
  opacity: 0.85;
  -webkit-mask: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
}

.role-gate-message p {
  color: var(--muted);
}

.role-gate-message a {
  color: var(--accent-ink);
  font-weight: 700;
}

/* --- Compte page: centered SaaS-style auth card --- */
.page-section.compte-page.active {
  display: flex;
  justify-content: center;
  padding-top: clamp(16px, 4vh, 56px);
}

.auth-shell {
  width: 100%;
  max-width: 440px;
}

.auth-shell.auth-shell-wide {
  max-width: min(1240px, 94vw);
}

/* La carte de connexion flottait dans le noir, en rayon de 28 px et dégradé
   blanchâtre - un composant générique, alors que c'est le seul écran que tout
   visiteur qui crée un compte traverse. Elle reprend maintenant le rayon du
   système, les surfaces du site, les équerres HUD, et la lumière vient d'en
   haut à gauche comme partout ailleurs. */
.auth-card {
  position: relative;
  width: 100%;
  padding: 40px 36px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border-strong);
  --hud-c: var(--hud-line);
  --hud-s: 13px;
  background:
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px top 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px top 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px top 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px top 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px bottom 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) left 9px bottom 9px / var(--hud-s) 1px no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px bottom 9px / 1px var(--hud-s) no-repeat,
    linear-gradient(var(--hud-c), var(--hud-c)) right 9px bottom 9px / var(--hud-s) 1px no-repeat,
    radial-gradient(130% 80% at 0% 0%, rgba(199, 243, 60, 0.06), transparent 58%),
    linear-gradient(160deg, var(--surface-2), var(--card-deep));
  box-shadow: var(--shadow-lg);
}

/* Filet de crête, comme sur .panel : la carte est éclairée par le haut. */
.auth-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: linear-gradient(90deg, transparent, rgba(199, 243, 60, 0.4) 26%, rgba(199, 243, 60, 0.4) 74%, transparent);
  pointer-events: none;
}

/* La page de connexion n'avait aucun décor : la carte flottait au milieu du
   vide. La même trame technique que .page-hero lui donne un lieu. */
#page-compte {
  position: relative;
}

#page-compte::before {
  content: '';
  position: absolute;
  inset: -24px calc(-1 * var(--app-pad-x)) 0;
  z-index: -1;
  background-image:
    linear-gradient(90deg, rgba(199, 243, 60, 0.05) 1px, transparent 1px),
    linear-gradient(180deg, rgba(199, 243, 60, 0.05) 1px, transparent 1px);
  background-size: 64px 64px, 64px 64px;
  mask-image: radial-gradient(64% 58% at 50% 34%, #000, transparent 78%);
  -webkit-mask-image: radial-gradient(64% 58% at 50% 34%, #000, transparent 78%);
  pointer-events: none;
}

.auth-card-header {
  text-align: center;
  margin-bottom: 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.auth-logo {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 16px;
  box-shadow: 0 0 0 3px rgb(var(--ink-rgb) / 0.15), 0 10px 30px rgba(199, 243, 60, 0.25);
}

.auth-card-header h2 {
  margin: 0 0 8px;
  font-size: var(--text-xl);
}

.auth-card-header p {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-md);
  line-height: 1.5;
}

.auth-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  padding: 4px;
  border-radius: 999px;
  background: rgb(var(--ink-rgb) / 0.04);
  border: 1px solid rgb(var(--ink-rgb) / 0.2);
  margin-bottom: 28px;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0;
  color: var(--muted);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.auth-divider::before, .auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgb(var(--ink-rgb) / 0.1);
}

.auth-switch-indicator {
  position: absolute;
  top: 4px;
  left: 4px;
  width: calc(50% - 4px);
  height: calc(100% - 8px);
  border-radius: 999px;
  background: linear-gradient(135deg, var(--primary), var(--primary-2));
  box-shadow: 0 6px 18px rgb(var(--ink-rgb) / 0.35);
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 0;
}

.auth-switch-btn {
  position: relative;
  z-index: 1;
  padding: 10px 0;
  border: none;
  background: transparent;
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-md);
  cursor: pointer;
  border-radius: 999px;
  transition: color 0.2s ease;
}

.auth-switch-btn.active {
  color: #0a0a0a;
}

.auth-forgot-link {
  display: block;
  margin: 4px auto 0;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  text-decoration: underline;
  cursor: pointer;
}

.auth-forgot-link:hover {
  color: var(--accent-ink);
}

#forgotPasswordPanel {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.auth-form.hidden {
  display: none;
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.auth-field label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.auth-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.auth-input-icon {
  position: absolute;
  left: 16px;
  color: var(--muted);
  pointer-events: none;
}

.auth-input-wrap input {
  width: 100%;
  padding: 14px 46px;
  border-radius: var(--radius);
  border: 1px solid rgb(var(--ink-rgb) / 0.25);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-size: var(--text-base);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.auth-input-wrap input:focus {
  outline: none;
  border-color: var(--primary-2);
  box-shadow: var(--ring);
}

/* Bare fields directly inside .auth-field (no icon, so no .auth-input-wrap
   wrapper) - password fields, Riot ID / région / rôle on the Valorant
   profile block. Without this they fall back to unstyled white browser
   default inputs, clashing with the dark theme everywhere else. */
.auth-field > input,
.auth-field > select,
.auth-field > textarea {
  width: 100%;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid rgb(var(--ink-rgb) / 0.25);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-size: var(--text-base);
  font-family: inherit;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  resize: vertical;
}

.auth-field > select {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23ffffff' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  padding-right: 38px;
  cursor: pointer;
}

.auth-field > select option {
  background: var(--surface-solid);
  color: var(--text);
}

.auth-field > input:focus,
.auth-field > select:focus,
.auth-field > textarea:focus {
  outline: none;
  border-color: var(--primary-2);
  box-shadow: var(--ring);
}

.auth-field > input:hover,
.auth-field > select:hover,
.auth-field > textarea:hover {
  border-color: rgb(var(--ink-rgb) / 0.5);
}

.auth-visibility-toggle {
  position: absolute;
  right: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  border-radius: var(--radius);
  transition: color 0.2s ease;
}

.auth-visibility-toggle:hover {
  color: var(--accent-ink);
}

.auth-submit {
  width: 100%;
  padding: 15px;
  border-radius: var(--radius);
  font-size: var(--text-md);
  display: flex;
  align-items: center;
  justify-content: center;
}

.auth-submit:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  transform: none !important;
}

.auth-submit-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.auth-submit-label.loading::before {
  content: '';
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid rgba(4, 22, 12, 0.35);
  border-top-color: #04160c;
  animation: auth-spin 0.7s linear infinite;
}

@keyframes auth-spin {
  to { transform: rotate(360deg); }
}

/* --- Logged-in account card --- */
.account-card {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 32px;
}

.account-left-col {
  flex: 0 0 280px;
  text-align: center;
}

.account-stats-col {
  flex: 1 1 320px;
  min-width: 280px;
  text-align: left;
}

.account-stats-col:empty {
  display: none;
}

.account-stats-title {
  margin: 0 0 16px;
  font-size: var(--text-lg);
}

.compte-orders-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 24px;
}

.compte-order-row {
  padding: 14px 16px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: rgb(var(--ink-rgb) / 0.02);
}

.compte-order-row-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.compte-order-number {
  font-family: var(--font-display);
  font-weight: 700;
}

.compte-order-row-items {
  color: var(--text-secondary);
  font-size: var(--text-md);
  margin-bottom: 6px;
}

.compte-order-row-bottom {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: var(--text-md);
}

.order-status-badge {
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
  background: rgb(var(--ink-rgb) / 0.06);
  color: var(--text-secondary);
}

.order-status-badge--payée,
.order-status-badge--terminée {
  background: rgba(199, 243, 60, 0.16);
  color: var(--accent-ink);
}

.order-status-badge--annulée {
  background: rgba(255, 90, 90, 0.14);
  color: #ff8080;
}

.account-stats-empty {
  color: var(--muted);
  font-size: var(--text-md);
  padding: 18px 20px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: rgb(var(--ink-rgb) / 0.02);
}

.account-avatar-wrap {
  position: relative;
  width: 72px;
  margin: 0 auto 18px;
}

.account-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  font-size: var(--text-2xl);
  font-weight: 700;
  color: #0a0a0a;
  background: linear-gradient(135deg, var(--primary), var(--primary-2));
  box-shadow: 0 10px 30px rgb(var(--ink-rgb) / 0.3);
}

.account-avatar-wrap .account-avatar {
  margin: 0;
}

.account-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.account-avatar-edit-btn {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(12, 9, 22, 0.92);
  border: 1px solid rgb(var(--ink-rgb) / 0.45);
  color: var(--primary-2);
  cursor: pointer;
  padding: 0;
}

.account-avatar-edit-btn:hover {
  background: var(--primary-soft);
}

.account-username-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.account-username-wrap .account-username {
  margin: 0 0 4px;
}

.account-username-edit-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: rgb(var(--ink-rgb) / 0.06);
  border: 1px solid rgb(var(--ink-rgb) / 0.3);
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  margin-bottom: 4px;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.account-username-edit-btn:hover {
  background: var(--primary-soft);
  color: var(--primary-2);
  border-color: rgb(var(--ink-rgb) / 0.55);
}

.compte-username-form {
  max-width: 260px;
  margin: 0 auto 16px;
}

.compte-username-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}

.account-subtitle {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-md);
}

.compte-roles-label {
  color: var(--muted);
  margin: 24px 0 10px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.role-badge-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-bottom: 28px;
}

.role-badge {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.4);
  background: var(--primary-soft);
  color: var(--primary-2);
  font-weight: 700;
  font-size: var(--text-sm);
}

.role-badge.role-badge-pending {
  border-color: rgba(255, 176, 32, 0.45);
  background: rgba(255, 176, 32, 0.14);
  color: #ffd98e;
}

.role-badge.role-badge-org {
  border-color: rgba(120, 170, 255, 0.45);
  background: rgba(120, 170, 255, 0.14);
  color: #a8c6ff;
}

.accounts-admin-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 14px 0 4px;
}

.accounts-admin-search {
  flex: 1;
  min-width: 200px;
  max-width: 340px;
  padding: 10px 16px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.25);
  background: rgba(4, 10, 6, 0.9);
  color: var(--text);
  font-weight: 600;
  font-size: var(--text-md);
}

.accounts-admin-count {
  color: var(--muted);
  font-size: var(--text-sm);
  font-weight: 600;
}

.accounts-admin-filter {
  display: flex;
  gap: 6px;
}

.accounts-filter-chip {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.14);
  background: rgb(var(--ink-rgb) / 0.04);
  color: var(--muted);
  font-weight: 600;
  font-size: var(--text-sm);
  cursor: pointer;
  transition: transform 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.accounts-filter-chip:hover {
  transform: translateY(-1px);
  border-color: rgb(var(--ink-rgb) / 0.4);
  color: var(--text);
}

.accounts-filter-chip.active {
  background: var(--primary-soft);
  border-color: rgb(var(--ink-rgb) / 0.55);
  color: var(--primary-2);
}

.accounts-admin-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 12px;
}

.account-admin-item {
  padding: 16px 20px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: rgb(var(--ink-rgb) / 0.03);
  transition: border-color 0.2s ease, background 0.2s ease;
}

.account-admin-item.pending {
  border-color: rgba(255, 176, 32, 0.35);
  background: rgba(255, 176, 32, 0.05);
}

.account-admin-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.account-admin-identity {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.account-admin-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  flex-shrink: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-md);
  font-weight: 700;
  color: #04160c;
  background: linear-gradient(135deg, rgba(199, 243, 60, 0.9), rgba(225, 242, 174, 0.7));
}

.account-admin-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.account-admin-username {
  font-weight: 700;
  font-size: var(--text-base);
}

.discord-badge {
  border-color: rgba(88, 101, 242, 0.4);
  background: rgba(88, 101, 242, 0.14);
  color: #b3b9ff;
  gap: 5px;
}

.discord-badge svg {
  flex-shrink: 0;
}

.account-admin-roles {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.map-pool-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}

.map-pool-chip {
  padding: 10px 18px;
  font-size: var(--text-md);
}

.role-toggle-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.14);
  background: rgb(var(--ink-rgb) / 0.04);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.15s ease;
}

.role-toggle-chip:hover:not(:disabled) {
  transform: translateY(-1px);
  border-color: rgb(var(--ink-rgb) / 0.4);
  color: var(--text);
}

.role-toggle-chip.active {
  background: var(--primary-soft);
  border-color: rgb(var(--ink-rgb) / 0.55);
  color: var(--primary-2);
}

.role-toggle-chip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.account-admin-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.account-admin-password-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgb(var(--ink-rgb) / 0.08);
}

.account-password-input {
  flex: 1;
  min-width: 180px;
  padding: 8px 12px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
}

.account-password-input:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

.account-password-status {
  font-size: var(--text-sm);
  color: var(--muted);
}

.account-password-status.success {
  color: var(--accent-ink);
}

.account-password-status.error {
  color: var(--danger);
}

.account-admin-valorant-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgb(var(--ink-rgb) / 0.08);
}

.account-admin-valorant-row select,
.account-admin-valorant-row input {
  padding: 8px 12px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
}

.account-riot-name-input {
  width: 130px;
}

.account-riot-tag-input {
  width: 70px;
}

.account-valorant-status {
  font-size: var(--text-sm);
  color: var(--muted);
}

.account-valorant-status.success {
  color: var(--accent-ink);
}

.account-valorant-status.error {
  color: var(--danger);
}


/* ===== DISCORD ===== */
.compte-discord-wrap {
  margin-bottom: 24px;
}

.compte-notif-hint {
  margin: 0 0 12px;
  color: var(--text-secondary);
  font-size: var(--text-md);
}

.compte-totp-manual-secret {
  font-family: 'Courier New', monospace;
  font-size: var(--text-md);
  letter-spacing: 0.05em;
  background: rgb(var(--ink-rgb) / 0.06);
  border-radius: var(--radius);
  padding: 8px 12px;
  margin: 10px 0;
  word-break: break-all;
}

.compte-totp-backup-list {
  list-style: none;
  margin: 10px 0;
  padding: 12px 16px;
  background: rgb(var(--ink-rgb) / 0.06);
  border-radius: var(--radius-card);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  font-family: 'Courier New', monospace;
  font-size: var(--text-md);
}

.compte-streaming-form {
  max-width: 320px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.compte-streaming-form .btn {
  align-self: center;
  margin-top: 4px;
}

.stream-input-twitch .auth-input-icon {
  color: #a970ff;
}

.stream-input-twitch input:focus {
  border-color: rgba(169, 112, 255, 0.7) !important;
  box-shadow: 0 0 0 4px rgba(169, 112, 255, 0.14) !important;
}

.stream-input-youtube .auth-input-icon {
  color: #ff5c5c;
}

.stream-input-youtube input:focus {
  border-color: rgba(255, 92, 92, 0.7) !important;
  box-shadow: 0 0 0 4px rgba(255, 92, 92, 0.14) !important;
}

.stream-input-tiktok .auth-input-icon {
  color: #25f4ee;
}

.stream-input-tiktok input:focus {
  border-color: rgba(37, 244, 238, 0.7) !important;
  box-shadow: 0 0 0 4px rgba(37, 244, 238, 0.14) !important;
}

.compte-valorant-rank {
  text-align: center;
  color: var(--accent-ink);
  font-weight: 700;
  font-size: var(--text-md);
  margin: -4px 0 12px;
}

.compte-riot-id-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.compte-riot-id-row .auth-field {
  flex: 1;
}

.compte-riot-hash {
  color: var(--muted);
  font-weight: 800;
  font-size: var(--text-lg);
}

.compte-riot-tag-field {
  flex: 0 0 84px;
}

/* ===== AGENT PICKER MODAL (Compte) ===== */
.agent-picker-card {
  max-width: 640px;
}

.avatar-upload-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 14px 0;
}

.agent-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 10px;
  max-height: 58vh;
  overflow-y: auto;
  margin-top: 14px;
  padding-right: 4px;
}

.agent-picker-item {
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.16);
  background-color: var(--surface-2);
  background-size: cover;
  background-position: center top;
  cursor: pointer;
  display: flex;
  align-items: flex-end;
  padding: 6px;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.agent-picker-item:hover {
  transform: translateY(-2px);
  border-color: rgba(199, 243, 60, 0.5);
}

.agent-picker-item.active {
  border-color: var(--accent-ink);
  box-shadow: 0 0 0 2px rgba(199, 243, 60, 0.4);
}

.agent-picker-item-name {
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  background: rgba(3, 8, 5, 0.75);
  padding: 2px 6px;
  border-radius: var(--radius);
  color: var(--text);
}

.discord-connect-btn {
  background: linear-gradient(135deg, #5865F2, #4752C4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.discord-connect-btn:hover {
  background: linear-gradient(135deg, #6874f5, #5865F2);
}

.discord-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(88, 101, 242, 0.4);
  background: rgba(88, 101, 242, 0.12);
  color: #b3b9ff;
  font-weight: 700;
  font-size: var(--text-md);
  flex-wrap: wrap;
}

.discord-status svg {
  color: #5865F2;
  flex-shrink: 0;
}

/* Both rules above set display:flex unconditionally, which - since they're
   defined after the generic .hidden rule - would otherwise win over it and
   keep the element visible even with .hidden applied. */
.discord-connect-btn.hidden,
.discord-status.hidden {
  display: none;
}

#compteDiscordUsername {
  flex: 1;
  margin-right: 10px;
}

#discordDisconnectBtn {
  margin-left: 6px;
}

/* Extra breathing room between the Discord block and whatever section
   follows it (Valorant profile / logout), on top of the shared
   .compte-discord-wrap bottom margin. */
#compteDiscordWrap {
  margin-top: 4px;
}

/* ===== COACH PANEL ===== */
.coach-team-tabs {
  display: flex;
  gap: 10px;
  margin: 8px 0 20px;
}

.coach-team-tab {
  padding: 10px 20px;
  border-radius: 999px;
  border: 1px solid rgb(var(--ink-rgb) / 0.25);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-md);
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.coach-team-tab:hover {
  transform: translateY(-1px);
  border-color: rgb(var(--ink-rgb) / 0.55);
}

.coach-team-tab.active {
  background: rgb(var(--ink-rgb) / 0.14);
  color: var(--text);
  border-color: rgb(var(--ink-rgb) / 0.65);
}

.coach-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 24px;
}

.coach-stat-tile {
  padding: 18px 20px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.16);
  background: rgb(var(--ink-rgb) / 0.03);
  text-align: center;
}

.coach-stat-value {
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--accent-ink);
  line-height: 1.2;
}

.coach-stat-label {
  margin-top: 6px;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.coach-map-table {
  width: 100%;
  border-collapse: collapse;
}

.coach-map-table th,
.coach-map-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid rgba(199, 243, 60, 0.1);
  font-size: var(--text-md);
}

.coach-map-table th {
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.coach-map-table tr:last-child td {
  border-bottom: none;
}

.coach-range-label {
  margin: 16px 0 10px;
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--accent-ink);
}

.coach-range-label.success {
  color: #7dff97;
}

.coach-range-label.error {
  color: #ff6b6b;
}

.coach-slot-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 20px;
}

.coach-slot-chip {
  padding: 8px 12px;
  border-radius: var(--radius);
  border: 1px solid rgb(var(--ink-rgb) / 0.08);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.coach-slot-chip:hover {
  transform: translateY(-1px);
  border-color: rgba(199, 243, 60, 0.4);
}

.coach-slot-chip.in-range {
  background: rgba(199, 243, 60, 0.14);
  border-color: rgba(199, 243, 60, 0.3);
  color: var(--status-ok);
}

.coach-slot-chip.range-end {
  background: linear-gradient(135deg, rgba(199, 243, 60, 0.9), rgba(225, 242, 174, 0.7));
  border-color: rgba(199, 243, 60, 0.7);
  color: #04160c;
}

.coach-availability-table {
  min-width: 1500px;
  margin-bottom: 8px;
}

.coach-availability-table th {
  position: relative;
  white-space: nowrap;
}

.coach-slot-count {
  display: block;
  margin-top: 2px;
  font-size: var(--text-3xs);
  font-weight: 700;
  color: var(--muted);
  text-transform: none;
  letter-spacing: normal;
}

.coach-availability-table th.coach-best-slot {
  background: rgba(199, 243, 60, 0.25);
  color: var(--text);
}

.coach-availability-table th.coach-best-slot .coach-slot-count {
  color: var(--status-ok);
}

.coach-availability-cell {
  cursor: default !important;
  pointer-events: none;
}

.coach-available-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
  min-height: 20px;
}

.coach-available-empty {
  color: var(--muted);
  font-size: var(--text-md);
  font-style: italic;
}

.coach-player-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(199, 243, 60, 0.4);
  background: rgba(199, 243, 60, 0.14);
  color: var(--status-ok);
  font-weight: 700;
  font-size: var(--text-sm);
}

.coach-player-chip.no-discord {
  border-color: rgba(255, 176, 32, 0.45);
  background: rgba(255, 176, 32, 0.14);
  color: #ffd98e;
}

.coach-convoke-message {
  width: 100%;
  min-height: 60px;
  margin-bottom: 16px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
  resize: vertical;
}

.coach-convoke-message:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

/* ===== COACH - SCOREBOARD ===== */
#coachScoreboardMatchSelect {
  width: 100%;
  max-width: 420px;
  margin-top: 4px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
}

#coachScoreboardMatchSelect:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

.coach-scoreboard-method-select {
  width: 100%;
  max-width: 420px;
  margin-top: 8px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
}

.coach-scoreboard-method-select:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

.coach-scoreboard-method-select:disabled {
  opacity: 0.5;
}

/* ===== ADMIN - SUIVI JOUEUR ===== */
.player-tracking-controls {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.player-tracking-controls select {
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.2);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-family: inherit;
  min-width: 200px;
}

.player-tracking-controls select:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.7);
  box-shadow: var(--ring);
}

.coach-scoreboard-table {
  table-layout: auto;
  width: auto;
  min-width: 100%;
}

.coach-scoreboard-table th:first-child,
.coach-scoreboard-table td:first-child {
  width: 140px;
  text-align: left;
  padding-left: 12px;
}

/* Method 1/2 add several stat columns (R, KAST, ADR, ACS, Plants, Defuses) -
   without a floor width:100% + table-layout:auto squeezes every column down
   to near-unreadable in a narrow modal. Give each its own minimum so the
   table overflows into .planning-table-scroll's horizontal scroll instead. */
.coach-scoreboard-table th:not(:first-child):not(:last-child),
.coach-scoreboard-table td:not(:first-child):not(:last-child) {
  min-width: 72px;
}

.coach-scoreboard-table th:last-child,
.coach-scoreboard-table td:last-child {
  width: 44px;
  min-width: 44px;
}

/* Beats the td:not(:first-child):not(:last-child) floor above, which is
   more specific (two :not() pseudo-classes) despite coming first. */
.coach-scoreboard-table td.scoreboard-impact-cell {
  min-width: 150px !important;
}

.coach-scoreboard-table.coach-readonly .scoreboard-remove-row {
  display: none;
}
.coach-scoreboard-table.coach-readonly input,
.coach-scoreboard-table.coach-readonly select {
  pointer-events: none;
  opacity: 0.7;
}

.scoreboard-input {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  padding: 8px 6px;
  border-radius: var(--radius);
  border: 1px solid rgba(199, 243, 60, 0.16);
  background: rgb(var(--ink-rgb) / 0.03);
  color: var(--text);
  font-size: var(--text-md);
  text-align: center;
}

.scoreboard-player {
  text-align: left;
  font-weight: 700;
}

.scoreboard-input:focus {
  outline: none;
  border-color: rgba(199, 243, 60, 0.6);
  box-shadow: var(--ring);
}

.coach-create-match-form {
  padding: 18px 20px;
  margin-bottom: 20px;
  border-radius: var(--radius-card);
  border: 1px solid rgba(199, 243, 60, 0.14);
  background: rgb(var(--ink-rgb) / 0.02);
}

.coach-scoreboard-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.scoreboard-impact {
  display: inline-flex;
  min-width: 40px;
  justify-content: center;
  padding: 6px 10px;
  border-radius: 999px;
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--muted);
  background: rgb(var(--ink-rgb) / 0.04);
}

.scoreboard-impact.positive {
  color: var(--accent-ink);
  background: rgba(199, 243, 60, 0.14);
}

.scoreboard-impact.negative {
  color: var(--danger);
  background: rgba(255, 92, 122, 0.14);
}

.scoreboard-impact-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.scoreboard-perf-tag {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted);
  white-space: nowrap;
}

.scoreboard-perf-tag.positive {
  color: var(--accent-ink);
}

.scoreboard-perf-tag.negative {
  color: var(--danger);
}

/* ===== COACH - CLASSEMENT IMPACT ===== */
.coach-rank-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

.coach-rank-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  border: 1px solid rgb(var(--ink-rgb) / 0.14);
}

.coach-rank-move {
  flex: 0 0 18px;
  text-align: center;
  font-weight: 700;
  color: var(--muted);
}

.coach-rank-move-up {
  color: var(--accent-ink);
}

.coach-rank-move-down {
  color: var(--danger);
}

.coach-pending-pracc-wrap {
  margin-bottom: 16px;
}

.coach-pending-pracc-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

.coach-pending-pracc-item {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  border: 1px solid rgba(122, 230, 74, 0.3);
}

.coach-pending-pracc-info {
  flex: 1;
  min-width: 200px;
}

.coach-pending-pracc-info strong {
  display: block;
}

.coach-pending-pracc-info span {
  font-size: var(--text-xs);
  color: var(--muted);
}

.coach-pending-pracc-actions {
  display: flex;
  gap: 8px;
}

.coach-stats-group {
  margin-bottom: 16px;
  border: 1px solid rgb(var(--ink-rgb) / 0.12);
  border-radius: var(--radius-card);
  background: var(--surface-2);
  overflow: hidden;
}

.coach-stats-group summary {
  list-style: none;
  cursor: pointer;
  padding: 14px 18px;
  font-size: var(--text-base);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
}

.coach-stats-group summary::-webkit-details-marker {
  display: none;
}

.coach-stats-group summary::after {
  content: '▸';
  color: var(--muted);
  transition: transform 0.15s ease;
}

.coach-stats-group[open] summary::after {
  transform: rotate(90deg);
}

.coach-stats-group summary:hover {
  background: rgb(var(--ink-rgb) / 0.05);
}

.coach-stats-group-body {
  padding: 0 18px 18px;
}

.coach-ai-analysis-wrap {
  margin-top: 20px;
}

.coach-ai-analysis-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.coach-ai-analysis-actions button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.coach-ai-analysis-result {
  margin-top: 10px;
  padding: 14px 16px;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  border: 1px solid rgb(var(--ink-rgb) / 0.14);
  white-space: pre-wrap;
  line-height: 1.5;
}

.coach-ai-analysis-result:empty {
  display: none;
}

.coach-rank-name {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.coach-rank-perf {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--muted);
  white-space: nowrap;
}

.coach-rank-perf.positive {
  color: var(--accent-ink);
}

.coach-rank-perf.negative {
  color: var(--danger);
}

.coach-rank-score {
  flex: 0 0 auto;
  min-width: 36px;
  text-align: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-weight: 800;
  font-size: var(--text-sm);
  background: rgb(var(--ink-rgb) / 0.05);
  color: var(--text);
}

/* ===== TOURNAMENT REGISTRATION (page-tournoi) ===== */
.tournament-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 8px;
}

/* .tournament-form is a shared utility class used by several admin forms
   too - the card treatment is scoped to the public registration form only
   so it doesn't nest a second border inside already-bordered admin panels. */
.tournament-panel .tournament-form {
  padding: 24px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
}

.tournament-form-row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.tournament-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-width: 200px;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
}

.tournament-field-tag {
  flex: 0 0 140px;
  min-width: 100px;
}

.tournament-players-label {
  margin: 4px 0 -4px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent-ink);
}

.tournament-players-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

@media (max-width: 560px) {
  .tournament-players-list {
    grid-template-columns: 1fr;
  }
}

.tournament-player-input {
  width: 100%;
}

.tournament-form-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 4px;
}

/* Toggle "chip": the whole row is clickable (native <input> hidden but
   still real and keyboard-accessible), lights up in lime when checked -
   deliberately louder than a bare native checkbox, which reads as barely
   visible on a black background and gives no feedback on what it affects. */
.tournament-field-checkbox {
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease);
}

.tournament-field-checkbox:hover {
  border-color: var(--accent-ink);
}

.tournament-field-checkbox input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.tournament-field-checkbox::before {
  content: '';
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background-color: transparent;
  background-repeat: no-repeat;
  background-position: center;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.tournament-field-checkbox:has(input:checked) {
  border-color: var(--accent-ink);
  background: var(--surface-1);
}

.tournament-field-checkbox:has(input:checked)::before {
  background-color: var(--accent-ink);
  border-color: var(--nbk-lime);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}

.toggle-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--text);
}

.toggle-text small {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-transform: none;
  letter-spacing: normal;
}

.toggle-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 4px 0;
}

/* ===== ADMIN NEWS LIST ===== */
.admin-news-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

.admin-news-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--surface-1);
  border: 1px solid var(--border);
}

.admin-news-row-thumb {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  background-size: cover;
  background-position: center;
}

.admin-news-row-info {
  flex: 1;
  min-width: 0;
}

.admin-news-row-title {
  font-weight: 700;
  font-size: var(--text-md);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin-news-row-meta {
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.admin-news-row-badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}

.admin-news-row-badge.published {
  color: var(--nbk-black);
  border-color: var(--accent-ink);
  background: var(--nbk-lime);
}

.admin-news-row-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.tournament-info {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 8px 0 24px;
  padding: 20px;
  border-radius: var(--radius-card);
  background: var(--surface-1);
  border: 1px solid var(--border);
}

.tournament-info-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.tournament-badge,
.tournament-tag {
  padding: 5px 12px;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tournament-badge-open {
  color: var(--nbk-black);
  background: var(--nbk-lime);
  border: none;
  animation: badgePulse 2s var(--ease) infinite;
}

@keyframes badgePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(199, 243, 60, 0.45); }
  50% { box-shadow: 0 0 0 6px rgba(199, 243, 60, 0); }
}

.tournament-tag {
  font-weight: 600;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border);
}

.tournament-info-title {
  margin: 0;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--text-2xl);
}

.tournament-info-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.tournament-info-meta-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 24px 14px 0;
  margin-right: 24px;
  border-right: 1px solid var(--border);
}

.tournament-info-meta-item:last-child {
  border-right: none;
}

/* The right border is a column divider. Once .tournament-info-meta wraps to
   one item per row on a phone, it stops separating columns and just hangs
   as a stray vertical rule beside the text. */
@media (max-width: 640px) {
  .tournament-info-meta-item {
    width: 100%;
    padding-right: 0;
    margin-right: 0;
    border-right: none;
  }

  .tournament-info-meta-item + .tournament-info-meta-item {
    border-top: 1px solid var(--border);
  }
}

.tournament-info-meta-label {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent-ink);
}

.tournament-info-meta-value {
  font-size: var(--text-md);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.tournament-info-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.6;
}

.tournament-info-body p {
  margin: 0;
}

.tournament-info-body strong {
  color: var(--text);
}

.tournament-info-reglement a {
  color: var(--accent-ink);
}

.tournament-info-reglement {
  font-style: normal;
}

.tournament-info-boxes {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.tournament-info-box {
  flex: 1;
  min-width: 220px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: transparent;
  border: 1px solid var(--nbk-lime);
}

.tournament-info-box-label {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent-ink);
}

.tournament-info-box p:last-child {
  margin: 0;
  font-size: var(--text-md);
}

/* ===== MOBILE REFINEMENTS ===============================================
   Everything added after the initial responsive pass (compte page account
   card, coach tabs, modal cards) never got phone-width treatment - this
   patches the pieces that actually break or feel cramped under 480-640px.
   =========================================================================== */
@media (max-width: 640px) {
  /* .account-left-col has flex-shrink: 0 at a fixed 280px, so once logged
     in it doesn't fit the auth-card's available width on a phone and forces
     horizontal scroll on the whole Compte page. */
  .account-left-col {
    flex: 1 1 100%;
  }

  .account-stats-col {
    flex: 1 1 100%;
    min-width: 0;
  }

  .coach-team-tabs {
    flex-wrap: wrap;
  }
}

@media (max-width: 480px) {
  .auth-card,
  .player-profile-card,
  .beta-modal-card {
    padding: 24px 20px;
  }

  .beta-modal-overlay {
    padding: 16px;
  }
}

/* ===== DASHBOARD STAFF (hub for Admin/Coach/Régie) ===== */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}

.dashboard-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 24px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}

.dashboard-card:hover,
.dashboard-card:focus-visible {
  border-color: var(--accent-ink);
  background: var(--surface-2);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.dashboard-card svg {
  color: var(--accent-ink);
}

.dashboard-card h3 {
  margin: 0;
  font-size: var(--text-base);
}

.dashboard-card p {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.5;
}

/* ===== FOOTER ===== */
.site-footer {
  position: relative;
  z-index: 1;
  margin-top: 40px;
  padding: 48px 28px 28px;
  border-top: 1px solid var(--border);
  overflow: hidden;
}

.site-footer::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--nbk-lime-soft) 20%, var(--nbk-lime) 50%, var(--nbk-lime-soft) 80%, transparent);
  opacity: 0.5;
}

/* Was bleeding off the right edge, cut mid-letter at most viewport widths
   - read as a layout bug rather than a deliberate brand mark. Centered and
   outlined instead, so it stays legible as a watermark regardless of width. */
.site-footer-watermark {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.12em;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(60px, 11vw, 160px);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: transparent;
  -webkit-text-stroke: 1px rgb(var(--ink-rgb) / 0.06);
  pointer-events: none;
  line-height: 1;
  white-space: nowrap;
}

.site-footer-inner {
  position: relative;
  max-width: 1280px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 32px;
}

.footer-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.footer-col .caption {
  margin-bottom: 4px;
}

.footer-col a {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: var(--text-md);
  transition: color 0.18s var(--ease);
}

.footer-col a:hover {
  color: var(--accent-ink);
}

.footer-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-xl);
  letter-spacing: -0.02em;
}

.footer-tagline {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-md);
  max-width: 32ch;
}

.footer-mentions {
  margin: 0;
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}

.footer-thanks {
  margin-top: 4px;
  color: var(--accent-ink);
  opacity: 0.75;
}

@media (max-width: 768px) {
  .site-footer-inner {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 480px) {
  .site-footer-inner {
    grid-template-columns: 1fr;
  }
}

/* ===== BOUTIQUE E-COMMERCE ===== */
.boutique-toolbar {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 24px;
  padding: 20px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-1);
}

.boutique-search-input {
  width: 100%;
  max-width: 420px;
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 10px 14px;
  border-radius: var(--radius);
  font-family: var(--font-body);
}

.boutique-search-input:focus {
  outline: none;
  border-color: var(--accent-ink);
  box-shadow: var(--ring);
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.18s var(--ease), color 0.18s var(--ease), background 0.18s var(--ease);
}

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

.chip.active {
  background: var(--nbk-lime);
  border-color: var(--accent-ink);
  color: var(--nbk-black);
}

.boutique-toolbar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.boutique-select {
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 9px 30px 9px 12px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23ffffff' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

.boutique-price-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-tertiary);
}

.boutique-price-filter input {
  width: 90px;
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 8px 10px;
  border-radius: var(--radius);
  font-family: var(--font-body);
}

.boutique-price-filter input:focus,
.boutique-select:focus {
  outline: none;
  border-color: var(--accent-ink);
  box-shadow: var(--ring);
}

.boutique-availability-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-md);
  color: var(--text-secondary);
  cursor: pointer;
}

.boutique-card-badge--new,
.boutique-card-badge--sale {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 1;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  background: var(--nbk-lime);
  color: var(--nbk-black);
}

.boutique-card-badge--sale {
  background: var(--nbk-white);
}

.boutique-card-badge--soon {
  background: #ffb020;
  color: var(--nbk-black);
  font-variant-numeric: tabular-nums;
}

.boutique-product-countdown {
  margin: 0 0 6px;
  padding: 8px 12px;
  border-radius: var(--radius);
  background: rgba(255, 176, 32, 0.12);
  border: 1px solid #ffb020;
  color: #ffb020;
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
}

.boutique-card-badge--new + .boutique-card-badge--sale,
.boutique-card-badge--oos + .boutique-card-badge--new,
.boutique-card-badge--oos + .boutique-card-badge--sale {
  top: 48px;
}

.boutique-price-old {
  color: var(--text-tertiary);
  text-decoration: line-through;
  font-weight: 400;
}

.boutique-card--sm {
  min-height: 180px;
}

.boutique-product-gallery {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.boutique-gallery-thumbs {
  display: flex;
  gap: 8px;
}

/* ---- 360° drag-to-rotate viewer (product with 4+ images) ---- */
.boutique-spin-viewer {
  position: relative;
  height: 280px;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.boutique-spin-viewer.is-dragging {
  cursor: grabbing;
}

.boutique-spin-hint {
  position: absolute;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.65);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.3s var(--ease);
}

.boutique-spin-dots {
  display: flex;
  justify-content: center;
  gap: 5px;
}

.boutique-spin-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--border-strong);
}

.boutique-spin-dot.active {
  background: var(--nbk-lime);
}

.boutique-gallery-thumb {
  width: 56px;
  height: 56px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background-color: var(--surface-2);
  background-size: cover;
  background-position: center;
  cursor: pointer;
  padding: 0;
}

.boutique-gallery-thumb.active {
  border-color: var(--accent-ink);
}

.boutique-qty-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 12px 0;
}

.boutique-qty-row input {
  width: 70px;
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 8px 10px;
  border-radius: var(--radius);
}

.boutique-similar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

/* ---- Cart nav button ---- */
.nav-cart-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border: none;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  border-left: 1px solid var(--border);
  margin-left: 4px;
  padding-left: 12px;
}

/* ===== BASCULE DE THÈME ===== */
.nav-theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 0.18s var(--ease), transform 0.18s var(--ease);
}

.nav-theme-btn:hover { color: var(--accent-ink); }
.nav-theme-btn:active { transform: scale(0.92); }

/* Une seule des deux icônes est visible : celle du thème qu'on obtiendrait en
   cliquant. En sombre on propose le soleil, en clair la lune. */
.nav-theme-icon { display: none; }
.nav-theme-icon--sun { display: block; }

:root[data-theme="light"] .nav-theme-icon--sun { display: none; }
:root[data-theme="light"] .nav-theme-icon--moon { display: block; }

.nav-cart-count {
  position: absolute;
  top: 2px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--nbk-lime);
  color: var(--nbk-black);
  font-size: var(--text-3xs);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- Cart drawer ---- */
.cart-drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 100000;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  justify-content: flex-end;
}

.cart-drawer {
  width: 100%;
  max-width: 400px;
  height: 100%;
  background: var(--field-bg);
  border-left: 1px solid var(--border);
  padding: 24px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.cart-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.cart-drawer-header h2 {
  text-transform: uppercase;
}

.cart-items-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1;
}

.cart-item {
  display: flex;
  gap: 12px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.cart-item-image {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: var(--radius);
  background-color: var(--surface-2);
  background-size: cover;
  background-position: center;
}

.cart-item-info {
  flex: 1;
  min-width: 0;
}

.cart-item-name {
  margin: 0 0 2px;
  font-weight: 700;
  font-size: var(--text-md);
}

.cart-item-meta {
  margin: 0 0 4px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

.cart-item-price {
  margin: 0 0 6px;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--text-md);
}

.cart-item-qty {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2px 10px;
}

.cart-qty-btn {
  background: none;
  border: none;
  color: var(--text);
  font-size: var(--text-base);
  cursor: pointer;
  padding: 2px 4px;
}

.cart-item-remove {
  flex: none;
  align-self: flex-start;
  background: none;
  border: none;
  color: var(--text-tertiary);
  cursor: pointer;
  font-size: var(--text-md);
}

.cart-item-remove:hover {
  color: var(--danger);
}

.cart-summary {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.cart-summary-row {
  display: flex;
  justify-content: space-between;
  padding: 4px 0;
  color: var(--text-secondary);
  font-size: var(--text-md);
}

.cart-summary-total {
  color: var(--text);
  font-weight: 700;
  font-size: var(--text-lg);
  font-family: var(--font-display);
}

.cart-drawer-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
}

.cart-drawer-actions .btn {
  width: 100%;
}

/* ---- Checkout modal ---- */
.checkout-card {
  max-width: 480px;
}

.checkout-summary {
  margin: 16px 0;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}

.checkout-line {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  font-size: var(--text-md);
  color: var(--text-secondary);
}

.checkout-promo-row {
  display: flex;
  gap: 8px;
}

.checkout-field-row {
  display: flex;
  gap: 8px;
}

.checkout-field-row .auth-field {
  flex: 1;
}

.checkout-promo-row input {
  flex: 1;
}

.checkout-line-discount {
  color: var(--accent-ink);
}

.checkout-line-total {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  color: var(--text);
  font-weight: 700;
  font-family: var(--font-display);
}

@media (max-width: 640px) {
  .cart-drawer {
    max-width: 100%;
  }
  .boutique-toolbar-row {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---- Admin: variants editor + image gallery preview ---- */
.bp-variants-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 8px 0;
}

.bp-variant-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.bp-variant-row input[type="text"] {
  flex: 1;
}

.bp-variant-row input[type="number"] {
  width: 100px;
}

.bp-variant-remove {
  flex: none;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-tertiary);
  border-radius: var(--radius);
  width: 36px;
  height: 36px;
  cursor: pointer;
}

.bp-variant-remove:hover {
  color: var(--danger);
  border-color: var(--danger);
}

.bp-image-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0 16px;
}

.bp-image-thumb {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background-color: var(--surface-2);
  background-size: cover;
  background-position: center;
}

.bp-image-thumb.is-main::after {
  content: 'Principale';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--nbk-lime);
  color: var(--nbk-black);
  font-size: var(--text-3xs);
  text-align: center;
  font-weight: 700;
  text-transform: uppercase;
  padding: 1px 0;
}

.bp-image-thumb-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--danger);
  color: #fff;
  border: none;
  font-size: var(--text-3xs);
  line-height: 1;
  cursor: pointer;
}

.admin-order-status-select {
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 6px 10px;
  border-radius: var(--radius);
  font-size: var(--text-sm);
}

.admin-order-tracking-input {
  border: 1px solid var(--border);
  background: var(--field-bg);
  color: var(--text);
  padding: 6px 10px;
  border-radius: var(--radius);
  font-size: var(--text-sm);
  width: 120px;
}

.bracket-display { display: flex; flex-direction: column; gap: 40px; margin-top: 16px; }

.bracket-side-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px;
  font-size: var(--text-base);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.bracket-side-icon { font-size: var(--text-base); filter: grayscale(1) opacity(0.7); }
.bracket-side--grand_final .bracket-side-title { color: var(--accent-ink); }
.bracket-side--grand_final .bracket-side-icon { filter: none; }

.bracket-rounds { position: relative; display: flex; gap: 32px; overflow-x: auto; padding: 4px 4px 12px; }
.bracket-round { display: flex; flex-direction: column; justify-content: space-around; gap: 20px; min-width: 220px; }
.bracket-round-title {
  align-self: flex-start;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}

.bracket-lines { position: absolute; top: 0; left: 0; pointer-events: none; overflow: visible; }
.bracket-line { fill: none; stroke: var(--border-strong); stroke-width: 1.5; stroke-linecap: round; }
.bracket-line.is-decided { stroke: var(--nbk-lime); opacity: 0.45; }

.bracket-match {
  position: relative;
  z-index: 1;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-1);
  overflow: hidden;
  transition: border-color 0.16s var(--ease, ease), transform 0.16s var(--ease, ease), box-shadow 0.16s var(--ease, ease);
}
.bracket-match:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.bracket-match[data-status="pending"] { opacity: 0.5; border-style: dashed; }
.bracket-match[data-status="ready"] { border-color: rgba(199, 243, 60, 0.4); box-shadow: 0 0 0 1px rgba(199, 243, 60, 0.1); }
.bracket-side--grand_final .bracket-match { border-color: rgba(199, 243, 60, 0.35); background: linear-gradient(180deg, rgba(199, 243, 60, 0.05), transparent 60%); }

.bracket-match-team {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 12px;
  font-size: var(--text-md);
  color: var(--text-secondary);
}
.bracket-match-team + .bracket-match-team { border-top: 1px solid var(--border); }
.bracket-match-team-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bracket-match-team-tag { color: var(--muted); font-size: 0.78em; }
.bracket-match-team-tbd { color: var(--muted); font-style: italic; }
.bracket-match-team-score { flex-shrink: 0; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text-secondary); }
.bracket-match-team.is-winner { color: var(--text); font-weight: 700; background: rgba(199, 243, 60, 0.07); }
.bracket-match-team.is-winner .bracket-match-team-name::before { content: '▸ '; color: var(--accent-ink); }
.bracket-match-team.is-winner .bracket-match-team-score { color: var(--accent-ink); }
.bracket-match-team.is-loser { opacity: 0.55; }
.bracket-match-team.is-loser .bracket-match-team-score { color: var(--muted); }

.bracket-match-inputs { display: flex; gap: 6px; margin-top: 2px; padding: 8px 12px; align-items: center; border-top: 1px solid var(--border); background: rgba(0, 0, 0, 0.15); }
.bracket-match-inputs-sep { color: var(--muted); }
.bracket-score-input { width: 40px; border: 1px solid var(--border); background: var(--nbk-black); color: var(--text); border-radius: var(--radius); padding: 4px 6px; font-size: var(--text-sm); text-align: center; }
.bracket-score-input:focus { outline: none; border-color: var(--accent-ink); }

/* Bye du système suisse : la carte n'attend personne, elle n'a simplement pas
   d'adversaire. Le ton est celui d'un "à déterminer" - présent mais en
   retrait - sans l'italique qui suggérerait qu'il reste quelque chose à
   remplir. */
.bracket-match-team.is-bye .bracket-match-team-name { color: var(--muted); }

/* Format de série, dans l'en-tête de ronde. Le titre passe en flex pour
   accueillir le contrôle sans que la pastille ne s'étire. */
.bracket-round-title { display: flex; align-items: center; gap: 8px; }
.bracket-round-series,
.bracket-round-series-chip {
  border: 1px solid var(--border);
  /* Surface opaque plutôt que --nbk-black : en thème clair la puce restait
     noire alors que son texte suivait l’encre du thème. */
  background: var(--surface-solid);
  color: var(--text-secondary);
  border-radius: 999px;
  padding: 1px 7px;
  font: inherit;
  font-size: 0.9em;
  letter-spacing: 0;
  line-height: 1.6;
}
.bracket-round-series { cursor: pointer; }
.bracket-round-series:focus-visible { outline: 2px solid var(--nbk-lime); outline-offset: 1px; }
.bracket-round-series-chip { color: var(--muted); }

/* ---------------------------------------------------------------------------
   Classement du système suisse - la vue principale de ce format : sans arbre
   à suivre du regard, c'est le tableau qui porte l'information.
   --------------------------------------------------------------------------- */
.swiss-standings { margin-bottom: 28px; }
.swiss-standings-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.swiss-standings-head .bracket-side-title { margin: 0; }
.swiss-progress {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Le tableau défile dans son propre cadre plutôt que d'élargir la page :
   cinq colonnes ne tiennent pas sur un écran de téléphone. */
.swiss-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-card); }
.swiss-table { width: 100%; border-collapse: collapse; font-size: var(--text-md); }
.swiss-table th,
.swiss-table td { padding: 8px 12px; text-align: left; white-space: nowrap; }
.swiss-table thead th {
  background: var(--surface-2);
  color: var(--muted);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.swiss-table tbody tr + tr td { border-top: 1px solid var(--border); }
.swiss-table tbody tr:hover td { background: rgb(var(--ink-rgb) / 0.02); }
.swiss-table td { color: var(--text-secondary); }
.swiss-rank { color: var(--muted); font-variant-numeric: tabular-nums; width: 1%; }
/* Les colonnes chiffrées s'alignent sur la même largeur de glyphe, sinon le
   classement paraît désaligné d'une ligne à l'autre. */
.swiss-record,
.swiss-num { font-variant-numeric: tabular-nums; }
.swiss-record { color: var(--text); font-weight: 700; }
.swiss-record-sep { color: var(--muted); margin: 0 2px; font-weight: 400; }

/* Les trois premières places, repère visuel immédiat dans un tableau qui peut
   compter des dizaines de lignes. */
.swiss-table tbody tr:nth-child(-n+3) .swiss-rank { color: var(--accent-ink); font-weight: 700; }

/* Bascule vers le playoff - proposée sous le classement plutôt que dans le
   panneau de lancement du haut, parce qu'elle dépend de ce classement et
   qu'elle ne remplace pas le bracket, elle le prolonge. */
.swiss-qualify {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-2);
}
.swiss-qualify-label { font-size: var(--text-md); color: var(--text-secondary); }

.tournament-field-inline { display: inline-flex; align-items: center; gap: 8px; font-size: var(--text-md); color: var(--text-secondary); }
.tournament-field-inline input { width: 64px; border: 1px solid var(--border); background: var(--nbk-black); color: var(--text); border-radius: var(--radius); padding: 6px 8px; text-align: center; }
.tournament-field-inline input:focus { outline: none; border-color: var(--accent-ink); }

/* ---------------------------------------------------------------------------
   Zones tactiles - WCAG 2.5.5 (et les recommandations Apple comme Material)
   demandent 44px minimum sous le doigt. Mesuré sur la page d'accueil en 375px :
   20 cibles sur 34 en dessous, dont des liens de 18px de haut ("Tracker",
   "Suivre") et les liens du pied de page à 22px. Un lien de 18px, on le rate.

   Restreint à `pointer: coarse` : à la souris, 18px se cliquent très bien, et
   toucher au bureau ferait bouger des mises en page qui n'ont pas ce problème.
   --------------------------------------------------------------------------- */
@media (pointer: coarse) {
  /* Padding pour la zone, marge négative pour annuler l'effet sur la mise en
     page : le lien garde exactement sa place, seule la surface sensible grandit.

     L'expansion est asymétrique - le voisin du dessus n'est qu'à 6px, et
     déborder dessus ferait ouvrir le tracker en visant le nom de l'agent.
     Vers le bas il y a 79px de libre dans la carte, on prend là. */
  .player-card-tracker {
    padding-top: 6px;
    padding-bottom: 20px;
    margin-top: -6px;
    margin-bottom: -20px;
  }

  .stream-offline-link {
    padding-top: 4px;
    padding-bottom: 22px;
    margin-top: -4px;
    margin-bottom: -22px;
  }

  /* Ici, pas de marge négative. Les liens du pied de page ne sont espacés que
     de 10px : deux zones de 44px se chevaucheraient de 12px, et on activerait
     le lien voisin - l'inverse du but recherché. On écarte donc réellement,
     le pied de page gagne en hauteur sur mobile. C'est le prix d'une cible
     atteignable, et un pied de page est l'endroit où on peut le payer. */
  .footer-col a {
    padding-block: 11px;
  }

  .nav-cart-btn {
    width: 44px;
    height: 44px;
  }
}

/* ---------------------------------------------------------------------------
   Vie de la page - le hero avait déjà sa mise en scène, le reste était figé.
   Trois gestes en mouvement pur : aucune couleur nouvelle, tout s'appuie sur
   les jetons existants.

   Le bloc global `prefers-reduced-motion` plus haut neutralise déjà les
   transitions ci-dessous ; le JS refuse en plus de poser les attributs, pour
   que rien ne reste à moitié révélé.
   --------------------------------------------------------------------------- */

/* Titres de section : dévoilés derrière un masque au lieu d'être là depuis
   toujours. C'est ce qui donne à une section l'impression de commencer.

   Les sélecteurs ne mordent que si l'attribut est posé, donc si le JS ne
   tourne pas (erreur, CDN coupé) les titres s'affichent normalement - on ne
   peut pas se retrouver avec une page de titres invisibles. */
.section-heading h2[data-revealed] {
  transition:
    clip-path 0.65s var(--ease),
    transform 0.65s var(--ease),
    opacity 0.4s var(--ease);
}

.section-heading h2[data-revealed="pending"] {
  /* Coupé sous sa propre ligne de base : le titre monte de derrière, il
     n'apparaît pas en fondu par-dessus le fond. */
  clip-path: inset(0 0 100% 0);
  transform: translateY(0.22em);
  opacity: 0;
}

.section-heading h2[data-revealed="done"] {
  /* -12% en bas plutôt que 0 : à 0 le masque rogne les jambages des lettres
     (le J de "Joueurs", le p de "Compétition") une fois l'animation finie. */
  clip-path: inset(0 0 -12% 0);
  transform: none;
  opacity: 1;
}

/* Halo suivant le pointeur sur les tuiles de l'accueil. Le JS ne met à jour
   que deux propriétés personnalisées ; c'est le compositeur qui peint, donc
   déplacer la souris ne déclenche aucun recalcul de mise en page.

   `--surface-2` est le jeton de surface déjà utilisé partout - c'est un effet
   de lumière, pas une couleur de plus. */
.home-grid-cell::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.28s var(--ease);
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    var(--surface-2),
    transparent 62%
  );
}

.home-grid-cell:hover::after {
  opacity: 1;
}

/* Les chiffres comptent en montant : pendant l'animation ils changent de
   largeur à chaque dizaine franchie. Le chasse fixe évite que la ligne
   entière tressaute - le JS fige la largeur en plus, ceci le double au cas
   où la police de chiffres proportionnels reprendrait la main. */
.stat-number {
  font-variant-numeric: tabular-nums;
}


/* ---------------------------------------------------------------------------
   Fiche joueur en onglets - mesuré avant/après sur un profil réel.

   Empilée, la fiche faisait 1915px de contenu pour 763px visibles. L'élargir
   la ramenait à 1158px, mais il restait 395px à parcourir. Or « aucun
   défilement » ne dépend pas que du contenu : à 900px de haut il ne rentre que
   quatre lignes de liste, à 800px deux, à 720px une seule. Tout montrer d'un
   coup sans défiler est donc impossible sur un portable ordinaire.

   Les onglets sont la seule mise en page qui y arrive sans rien retirer :
   chaque volet plafonne autour de 450px, et l'en-tête reste visible en
   permanence pour qu'on sache toujours de quel joueur on parle.
   --------------------------------------------------------------------------- */
.pp-tabs {
  display: flex;
  gap: 4px;
  margin: 18px 0 16px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--border);
  /* Trois onglets tiennent en 343px sur mobile ; au-delà on fait défiler la
     barre plutôt que de replier les libellés sur deux lignes. */
  overflow-x: auto;
  scrollbar-width: none;
}

.pp-tabs::-webkit-scrollbar { display: none; }

.pp-tab {
  position: relative;
  flex: none;
  padding: 9px 14px;
  border: none;
  background: none;
  color: var(--text-tertiary);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.18s var(--ease);
}

.pp-tab:hover { color: var(--text-secondary); }

.pp-tab.is-active { color: var(--text); }

/* Le soulignement est porté par l'onglet et non par la barre : il se déplace
   avec lui sans qu'aucune position n'ait à être calculée en JS. */
.pp-tab.is-active::after {
  content: '';
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -3px;
  height: 2px;
  background: var(--nbk-lime);
}

.pp-panel { animation: pp-panel-in 0.25s var(--ease); }

@keyframes pp-panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

@media (min-width: 1100px) {
  /* Plus large qu'avant, mais bien moins qu'il n'aurait fallu sans onglets :
     c'est la hauteur qui commandait, pas la largeur. */
  #playerProfileOverlay .player-profile-card {
    max-width: 940px;
    max-height: 92vh;
  }

  /* En-tête sur une ligne : 170px de haut pour un avatar et un nom, c'était
     autant de moins pour le contenu. */
  #playerProfileContent .player-profile-header { align-items: center; }

  #playerProfileContent .player-profile-header > div {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
  }

  #playerProfileContent .player-profile-name { margin: 0; }

  /* Les six tuiles tiennent sur une ligne. */
  #playerProfileContent .coach-stat-grid { grid-template-columns: repeat(6, 1fr); }
  #playerProfileContent .coach-stat-value { font-size: var(--text-xl); }
  #playerProfileContent .coach-stat-label {
    font-size: var(--text-3xs);
    letter-spacing: 0.04em;
  }

  /* Les deux graphiques côte à côte : c'est le volet le plus large, et celui
     qui gagne le plus à l'être.
     `:not([hidden])` est indispensable : l'attribut hidden ne masque que par
     le `display:none` de la feuille par défaut du navigateur, qu'une règle
     d'auteur posant `display` écrase sans bruit. Sans ce garde, les deux
     graphiques restaient affichés sous l'onglet "Vue d'ensemble". */
  [data-pp-panel="graphiques"]:not([hidden]) {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 24px;
    align-items: start;
  }

}

/* Écrans courts (portables 13-14" en 768p, fenêtre non maximisée) : à 720px de
   haut il restait 80px à parcourir sur le volet le plus dense. On récupère ces
   pixels sur les marges plutôt que sur le contenu - c'est exactement là que la
   place manque, et nulle part ailleurs. */
@media (min-width: 1100px) and (max-height: 820px) {
  #playerProfileOverlay .player-profile-card {
    max-height: 96vh;
    padding: 20px 24px;
  }

  #playerProfileContent .pp-tabs { margin: 12px 0 12px; }

  #playerProfileContent .player-profile-header { margin-bottom: 4px; }
}

/* Le volet "Derniers matchs" répétait son propre titre juste sous l'onglet du
   même nom. Retiré ici seulement : le gabarit est partagé avec la page Compte
   et les panels Admin/Coach, où ce titre est le seul repère de section. Aucune
   perte pour les lecteurs d'écran, le panneau étant déjà nommé par son onglet
   via aria-labelledby. */
[data-pp-panel="matchs"] > .pp-block > .player-profile-section-title,
[data-pp-panel="agents"] > .pp-block > .player-profile-section-title {
  display: none;
}

/* Sur mobile, les six tuiles s'empilaient sur une seule colonne : 582px pour
   six chiffres, et l'onglet Stats redemandait 167px de défilement. En trois
   colonnes compactes elles tiennent sur deux rangées (164px) - les valeurs
   restent lisibles, ce sont surtout les marges qui rétrécissent. */
@media (max-width: 640px) {
  #playerProfileContent .coach-stat-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
  }

  #playerProfileContent .coach-stat-tile { padding: 10px 6px; }
  #playerProfileContent .coach-stat-value { font-size: var(--text-lg); }

  #playerProfileContent .coach-stat-label {
    font-size: var(--text-3xs);
    letter-spacing: 0.02em;
  }
}

/* Listes sur deux colonnes dès 700px, sans attendre l'élargissement de la
   fiche à 1100px : huit matchs empilés font 451px de haut, en deux colonnes
   235px. C'est cette différence qui décide s'il faut défiler ou non, et elle
   vaut aussi sur une tablette ou une fenêtre réduite. */
@media (min-width: 700px) {
  #playerProfileContent .player-profile-matches,
  #playerProfileContent .coach-rank-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 20px;
    align-content: start;
  }
}

/* ---------------------------------------------------------------------------
   Odomètre des statistiques - chaque chiffre est une colonne de 0 à 9 qu'on
   fait glisser derrière une fenêtre d'une ligne de haut.

   Réécrire le nombre entier à chaque image faisait clignoter des chiffres qui
   ne changent pas : pour aller de 0 à 44, celui des dizaines était réécrit des
   dizaines de fois pour n'occuper que deux valeurs. Ici une colonne dont la
   cible est 0 ne bouge tout simplement pas.
   --------------------------------------------------------------------------- */
.odo-digit {
  display: inline-block;
  height: 1em;
  overflow: hidden;
  vertical-align: bottom;
  line-height: 1;
}

.odo-strip {
  display: flex;
  flex-direction: column;
  transform: translateY(0);
  /* Long et très amorti : la colonne parcourt jusqu'à dix chiffres, une durée
     courte donnerait un défilement illisible plutôt qu'un mouvement. */
  transition: transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
}

.odo-strip > span {
  height: 1em;
  line-height: 1;
  /* Chasse fixe : sans elle les dix chiffres n'ont pas la même largeur et la
     colonne tremble latéralement en défilant. */
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Cartes qui répondent au pointeur - inclinaison légère suivant le curseur.
   Réservé au pointeur fin : au doigt il n'y a pas de survol, une carte
   resterait penchée là où on a tapé.
   --------------------------------------------------------------------------- */
@media (pointer: fine) {
  .home-grid-cell,
  .player-card,
  .boutique-card {
    transform:
      perspective(900px)
      rotateX(var(--tilt-x, 0deg))
      rotateY(var(--tilt-y, 0deg));
  }

  /* Ces règles reprennent le soulèvement que les :hover d'origine posaient
     seuls. Elles sont indispensables : deux déclarations `transform` ne se
     cumulent pas, la dernière gagne - l'inclinaison aurait donc effacé le
     soulèvement, ou l'inverse selon l'ordre du fichier. */
  .player-card:hover,
  .player-card:focus-visible {
    transform:
      perspective(900px)
      rotateX(var(--tilt-x, 0deg))
      rotateY(var(--tilt-y, 0deg))
      translateY(-6px);
  }

  .boutique-card:hover {
    transform:
      perspective(900px)
      rotateX(var(--tilt-x, 0deg))
      rotateY(var(--tilt-y, 0deg))
      translateY(-3px);
  }
}

/* Les lignes des listes se posent l'une après l'autre plutôt que d'apparaître
   en bloc. Une `animation` et non une transition pilotée par du JS : elle se
   termine toujours sur l'état visible, donc même si le script échoue ou si
   l'utilisateur a demandé moins de mouvement (le bloc global plus haut ramène
   la durée à zéro), la ligne reste lisible. Impossible d'obtenir une liste
   invisible avec ce motif. */
[data-pp-panel] .player-profile-match,
[data-pp-panel] .coach-rank-row {
  animation: pp-row-in 0.42s var(--ease) both;
}

@keyframes pp-row-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* Le décalage s'arrête à la huitième ligne : au-delà l'attente se verrait plus
   que l'effet, et les listes ne dépassent de toute façon pas huit entrées. */
[data-pp-panel] .player-profile-match:nth-child(2),
[data-pp-panel] .coach-rank-row:nth-child(2) { animation-delay: 40ms; }
[data-pp-panel] .player-profile-match:nth-child(3),
[data-pp-panel] .coach-rank-row:nth-child(3) { animation-delay: 80ms; }
[data-pp-panel] .player-profile-match:nth-child(4),
[data-pp-panel] .coach-rank-row:nth-child(4) { animation-delay: 120ms; }
[data-pp-panel] .player-profile-match:nth-child(5),
[data-pp-panel] .coach-rank-row:nth-child(5) { animation-delay: 160ms; }
[data-pp-panel] .player-profile-match:nth-child(6),
[data-pp-panel] .coach-rank-row:nth-child(6) { animation-delay: 200ms; }
[data-pp-panel] .player-profile-match:nth-child(n+7),
[data-pp-panel] .coach-rank-row:nth-child(n+7) { animation-delay: 240ms; }

/* Les tuiles de stats suivent la même logique. */
[data-pp-panel="stats"] .coach-stat-tile {
  animation: pp-row-in 0.42s var(--ease) both;
}
[data-pp-panel="stats"] .coach-stat-tile:nth-child(2) { animation-delay: 45ms; }
[data-pp-panel="stats"] .coach-stat-tile:nth-child(3) { animation-delay: 90ms; }
[data-pp-panel="stats"] .coach-stat-tile:nth-child(4) { animation-delay: 135ms; }
[data-pp-panel="stats"] .coach-stat-tile:nth-child(5) { animation-delay: 180ms; }
[data-pp-panel="stats"] .coach-stat-tile:nth-child(6) { animation-delay: 225ms; }

/* Diagnostic des salons Discord - séparé de la liste des commandes par un
   filet : c'est un outil de configuration, pas une donnée de commande. */
.admin-discord-diag {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

.admin-discord-diag .tournament-form-row { margin-top: 12px; }

/* Section Développeur vue par un administrateur : présente et lisible, mais
   sans outil. Le liseré rappelle qu'on regarde quelque chose qui ne nous est
   pas destiné, sans pour autant crier à l'erreur. */
.admin-dev-locked {
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}

/* ---------------------------------------------------------------------------
   Panel Développeur - tableau d'état de la configuration et des services.
   Dense et scannable : on vient y chercher la ligne qui cloche, pas lire.
   --------------------------------------------------------------------------- */
.admin-dev-block { margin-bottom: 28px; }

.admin-dev-grid { margin: 12px 0; }

.dev-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 0;
  font-size: var(--text-sm);
  border-bottom: 1px solid var(--border);
}

.dev-row:last-child { border-bottom: none; }

/* La pastille porte l'information : on balaie la colonne de gauche et on
   s'arrête sur la seule qui n'est pas verte. */
.dev-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  /* Le décalage compense l'alignement sur la ligne de base du texte voisin. */
  transform: translateY(-1px);
}

.dev-dot.ok { background: var(--nbk-lime); }
.dev-dot.ko { background: var(--danger); }

.dev-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.dev-detail {
  margin-left: auto;
  text-align: right;
  color: var(--muted);
  font-size: var(--text-xs);
  /* Une URL ou un identifiant long ne doit pas pousser la colonne de gauche
     hors du cadre. */
  overflow-wrap: anywhere;
}

.dev-group { margin: 18px 0 4px; }

/* ===========================================================================
   THÈME CLAIR - surfaces qui restent sombres
   ---------------------------------------------------------------------------
   Trois familles de composants sont sombres par nature et le restent quel que
   soit le thème : les cartes de map (une photo sous un voile), la prévisu de
   l'overlay de diffusion (elle sera incrustée sur une capture de jeu), et le
   bouton noir de la bannière lime. Sur ces îlots, on ré-épingle les jetons de
   texte à leurs valeurs sombres - sinon l'encre du thème clair s'y écrit en
   noir sur noir.
   =========================================================================== */
:root[data-theme="light"] :is(.map-card, .overlay-ban-item, .overlay-live-panel, .pick-choice, .overlay-team, .overlay-panel, .obs-tools-panel,
  .boutique-card, .news-card, .partner-card, .historique-card, .player-card) {
  --text: var(--nbk-white);
  --text-secondary: rgb(255 255 255 / 0.62);
  --text-tertiary: rgb(255 255 255 / 0.47);
  --muted: rgb(255 255 255 / 0.47);
  --accent-ink: var(--nbk-lime);
  --status-ok: #baffd4;
  --status-ko: #ffb3c1;
  color: var(--text);
}

/* Le bouton de la bannière Discord est un aplat noir posé sur le lime : son
   texte doit rester lime vif, pas le lime assombri réservé au papier. */
:root[data-theme="light"] .discord-banner .btn {
  --accent-ink: var(--nbk-lime);
  color: var(--accent-ink);
}

/* ===== SÉLECTEUR DE LANGUE =====
   Deux lettres, même gabarit que la bascule de thème. Le libellé indique la
   langue vers laquelle on bascule. */
.nav-lang-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  transition: color 0.18s var(--ease), transform 0.18s var(--ease);
}

.nav-lang-btn:hover { color: var(--accent-ink); }
.nav-lang-btn:active { transform: scale(0.92); }

/* ===== DÉCLARATION D'ABSENCE (espace joueur) =====
   Encadré dans l'espace Compte, entre l'identité et les statistiques. Il
   n'apparaît que pour un compte lié à un joueur du roster. */
.account-indispo {
  margin-top: 24px;
  padding: 22px 22px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}

.account-indispo-lede {
  margin: 0 0 16px;
  max-width: 62ch;
  color: var(--text-secondary);
  font-size: var(--text-md);
  line-height: 1.6;
}

/* Les intitules des champs etaient de simples noeuds de texte a la taille du
   corps, collés à leur champ : « Du » et « Au » pesaient autant que la phrase
   d'introduction. On les traite comme des etiquettes. */
.account-indispo .form-field {
  gap: 6px;
  color: var(--text-secondary);
  font-family: var(--font-display, inherit);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.account-indispo .form-field input {
  font-size: var(--text-md);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

/* Les deux dates tiennent cote a cote des qu'il y a la place, et passent l'une
   sous l'autre en dessous - c'est la meme information, elle doit se lire d'un
   bloc. */
.account-indispo .form-row-wrap { gap: 12px; align-items: flex-start; }

.account-indispo .form-row:last-child {
  margin-top: 16px;
  flex-wrap: wrap;
  gap: 10px 14px;
}

@media (max-width: 520px) {
  /* Un bouton d'envoi a demi-largeur, aligne a gauche sous des champs pleine
     largeur, donne un formulaire de travers sur telephone. */
  .account-indispo .form-row:last-child .btn { width: 100%; }
  .account-indispo .form-status { width: 100%; }
}

/* Le retour d'envoi parle gris tant qu'il annonce un succès, et rouge quand
   il annonce un refus : c'est la seule information qui doit arrêter l'œil. */
.form-status-error {
  color: var(--danger);
}

/* ===== MAJUSCULES : OU ELLES GAGNENT LEUR PLACE =====
   Le site posait `text-transform: uppercase` par 65 regles, sur 1023 elements.
   Le releve a montre que la plupart sont justes : etiquettes, badges, en-tetes
   de tableau, intitules de champ, boutons, et les 53 titres de section courts
   ("Boutique", "News du mois"), qui portent la voix de la marque.

   Le defaut est ailleurs. La regle `h2` s'applique a tout h2, y compris quand
   son contenu est une phrase : "Treize joueurs, deux equipes." criee perd
   exactement ce qui en faisait une phrase. On rend donc la casse normale la ou
   le texte est une phrase, une question ou un intitule long - pas partout.

   Les noms propres suivent la meme logique : un pseudo s'ecrit comme son
   porteur l'ecrit. Forcer les capitales transformait "SoLa" en "SOLA".

   Place en fin de feuille a dessein : .discord-banner h2, .obs-tools-header h2
   et .player-card-name posent uppercase avec la meme specificite que ces
   selecteurs, donc c'est l'ordre qui tranche. Pas de :where() ici pour la
   meme raison - a specificite nulle, la regle ne gagnerait aucun de ces
   duels. */
.sw-panel__title,
.discord-banner h2,
.obs-tools-header h2,
.legal-page .panel-title,
.player-card-name {
  text-transform: none;
}
