:root {
  /* Refonte « Glitchcraft » (voir DESIGN.md) : tout est un bloc carré, posé
     sur un fond sombre, cerné d'un contour épais et lesté d'une ombre dure
     décalée. Aucun arrondi, aucun dégradé, aucun flou, sauf une lueur
     (marqueur du reel). */
  /* Fonds éclaircis d'un cran (le site paraissait « fort sombre au premier
     regard », 2026-09-22) : les panneaux se détachent du fond. Contours et
     ombres dans un noir adouci (un #060608 faisait trop dur), à peine plus
     clair que le fond mais plus sombre que les panneaux : les blocs restent nets. */
  --bg: #0e0e12;
  --surface-1: #17171d;
  --surface-2: #1d1d24;
  --surface-3: #282830;
  --outline: #111116;
  --outline-inner: #2e2e36;
  --hairline: #26262e;
  --ink: #1c1c22; /* texte posé sur un aplat jaune, vert ou de rareté */
  --text-strong: #ffffff;
  --text: #e8e8e6;
  --text-muted: #9a9aa0;
  /* DESIGN.md propose #6e6e75 : 3,9:1 sur le fond, sous le seuil AA (4,5:1)
     que le même document exige. Éclairci pour rester au-dessus de 4,5:1 sur
     les fonds plus clairs (--surface-3 compris). */
  --text-dim: #929299;
  --text-faint: #4e4e56; /* décor seulement (séparateurs), jamais une information */
  --accent: #ffe900;
  --accent-hover: #ffffff;
  --glitch-r: rgba(255,59,48,.45);
  --glitch-c: rgba(0,213,255,.45);
  --danger: #ff3b30;
  --success: #00ff88;

  /* Échelle de rareté : vit dans un badge, un liseré ou un point, jamais
     dans un fond de carte entier. Le légendaire partage le jaune de l'accent,
     sommet de l'échelle. */
  --rarity-commun: #b9b9c0;
  --rarity-peu_commun: #00ff88;
  --rarity-rare: #00d5ff;
  --rarity-epique: #c77dff;
  --rarity-legendaire: #ffe900;

  --font-title: 'Press Start 2P', monospace; /* libellés courts en capitales */
  --font-ui: 'VT323', monospace;             /* tout le texte d'interface */
  --font-mono: 'JetBrains Mono', monospace;  /* toute valeur numérique */

  /* VT323 a un petit œil : jamais sous 18px. */
  --fs-xs: 18px;
  --fs-sm: 19px;
  --fs-md: 20px;
  --fs-lg: 22px;
  --fs-xl: 26px;
  --fs-2xl: 30px;
  /* Valeurs numériques, en JetBrains Mono. */
  --fm-xs: 10px;
  --fm-sm: 11px;
  --fm-md: 12px;
  --fm-lg: 13px;
  --fm-xl: 15px;
  --fm-2xl: 20px;

  /* Contour de bloc, liseré intérieur des panneaux, ombres dures. */
  --block: inset 0 0 0 3px var(--outline);
  --block-panel: inset 0 0 0 3px var(--outline), inset 0 0 0 4px var(--outline-inner);
  --shadow-sm: 4px 4px 0 0 var(--outline);
  --shadow-md: 6px 6px 0 0 var(--outline);
  --shadow-lg: 8px 8px 0 0 var(--outline);
  --glitch-text: 1.5px 0 var(--glitch-r), -1.5px 0 var(--glitch-c);
  --hatch: repeating-linear-gradient(45deg, rgba(255,255,255,.07) 0 5px, transparent 5px 10px);

  /* Anciens noms, gardés tant que toutes les règles ne sont pas reprises. */
  --text-secondary: var(--text-muted);
  --text-tertiary: var(--text-dim);
  --text-disabled: var(--text-dim);
  --text-disabled-2: var(--text-dim);
  --line: var(--hairline);
  --line-strong: var(--outline-inner);
  --selected-bg: var(--surface-3);
  --selected-ring: var(--accent);
  --currency: var(--accent);
  --focus: var(--accent);
}

* { box-sizing: border-box; }
button, input, select, textarea { border-radius: 0; }

html, body { margin: 0; padding: 0; }

body {
  min-height: 100vh;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  line-height: 1.2;
  color: var(--text);
  background-color: var(--bg);
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 4px);
  background-attachment: fixed;
  /* VT323 et Press Start 2P n'ont qu'une graisse : pas de faux gras baveux. */
  font-synthesis: none;
}
/* Rendu pixel pour le décor ; les jaquettes Steam et les photos d'avatar
   restent lissées (en pixelated, une photo réduite crénelle). */
html { image-rendering: pixelated; }
/* Place de la barre de défilement toujours réservée : sans elle, les pages
   courtes (sans barre) étaient plus larges que les longues, et tout le
   contenu se décalait de quelques pixels en changeant de page. */
html { scrollbar-gutter: stable; }
img { image-rendering: auto; }
::selection { background: var(--accent); color: var(--ink); }
input, textarea { caret-color: var(--accent); }
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  flex: none;
  background: var(--surface-2);
  box-shadow: inset 0 0 0 3px var(--outline-inner);
  cursor: pointer;
}
input[type="checkbox"]:checked { background: var(--accent); box-shadow: inset 0 0 0 3px var(--outline), inset 0 0 0 5px var(--accent); }
input[type="checkbox"]:checked::after {
  content: '';
  display: block;
  width: 6px;
  height: 6px;
  margin: 5px;
  background: var(--ink);
}

a { color: var(--text); text-decoration: none; }

.hidden { display: none !important; }

/* Anneau de focus clavier explicite (audit design F-30) : l'anneau bleu
   par défaut du navigateur disparaît sur les boutons en --accent, et
   aucune règle :focus-visible n'existait sinon. */
/* Focus clavier : contour jaune plein, jamais de halo flou. */
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--outline-inner); }
* { scrollbar-width: thin; scrollbar-color: var(--outline-inner) transparent; }

/* --- Mono utility links --- */
.mono-link {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.mono-link:hover { color: #fff; }

.icon-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.icon-link i { font-size: 12px; }

/* --- Wordmark --- */
.wordmark {
  display: flex;
  align-items: center;
  gap: 9px;
}
.wordmark span:last-child {
  font-family: var(--font-ui);
  font-size: 23px;
  line-height: 1;
  letter-spacing: .04em;
  color: var(--text-strong);
  text-shadow: 1px 0 rgba(255,59,48,.4), -1px 0 rgba(0,213,255,.4);
}

/* --- En-tête de page (audit design F-08) : titre + métrique clé,
   identique sur les 6 pages qui n'avaient ni H1 ni H2 (Caisses a déjà sa
   propre ligne de statut, servant de référence, non dupliquée ici). --- */
/* Hauteur minimale commune : l'en-tête grandissait selon ce qu'il contient
   (bouton, compteur, texte), et le contenu de la page démarrait plus ou
   moins bas d'une page à l'autre. */
.page-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  min-height: 44px;
}
.page-header-title {
  margin: 0;
  font-family: var(--font-title);
  font-size: clamp(20px, 2.6vw, 28px);
  font-weight: 400;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--text-strong);
  text-shadow: var(--glitch-text), 0 4px 0 var(--outline);
}
.page-header-meta {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-muted);
}

/* --- Login view : accueil publique. Deux colonnes sur ordinateur (présentation
   à gauche, formulaire à droite) pour que tout tienne dans l'écran sans
   défiler ; une seule colonne, formulaire en 3e, sur petit écran. --- */
.login-view {
  min-height: 100vh;
  padding: clamp(24px, 5vh, 56px) 32px;
  display: flex;
  align-items: center;
}

@keyframes omRise { 0% { opacity: 0; transform: translateY(10px); } 100% { opacity: 1; transform: none; } }

.landing {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 400px;
  grid-template-areas:
    "brand    auth"
    "hero     auth"
    "features auth"
    "rarity   auth";
  grid-template-rows: auto auto auto auto;
  column-gap: clamp(32px, 6vw, 88px);
  align-items: start;
  text-align: left;
  animation: omRise .5s ease both;
}

.landing-wordmark { grid-area: brand; margin-bottom: clamp(20px, 5vh, 48px); }

/* Le bloc prend la largeur du titre ; la description se cale dessus (largeur 0 +
   min-width 100 % : elle ne peut pas élargir le bloc), donc même bord droit. */
.landing-hero { grid-area: hero; width: fit-content; max-width: 100%; }
.landing-hero h1 {
  font-family: var(--font-title);
  font-weight: 400;
  font-size: clamp(24px, 4vw, 40px);
  line-height: 1.3;
  text-wrap: balance;
  margin: 0 0 18px;
  color: var(--text-strong);
  text-shadow: var(--glitch-text), 0 4px 0 var(--outline);
}
.landing-hero .subtext {
  margin: 0 0 clamp(20px, 4vh, 36px);
  width: 0;
  min-width: 100%;
  text-wrap: pretty;
  font-size: var(--fs-lg);
  line-height: 1.35;
  color: var(--text-muted);
}

.login-card {
  grid-area: auth;
  align-self: center;
  width: 100%;
  max-width: 400px;
  padding: 26px 24px;
  text-align: left;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.login-card h2 {
  margin: 0 0 22px;
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--text-strong);
}

.landing-features {
  grid-area: features;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 0 0 clamp(18px, 4vh, 36px);
}
.feature-card {
  padding: 16px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
  text-align: left;
}
.feature-card i {
  display: inline-flex;
  font-size: 20px;
  color: var(--accent);
  margin-bottom: 12px;
}
.feature-card strong { display: block; color: var(--text-strong); font-family: var(--font-title); font-size: 10px; font-weight: 400; line-height: 1.5; text-transform: uppercase; margin-bottom: 8px; }
.feature-card p { margin: 0; font-size: var(--fs-md); line-height: 1.2; color: var(--text-muted); }

/* Pleine largeur de la colonne : même bord droit que les trois cartes. */
.rarity-spectrum-block { grid-area: rarity; width: 100%; }
.rarity-spectrum-block > .mono-note { margin: 0 0 12px; text-align: left; }
.rarity-spectrum {
  display: flex;
  gap: 3px;
  height: 18px;
  overflow: hidden;
  background: var(--outline);
  box-shadow: 0 0 0 3px var(--outline);
}
.rarity-seg-commun { background: var(--rarity-commun); }
.rarity-seg-peu_commun { background: var(--rarity-peu_commun); }
.rarity-seg-rare { background: var(--rarity-rare); }
.rarity-seg-epique { background: var(--rarity-epique); }
.rarity-seg-legendaire { background: var(--rarity-legendaire); }
.rarity-spectrum-legend {
  display: flex;
  justify-content: space-between; /* les pastilles couvrent toute la barre */
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

/* Petit écran : une colonne centrée, dans l'ordre marque, accroche,
   formulaire, puis le détail — la page peut défiler. */
@media (max-width: 900px) {
  .login-view { display: block; padding: 48px 22px 64px; }
  .landing {
    max-width: 640px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "brand" "hero" "auth" "features" "rarity";
    justify-items: center;
    text-align: center;
  }
  .landing-wordmark { margin-bottom: 40px; }
  .landing-hero { width: auto; }
  .landing-hero .subtext { width: auto; max-width: 460px; margin: 0 auto 36px; }
  .login-card { align-self: start; }
  .landing-features { width: 100%; margin: 56px 0 36px; }
  .rarity-spectrum-block > .mono-note { text-align: center; }
  .rarity-spectrum-legend { justify-content: center; }
}
@media (max-width: 640px) {
  .landing-features { grid-template-columns: 1fr; }
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 8px;
}
.auth-form input {
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  padding: 9px 12px;
}
.auth-form input:focus { border-color: var(--accent); outline: none; }
.auth-form input::placeholder { color: var(--text-disabled); }
.auth-form .btn-lg { width: 100%; }
.auth-error {
  margin: 0;
  min-height: 16px;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--danger);
}
/* Erreur affichée : bloc au contour rouge. */
.auth-error:not(:empty):not([role="status"]) { padding: 6px 10px; box-shadow: inset 0 0 0 3px var(--danger); }
.auth-toggle a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.auth-toggle a:hover { color: var(--accent-hover); }

.mono-note {
  margin: 18px 0 0;
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

/* --- App view : sidebar + contenu --- */
.app-view {
  display: flex;
  min-height: 100vh;
  align-items: stretch;
}

.sidebar {
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  width: 240px;
  flex: 0 0 240px;
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding: 22px 16px;
  overflow-y: auto;
  background: var(--surface-1);
  border-right: 3px solid var(--outline);
  box-shadow: inset -3px 0 0 0 var(--outline-inner);
}

.sidebar-wordmark { padding: 2px 4px; }

.side-nav {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.side-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-family: var(--font-ui);
  font-size: 21px;
  line-height: 1.1;
  text-transform: lowercase;
  padding: 8px 11px;
  cursor: pointer;
  text-align: left;
}
.side-nav-item > span:not(.nav-case-timer) { flex: 1 1 auto; line-height: 1; }
/* Icône et libellé alignés sur leur dessin, pas sur leur boîte : VT323 porte
   ses minuscules bas dans sa hauteur de ligne (hampe de 4px sous la ligne de
   base), la police d'icônes non. Hauteurs de ligne à 1 pour des boîtes
   exactes, puis l'icône descend de 2px pour se centrer sur les minuscules. */
.side-nav-item i { font-size: 15px; width: 18px; flex: none; display: flex; justify-content: center; line-height: 1; position: relative; top: 2px; }
.nav-more-btn { display: none; }
.side-nav-item:hover { background: var(--surface-3); color: var(--text-strong); box-shadow: var(--block); }
.side-nav-item.active {
  background: var(--accent);
  color: var(--ink);
  box-shadow: var(--block), var(--shadow-sm);
}

.sidebar-footer {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 13px;
  padding: 0 2px;
}

/* Carte joueur : avatar, pseudo (+ badge VIP) et pièces dans une seule boîte,
   au lieu d'une boîte de monnaie isolée au-dessus du pseudo. */
.sidebar-player {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  background: var(--surface-2);
  box-shadow: var(--block), var(--shadow-sm);
}
/* Avatar et cadre VIP plus fins que partout ailleurs : dégagés du bord de la carte. */
.sidebar-player .user-avatar { width: 30px; height: 30px; }
.sidebar-player .vip-frame { box-shadow: 0 0 0 2px var(--accent), 0 0 0 4px rgba(255,233,0,.5); }
.sidebar-player-info { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sidebar-player .user-name { line-height: 1; }
/* « Mon VIP » et la déconnexion (bouton carré) sur une même ligne. */
.sidebar-actions { display: flex; gap: 8px; }
.sidebar-actions .vip-nav-btn { flex: 1 1 auto; min-height: 34px; }
.sidebar-actions .logout-link { width: 34px; min-height: 34px; color: var(--text-muted); }
.sidebar-actions .logout-link:hover { color: var(--text-strong); }
/* Liens légaux : centrés sous un filet, en bas de colonne. */
.sidebar-footer .legal-links { justify-content: center; text-align: center; padding-top: 10px; border-top: 3px solid var(--hairline); }

.user-avatar {
  width: 32px;
  height: 32px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--accent);
  border: 3px solid var(--outline);
  color: var(--ink);
  font-family: var(--font-title);
  font-size: 10px;
}
.user-avatar img, .profile-avatar img, .row-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* --- En-tête de la page profil : avatar (éditable) + pseudo + collection --- */
.profile-header { display: flex; align-items: center; gap: 20px; }
/* .panel (déclarée plus bas) passe ses enfants en colonne : l'en-tête reste en ligne. */
.panel.profile-header { flex-direction: row; }
.profile-avatar-wrap { position: relative; flex-shrink: 0; }
.profile-avatar {
  width: 84px;
  height: 84px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  border: 3px solid var(--outline);
  color: var(--ink);
  font-family: var(--font-title);
  font-size: 28px;
}
.profile-avatar-edit {
  position: absolute;
  right: -6px;
  bottom: -6px;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: var(--accent);
  color: var(--ink);
  font-size: 13px;
  cursor: pointer;
  box-shadow: var(--block), var(--shadow-sm);
}
.profile-avatar-edit:hover { background: var(--accent-hover); }
.profile-header-info { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.profile-name {
  font-family: var(--font-title);
  font-size: 20px;
  line-height: 1.4;
  color: var(--text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.profile-header-meta {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-muted);
}

.user-name {
  font-size: 21px;
  color: var(--text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.main-area {
  flex: 1 1 auto;
  min-width: 0;
}

/* 1400px plutôt que les 1080px du DESIGN.md : sur grand écran, les pages
   gagnent en largeur (choix de l'utilisateur, 2026-09-22). */
.content {
  max-width: 1400px;
  margin: 0 auto;
  --pad-top: clamp(18px, 3vh, 40px);
  --pad-bottom: 48px;
  padding: var(--pad-top) clamp(16px, 4vw, 40px) var(--pad-bottom);
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 2.6vh, 28px);
  overflow-x: hidden;
}

.page-panel {
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 2.6vh, 28px);
}

@media (max-width: 760px) {
  .app-view { flex-direction: column; }
  /* En-tête : marque + monnaie/compte. La navigation passe dans une barre
     fixe en bas (audit P2-12) : quatre entrées avec libellé sous l'icône, le
     reste derrière « Plus » — neuf icônes seules ne se devinaient pas. */
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 20;
    height: auto;
    width: 100%;
    flex: 0 0 auto; /* la base desktop (232px) devenait une hauteur en colonne */
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    gap: 12px;
    padding: 10px 14px;
    border-right: none;
    border-bottom: 3px solid var(--outline);
    box-shadow: inset 0 -3px 0 0 var(--outline-inner);
    background: var(--surface-1);
  }
  .sidebar-footer { margin-top: 0; margin-left: auto; flex-direction: row; align-items: center; }

  .side-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 4px;
    background: var(--surface-1);
    border-top: 3px solid var(--outline);
    box-shadow: inset 0 3px 0 0 var(--outline-inner);
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
  }
  .side-nav-item {
    position: relative;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    min-width: 0;
    min-height: 52px;
    padding: 4px 2px;
    text-align: center;
  }
  /* flex: none : le libellé s'étirait (flex: 1 de l'ordinateur, prévu pour
     pousser la pastille à droite) et, en colonne, avalait la hauteur libre :
     icône et texte collés en haut du bouton au lieu d'y être centrés. */
  .side-nav-item > span:not(.nav-case-timer) { flex: none; font-size: var(--fs-xs); }
  /* Icône au-dessus du libellé : pas de recalage vertical. */
  .side-nav-item i { top: 0; }
  /* Barre du bas trop étroite pour un chrono : réservé à l'ordinateur. */
  .nav-case-timer { display: none !important; }
  .nav-secondary { display: none; }
  /* « Plus » ouvert : les entrées secondaires au-dessus, quatre par ligne, puis
     la barre principale, quel que soit leur nombre. En grille, les forcer sur
     une seule rangée les faisait déborder dès qu'il y en avait plus de cinq. */
  .side-nav.more-open {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    max-height: 75vh;
    overflow-y: auto;
  }
  .side-nav.more-open > * { flex: 0 0 calc((100% - 16px) / 5); }
  /* Quatre par ligne : place pour « Notifications », le plus long libellé. */
  .side-nav.more-open .nav-secondary { display: flex; order: 0; flex-basis: calc((100% - 12px) / 4); }
  .side-nav.more-open .nav-secondary.hidden { display: none; }
  /* Séparateur : force le retour à la ligne avant la barre principale. */
  .side-nav.more-open::before {
    content: '';
    order: 1;
    flex: 0 0 100%;
    height: 3px;
    margin: 2px 0;
    background: var(--outline);
  }
  .side-nav.more-open > :not(.nav-secondary) { order: 2; }
  .side-nav-item > span { white-space: nowrap; }
  .nav-more-btn { display: flex; }
  /* En-tête compact : pseudo et « déconnexion » restent lisibles pour un
     lecteur d'écran mais ne doivent pas faire déborder la ligne. */
  .sidebar-footer { gap: 10px; }
  /* En-tête mobile : la déconnexion redevient une simple icône (place comptée). */
  .sidebar-actions { gap: 8px; align-items: center; }
  .sidebar-actions .logout-link { width: auto; min-height: 0; padding: 0 2px; background: none; box-shadow: none; }
  .sidebar-player .user-name,
  .logout-link span:not(.fi) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .main-area { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }
  /* Scène des caisses ramenée à l'écran à l'ouverture : ni sous l'en-tête
     collant, ni sous la barre du bas. */
  #cstage { scroll-margin-top: 72px; scroll-margin-bottom: calc(84px + env(safe-area-inset-bottom)); }
  /* Les liens légaux quittent l'en-tête, trop étroit, pour le bas du contenu. */
  .sidebar-footer .legal-links { display: none; }
  .toast-region { bottom: calc(84px + env(safe-area-inset-bottom)); right: 12px; }
}

/* Bandeau de l'happy hour, au-dessus du stock (voir pages/cases.ts). */
.happy-hour {
  margin-bottom: 12px;
  padding: 10px 14px 10px 20px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), inset 6px 0 0 0 var(--accent), var(--shadow-md);
  color: var(--text-strong);
  font-size: var(--fs-sm);
}

.case-status-section {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  padding: 14px 18px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.case-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 21px;
  color: var(--text-muted);
}
/* Nombre et libellé : même écart que l'icône, sur la même ligne de base. */
.case-status > span { display: inline-flex; align-items: baseline; gap: 8px; }
.case-status #caseBalance {
  font-family: var(--font-title);
  font-size: 15px;
  color: var(--text-strong);
}
.case-status i { color: var(--accent); font-size: 17px; }
.case-timer {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--accent);
}
.collection-progress {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-size: 21px;
  color: var(--text-muted);
}
#ownedCount, #catalogSize {
  font-family: var(--font-mono);
  font-size: var(--fm-xl);
  font-weight: 700;
  color: var(--text-strong);
}
#catalogSize { color: var(--text-dim); }
.progress-sep { color: var(--text-faint); }


.album-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.modal-card .album-search {
  flex: 0 0 auto;
}
.album-search {
  flex: 1 1 220px;
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  padding: 6px 12px;
  color: var(--text-dim);
}
.album-search > .fi { font-size: 13px; }
.album-search input {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  outline: none;
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
}
.album-search input::placeholder { color: var(--text-disabled); }
.album-search:focus-within { border-color: var(--accent); }

.album-select {
  appearance: none;
  background: var(--surface-2) linear-gradient(var(--accent), var(--accent)) no-repeat right 12px center / 6px 6px;
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  padding: 6px 32px 6px 12px;
  cursor: pointer;
}
.album-select:focus { border-color: var(--accent); outline: none; }
.album-select option { background: var(--surface-2); color: var(--text-strong); }

/* Bascule Tout / Possédés de l'album. */
.scope-toggle {
  display: inline-flex;
  gap: 6px;
}
.scope-btn {
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  background: var(--surface-2);
  border: 0;
  padding: 6px 12px;
  cursor: pointer;
  box-shadow: var(--block);
}
.scope-btn:hover { color: var(--text-strong); background: var(--surface-3); }
.scope-btn.active { background: var(--accent); color: var(--ink); }


.album-rarity-filters { gap: 7px; }

/* Vignettes plus grandes et plus espacées (la grille était jugée trop tassée). */
.album-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 16px;
}
/* Téléphone : deux colonnes plutôt qu'une seule vignette géante. */
@media (max-width: 760px) {
  .album-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
}

/* Carte d'album : jaquette en haut, nom en bas sur un filet 3px de la couleur
   de rareté (comme les tuiles du reel). La hauteur suit la largeur :
   jaquette au format Steam 920 × 430 + barre de nom (46px de bords et barre).
   fitAlbumPageSize (collection.ts) refait le même calcul. */
.album-item {
  position: relative;
  height: 0;
  padding-top: calc((100% - 6px) * 0.46739 + 46px);
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 3px var(--hairline), var(--shadow-sm);
  cursor: pointer;
  --rarity-edge: var(--hairline);
}
.album-item .gamecard-art, .album-item .album-scrim {
  inset: auto;
  top: 3px;
  left: 3px;
  width: calc(100% - 6px);
  height: calc(100% - 46px);
}
.album-item .gamecard-logo { top: calc(50% - 20px); }
.album-item .gamecard-name-fallback { inset: 3px 3px 43px; }
/* Cadre à la couleur de rareté (le filet de la barre de nom seul se voyait
   mal). */
.album-item:not(.locked) { box-shadow: inset 0 0 0 3px var(--rarity-edge), var(--shadow-sm); }
.album-item:not(.locked):hover { transform: translate(-2px, -2px); box-shadow: inset 0 0 0 3px var(--rarity-edge), var(--shadow-md); }
.album-item:not(.locked):active { transform: translate(2px, 2px); box-shadow: inset 0 0 0 3px var(--rarity-edge), 1px 1px 0 0 var(--outline); }
.album-item .album-rarity-badge { position: absolute; z-index: 2; top: 7px; left: 7px; }
.album-item .album-name {
  position: absolute;
  left: 3px;
  right: 3px;
  bottom: 3px;
  height: 37px;
  padding: 5px 8px 0;
  border-top: 3px solid var(--rarity-edge);
  background: var(--surface-2);
  font-size: var(--fs-md);
  line-height: 1.2;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.album-item .album-scrim {
  position: absolute;
  background: rgba(8,8,10,.35);
}
.album-item .album-count {
  position: absolute;
  top: 7px;
  right: 7px;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  padding: 2px 5px;
  box-shadow: inset 0 0 0 2px var(--outline);
}

/* Non possédé (vue « Tout ») : le jeu en gris et assombri, cadre neutre ;
   l'étiquette de rareté garde sa couleur (ce qu'il reste à obtenir). */
.album-item.locked {
  box-shadow: inset 0 0 0 3px var(--hairline);
  --rarity-edge: var(--hairline);
}
.album-item.locked .gamecard-art, .album-item.locked .gamecard-logo { filter: grayscale(1) brightness(.55); }
.album-item.locked .album-scrim { background: rgba(8,8,10,.45); }
.album-item.locked .album-name { color: var(--text-dim); }
.album-item.locked .album-rarity-badge { opacity: .8; }
.album-item.locked:hover { box-shadow: inset 0 0 0 3px var(--text-dim); }

/* Vignette ou nom qui ouvre la fiche du jeu (voir linkGameDetail). Les
   vignettes de l'album et les lignes d'historique ont déjà leur survol. */
.game-link, .game-link-text { cursor: pointer; }
.game-link:not(.album-item):not(.history-item):hover { outline: 2px solid var(--accent); outline-offset: 2px; }
.game-link-text:hover { color: var(--text-strong); text-decoration: underline; text-underline-offset: 3px; }
/* Fiche d'un jeu et mise aux enchères : au-dessus des autres fenêtres (collection
   d'un ami, profil d'un joueur), d'où elles peuvent maintenant s'ouvrir. */
#gameDetailModal, #createListingModal { z-index: 110; }

.rarity-badge, .badge-alert, .badge-status {
  display: inline-flex;
  align-items: center;
  padding: 5px 8px;
  font-family: var(--font-title);
  font-size: 8px;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  flex-shrink: 0;
  box-shadow: inset 0 0 0 2px var(--outline);
}
/* Sanction (ex : joueur banni) — distincte de la rareté (audit design
   F-04/F-18) : réutilisait --rarity-legendaire, la couleur la plus
   désirable du jeu comme étiquette de sanction. */
.badge-alert { background: var(--bg); color: var(--danger); box-shadow: inset 0 0 0 3px var(--danger); }
/* Statut neutre (ex : "nouveau") — contour, pas une pastille pleine,
   pour ne jamais se confondre avec un badge de rareté à côté (F-18) :
   avant, "nouveau" et la rareté tirée avaient la même forme pleine, et
   se confondaient carrément en couleur pour un tirage "rare". */
/* Statut (nouveau, vendu, expiré) : contour et texte de la couleur d'état. */
.badge-status { background: var(--bg); color: var(--success); box-shadow: inset 0 0 0 3px currentColor; }

.rarity-commun { background: var(--rarity-commun); color: var(--ink); }
.rarity-peu_commun { background: var(--rarity-peu_commun); color: var(--ink); }
.rarity-rare { background: var(--rarity-rare); color: var(--ink); }
.rarity-epique { background: var(--rarity-epique); color: var(--ink); }
.rarity-legendaire { background: var(--rarity-legendaire); color: var(--ink); }

.status-text {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-dim);
  padding: 40px 0;
  text-align: center;
}
/* Curseur carré qui clignote à 1 Hz, par paliers : pas de spinner. */
.status-text::after {
  content: '';
  display: inline-block;
  width: .5em;
  height: .8em;
  margin-left: 4px;
  vertical-align: -1px;
  background: currentColor;
  animation: gcBlink 1s steps(1) infinite;
}
@keyframes gcBlink { 50% { opacity: 0; } }
.status-text.hidden { display: none !important; }

/* Libellés de section : TON STOCK, HISTORIQUE DES DROPS (le texte est mis
   en forme par applyStaticTranslations, i18n.ts). */
.section-label {
  font-family: var(--font-title);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .04em;
  color: var(--text-strong);
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 32px;
  padding: 0 12px;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  border: none;
  background: var(--surface-2);
  color: var(--text-muted);
  box-shadow: var(--block);
}
.tag-chip:hover { background: var(--surface-3); color: var(--text-strong); }
/* Coloré dans sa propre couleur de rareté quand actif (jamais en accent
   générique) : la barre de filtres devient aussi la légende du système
   de rareté (audit design F-21). Neutre par défaut (voir isFiltering
   dans collection.ts/market.ts) tant qu'aucun filtre réel n'est posé. */
.tag-chip.active.tag-chip-commun { background: var(--rarity-commun); color: var(--ink); }
.tag-chip.active.tag-chip-peu_commun { background: var(--rarity-peu_commun); color: var(--ink); }
.tag-chip.active.tag-chip-rare { background: var(--rarity-rare); color: var(--ink); }
.tag-chip.active.tag-chip-epique { background: var(--rarity-epique); color: var(--ink); }
.tag-chip.active.tag-chip-legendaire { background: var(--rarity-legendaire); color: var(--ink); }

/* --- Stage / reel --- */
@keyframes omNudge {
  0%, 100% { transform: translate3d(0,0,0); }
  22% { transform: translate3d(0,-4px,0); }
  55% { transform: translate3d(0,2px,0); }
}

.stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.stage.won {
  animation: omNudge .5s steps(4) both;
}

.reel-viewport {
  position: relative;
  height: clamp(170px, 26vh, 212px);
  overflow: hidden;
  background: #0a0a0c;
  box-shadow: var(--block-panel), var(--shadow-md);
}
/* Cadre redessiné par-dessus le rouleau : une ombre intérieure passe sous le
   contenu, et les jeux coupés à gauche et à droite recouvraient la bordure.
   Sous le curseur (z-index 6), la sélection et les effets. */
.reel-viewport::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  box-shadow: var(--block-panel);
}

.track {
  position: absolute;
  top: 20px;
  left: 0;
  height: calc(100% - 40px);
  display: flex;
  gap: 12px;
  will-change: transform;
}

/* Tuile du reel : jaquette en haut, nom en bas, séparés par un filet 3px
   de la couleur de rareté. */
.tile {
  position: relative;
  flex: 0 0 164px;
  width: 164px;
  height: 100%;
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 3px var(--hairline);
  --tile-edge: var(--hairline);
}

.tile .art {
  position: absolute;
  top: 3px;
  left: 3px;
  display: block;
  object-fit: cover;
  width: calc(100% - 6px);
  height: calc(100% - 43px);
}

.tile .scrim {
  position: absolute;
  top: 3px;
  left: 3px;
  width: calc(100% - 6px);
  height: calc(100% - 43px);
  background: rgba(8,8,10,.45);
}

.tile .tile-glow { display: none; }

.tile.tile-rarity-commun { --tile-edge: var(--rarity-commun); }
.tile.tile-rarity-peu_commun { --tile-edge: var(--rarity-peu_commun); }
.tile.tile-rarity-rare { --tile-edge: var(--rarity-rare); }
.tile.tile-rarity-epique { --tile-edge: var(--rarity-epique); }
.tile.tile-rarity-legendaire { --tile-edge: var(--rarity-legendaire); }
.tile .tile-name {
  position: absolute;
  left: 3px;
  right: 3px;
  bottom: 3px;
  height: 37px;
  padding: 5px 8px 0;
  border-top: 3px solid var(--tile-edge);
  background: var(--surface-2);
  font-size: var(--fs-md);
  line-height: 1.2;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== Carte de jeu : traitement flou+logo partagé (audit design F-17).
   Le reel (.tile) et le marché/la modale gardent leurs règles existantes
   (déjà flou+logo) ; ces classes servent aux contextes qui affichaient
   une jaquette nette+nom (album, profil, admin) pour rendre le même
   jeu reconnaissable d'un écran à l'autre. Container : garde sa propre
   classe pour position/overflow/background, ajoute juste .gamecard-{xs,sm}. */
.gamecard-art {
  position: absolute;
  display: block;
  object-fit: cover;
}
.gamecard-scrim {
  position: absolute;
  inset: 0;
  background: rgba(8,8,10,.4);
}
/* Au-dessus du voile, quel que soit l'ordre du DOM. */
.gamecard-logo {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  object-fit: contain;
  filter: drop-shadow(1px 1px 0 rgba(0,0,0,.95));
}
.gamecard-name-fallback {
  position: absolute;
  z-index: 1;
  inset: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: var(--fs-sm);
  line-height: 1;
  color: var(--text-strong);
}

.gamecard-sm { }
.gamecard-sm .gamecard-art { inset: 0; width: 100%; height: 100%; }
.gamecard-sm .gamecard-logo { max-width: 74%; max-height: 58%; }

.gamecard-xs { }
.gamecard-xs .gamecard-art { inset: 0; width: 100%; height: 100%; }
.gamecard-xs .gamecard-logo { max-width: 70%; max-height: 60%; }
.gamecard-xs .gamecard-name-fallback { display: none; } /* pas la place à cette taille */

/* Liseré de rareté : variante d'état légère pour les tailles sm/xs (le
   reel garde son propre halo, plus marqué, via .tile-rarity-*). */
.gamecard-rarity-commun { --rarity-edge: var(--rarity-commun); }
.gamecard-rarity-peu_commun { --rarity-edge: var(--rarity-peu_commun); }
.gamecard-rarity-rare { --rarity-edge: var(--rarity-rare); }
.gamecard-rarity-epique { --rarity-edge: var(--rarity-epique); }
.gamecard-rarity-legendaire { --rarity-edge: var(--rarity-legendaire); }

.tile .logo {
  position: absolute;
  top: calc(50% - 20px);
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 80%;
  max-height: 46%;
  object-fit: contain;
  filter: drop-shadow(2px 2px 0 rgba(0,0,0,.9));
}

.tile .name-fallback { display: none; }

.tile .tile-tag { display: none; }

@keyframes omBreathe { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

/* Marqueur central : trait jaune 4px à aberration chromatique, taquets en
   haut et en bas. L'une des deux lueurs autorisées du site. */
.marker {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 4px;
  margin-left: -2px;
  z-index: 6;
  pointer-events: none;
  background: var(--accent);
  box-shadow: 2px 0 0 rgba(255,59,48,.3), -2px 0 0 rgba(0,213,255,.3), 0 0 20px 3px rgba(255,233,0,.28);
}
.marker::before, .marker::after {
  content: '';
  position: absolute;
  left: -8px;
  width: 20px;
  height: 8px;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--outline);
}
.marker::before { top: 0; }
.marker::after { bottom: 0; }
.marker.spinning { animation: omBreathe 1.1s steps(2) infinite; }
/* Le trait central reste visible une fois le tirage terminé. */

@keyframes omFrame {
  0% { opacity: 0; transform: scale(1.18); }
  60% { opacity: 1; transform: scale(.985); }
  100% { opacity: 1; transform: scale(1); }
}

.winner-frame {
  position: absolute;
  left: 50%;
  top: 20px;
  bottom: 20px;
  width: 164px;
  margin-left: -82px;
  z-index: 8;
  pointer-events: none;
  opacity: 0;
}
.winner-frame.show {
  opacity: 1;
  box-shadow: inset 0 0 0 3px var(--accent), 0 0 0 3px var(--outline);
  animation: omFrame .3s steps(3) both;
}

.sparks {
  position: absolute;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  overflow: hidden;
}

@keyframes omSpark {
  0% { opacity: .9; transform: translate3d(0,0,0) scale(1); }
  100% { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) scale(.25); }
}

@keyframes omFlash { 0% { opacity: 0; } 10% { opacity: .85; } 100% { opacity: 0; } }

.flash {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  opacity: 0;
}
/* Éclair à l'arrivée : un aplat, par paliers, sans dégradé ni fondu. */
.flash.show {
  background: rgba(255,233,0,.22);
  animation: omFlash .45s steps(3) both;
}

/* Boutons (audit P3-01) : une base .btn, deux axes — variante et taille —
   au lieu de sept définitions complètes (spin-btn, admin-action,
   achievement-claim-btn, market-bid-btn, pagination-btn, duration-btn) qui
   se recopiaient avec quatre hauteurs et trois familles de couleurs.
     variante : .btn-primary (accent : l'action principale de l'écran, une
                seule), .btn-secondary, .btn-danger, .btn-option (choix dans
                un groupe, .active = sélectionné)
     taille   : .btn-sm 32px (utilitaire), .btn-md 40px (accent secondaire),
                .btn-lg 48px (action principale d'un écran)
   Les puces de filtre .tag-chip restent un composant à part : ce sont des
   filtres colorés par rareté, pas des actions. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: none;
  font-family: var(--font-ui);
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--block), var(--shadow-sm);
}
/* Clic : le bloc s'enfonce sur son ombre. */
.btn:active:not(:disabled) { transform: translate(3px, 3px); box-shadow: var(--block), 1px 1px 0 0 var(--outline); }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: var(--block); }
/* Icône placée devant le libellé d'un bouton. .btn étant un conteneur flex,
   l'espace tapé entre l'icône et le texte y est ignoré : la flèche collait au
   texte. line-height: 1 cale la boîte de l'icône sur son glyphe, qu'align-items
   peut alors vraiment centrer (elle remontait). Ne vise ni les boutons sans
   texte, ni le cadenas de « Tout ouvrir », placé après le libellé. */
.btn > .fi:first-child:not(:only-child) { display: inline-flex; line-height: 1; font-size: 12px; }
.btn-sm { min-height: 32px; padding: 0 12px; font-size: var(--fs-sm); }
.btn-md { flex: 0 0 auto; min-height: 40px; padding: 0 16px; font-size: var(--fs-md); }
.btn-lg {
  flex: 0 0 auto;
  position: relative;
  min-height: 48px;
  padding: 0 24px;
  font-size: var(--fs-lg);
}
.btn-primary {
  background: var(--accent);
  color: var(--ink);
  font-family: var(--font-title);
  font-size: 10px;
  line-height: 1.4;
  text-transform: uppercase;
  box-shadow: var(--block), 5px 5px 0 0 var(--outline);
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); }
.btn-lg.btn-primary { font-size: 11px; }
.btn-secondary { background: var(--surface-2); color: var(--text); }
.btn-secondary:hover:not(:disabled) { background: var(--surface-3); color: var(--text-strong); }
.btn-danger { background: transparent; color: var(--danger); box-shadow: inset 0 0 0 3px var(--danger); }
.btn-danger:hover:not(:disabled) { background: rgba(255,59,48,.14); }
.btn-danger:active:not(:disabled) { box-shadow: inset 0 0 0 3px var(--danger); }
.btn-danger:disabled { box-shadow: inset 0 0 0 3px var(--danger); }
/* Fantôme : liseré jaune, sans ombre (liens d'aide, « comment ça marche ? »). */
.btn-ghost { background: transparent; color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.btn-ghost:hover:not(:disabled) { background: var(--accent); color: var(--ink); }
.btn-ghost:active:not(:disabled) { box-shadow: inset 0 0 0 2px var(--accent); }
.btn-option { background: var(--surface-2); color: var(--text-muted); font-size: var(--fs-sm); }
.btn-option:hover:not(:disabled) { color: var(--text-strong); background: var(--surface-3); }

/* --- Ligne de statut : le stock remplace le compteur X/10 --- */
.case-status-unit { color: var(--text-muted); }

/* --- Ligne de résultat : hauteur fixe, sinon la scène grandit à l'arrivée
   du nom (.result-text.won passe à clamp(22px,3.4vw,32px)). Passe à la ligne
   quand la place manque (fenêtre moyenne) : sans ça, le nom du jeu
   rétrécissait jusqu'à disparaître et les boutons débordaient à droite. --- */
.result-bar {
  display: flex;
  align-items: center;
  gap: 10px 16px;
  flex-wrap: wrap;
  min-height: 34px;
  padding: 13px 18px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.result-bar .rarity-badge, .result-bar .badge-status {
  font-size: 9px;
  padding: 6px 9px;
}
.result-bar .rarity-badge { box-shadow: inset 0 0 0 3px var(--outline); }

/* « Passer l'animation » : dans la barre de résultat, à droite, visible
   seulement pendant le défilement (un clic sur le défilement ou Échap font
   pareil). */
.skip-btn { margin-left: auto; align-self: center; flex-shrink: 0; position: relative; display: inline-flex; align-items: center; }
.skip-label { display: inline-flex; align-items: center; gap: 6px; }
.skip-btn i { display: flex; align-items: center; justify-content: center; line-height: 1; font-size: 12px; }
/* Réservé aux VIP : texte grisé et flouté, cadenas par-dessus (comme « Tout ouvrir »).
   Le bouton reste cliquable : il mène à la fenêtre VIP. */
.skip-btn .skip-lock { display: none; }
.skip-btn.locked { cursor: pointer; }
.skip-btn.locked { color: var(--text-dim); }
.skip-btn.locked .skip-lock {
  display: flex;
  margin-left: 8px;
  font-size: 11px;
}
.reel-viewport.skippable { cursor: pointer; }

/* Les boutons vont à droite ; la rangée passe à la ligne sur petit écran. */
#vipBonusBtn { margin-left: auto; }
#vipBonusBtn.hidden { display: none; }
.open-all-btn { margin-left: 0; }
#vipBonusBtn.hidden + .open-all-btn { margin-left: auto; }
.open-all-btn.hidden { display: none; }
/* « Tout ouvrir » réservé aux VIP : bouton grisé, cadenas par-dessus. Reste
   cliquable (mène à la fenêtre VIP), donc pas de :disabled. */
.open-all-btn.locked { position: relative; cursor: pointer; }
.open-all-btn.locked { color: var(--text-dim); } /* texte flouté : le cadenas ressort */
.open-all-btn.locked .open-all-lock {
  display: inline-flex;
  font-size: 11px;
}

/* Résultats de « Tout ouvrir ». */
/* .modal-card (défini plus bas, même spécificité) impose max-width: 380px. */
.modal-card.open-all-card { max-width: 560px; }
.open-all-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 60vh;
  overflow-y: auto;
}
.open-all-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 12px;
  background: var(--surface-1);
  box-shadow: var(--block), inset 0 0 0 4px var(--hairline);
}
.open-all-thumb {
  position: relative;
  width: 64px;
  height: 36px;
  overflow: hidden;
  flex-shrink: 0;
}
.open-all-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.open-all-name {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-lg);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Inventaire ---
   Le cœur du jeu : un panneau à part entière, liseré jaune à gauche et titre
   en jaune, pour ne pas se fondre entre la scène et l'historique. */
.inventory-section {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px 18px 24px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), inset 6px 0 0 0 var(--accent), var(--shadow-md);
}
.inventory-header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; }
.inventory-header .section-label { font-size: 13px; color: var(--accent); text-shadow: var(--glitch-text); }
/* Dans le panneau, les emplacements pleins ressortent sur un fond plus clair. */
.inventory-section .crate-slot.filled { background: var(--surface-2); }
.inventory-section .crate-slot.filled:hover { background: var(--surface-3); }
.inventory-hint {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-muted);
}

/* nowrap explicite — la rangée ne doit jamais se casser en deux lignes.
   space-between : les emplacements gardent une largeur fixe (86px) mais la
   rangée s'étire pour caler son bord droit sur celui des autres sections
   (stage, historique) au lieu de rester plus courte qu'elles. */
.inventory {
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  gap: 10px;
}
.inventory.dimmed .crate-slot { opacity: .3; }

.crate-slot {
  position: relative;
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: inset 0 0 0 3px var(--outline-inner);
  cursor: default;
}
.crate-slot.filled {
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-sm);
  cursor: pointer;
}
.crate-slot.filled .crate { animation: gcCrateIdle 2.6s ease-in-out infinite; }
/* Bande des caisses en stock : même aberration rouge / cyan et même lueur que
   le marqueur de la roulette, avec un petit sursaut de temps en temps
   (décalé d'une caisse à l'autre). */
.crate-slot.filled .crate-seam {
  box-shadow: 2px 0 0 rgba(255,59,48,.45), -2px 0 0 rgba(0,213,255,.45), 0 0 12px 2px rgba(255,233,0,.3);
  animation: gcSeamGlitch 3.4s steps(1) infinite;
}
.crate-slot.filled:nth-child(3n+2) .crate-seam { animation-delay: -1.1s; }
.crate-slot.filled:nth-child(3n) .crate-seam { animation-delay: -2.3s; }
@keyframes gcSeamGlitch {
  0%, 88%, 100% { transform: none; }
  90% { transform: translateX(2px); box-shadow: 4px 0 0 rgba(255,59,48,.7), -3px 0 0 rgba(0,213,255,.7), 0 0 14px 3px rgba(255,233,0,.4); }
  93% { transform: translateX(-2px); box-shadow: -3px 0 0 rgba(255,59,48,.7), 4px 0 0 rgba(0,213,255,.7), 0 0 14px 3px rgba(255,233,0,.4); }
  96% { transform: translateX(1px); }
}
@media (prefers-reduced-motion: reduce) {
  .crate-slot.filled .crate-seam { animation: none; }
}
@keyframes gcCrateIdle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
.crate-slot.filled:hover {
  background: var(--surface-3);
}
.crate-slot.filled:active { transform: translate(3px, 3px); box-shadow: var(--block-panel), 1px 1px 0 0 var(--outline); }
.crate-slot .slot-timer {
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  font-weight: 700;
  color: var(--text-dim);
}
.crate-slot.filling { animation: omSlotFill .42s cubic-bezier(.2,1.2,.35,1) both; }

/* --- Vignette coffre : 5 div, aucune image. Les tailles dérivent de
   --crate-w, donc le même markup sert à 52px (emplacement) et au
   centre de la scène (scale 1.9 via transform). --- */
.crate {
  position: relative;
  width: var(--crate-w, 52px);
  height: calc(var(--crate-w, 52px) * .82);
  transform-origin: bottom center;
}
.crate-body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: calc(var(--crate-w) * .56);
  background: var(--surface-3);
  box-shadow: inset 0 0 0 3px var(--outline), inset -4px -4px 0 0 #0e0e12, inset 4px 4px 0 0 #2c2c34;
}
.crate-strap {
  position: absolute;
  bottom: 3px;
  width: 5px;
  height: calc(var(--crate-w) * .56 - 6px);
  background: #0e0e12;
}
.crate-strap-l { left: 22%; }
.crate-strap-r { right: 22%; }
.crate-seam {
  position: absolute;
  left: 3px;
  right: 3px;
  bottom: calc(var(--crate-w) * .56 - 2px);
  height: 4px;
  background: var(--accent);
}
.crate-lid {
  position: absolute;
  top: 0;
  left: -2px;
  right: -2px;
  height: calc(var(--crate-w) * .26);
  background: #22222a;
  box-shadow: inset 0 0 0 3px var(--outline), inset -3px -3px 0 0 #0e0e12, inset 3px 3px 0 0 #34343e;
  transform-origin: bottom center;
}

/* --- Prélude : calque au-dessus du track, sous le marker --- */
.prelude {
  position: absolute;
  inset: 0;
  z-index: 7;
  display: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  background: rgba(8,8,10,.94);
}
.prelude.active { display: flex; }
.prelude-caption {
  position: absolute;
  left: 0; right: 0;
  bottom: 18px;
  text-align: center;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-dim);
}

/* --- Le coffre en vol : clone en position:fixed sur <body> --- */
.crate-flying {
  position: fixed;
  z-index: 999;
  pointer-events: none;
  --crate-w: 52px;
  transition: transform .42s cubic-bezier(.3,.9,.3,1);
}
/* paliers de tension : la même secousse, trois vitesses */
.crate-flying.tension-1 { animation: omCrateShake 1.25s ease-in-out infinite; }
.crate-flying.tension-2 { animation: omCrateShake .85s ease-in-out infinite; }
.crate-flying.tension-3 { animation: omCrateShake .55s ease-in-out infinite; }
.crate-flying.tension-1 .crate-lid { animation: omLidTense 1.25s ease-in-out infinite; }
.crate-flying.tension-2 .crate-lid { animation: omLidTense .85s ease-in-out infinite; }
.crate-flying.tension-3 .crate-lid { animation: omLidTense .55s ease-in-out infinite; }
.crate-flying.tension-1 .crate-seam { animation: omSeamPulse 1.25s ease-in-out infinite; }
.crate-flying.tension-2 .crate-seam { animation: omSeamPulse .85s ease-in-out infinite; }
.crate-flying.tension-3 .crate-seam { animation: omSeamPulse .55s ease-in-out infinite; }

.crate-flying.bursting { animation: none; }
.crate-flying.bursting .crate-lid { animation: omCrateBurst .32s cubic-bezier(.3,1.2,.4,1) forwards; }
.crate-flying.bursting .crate-seam { animation: none; opacity: 1; }
.crate-flying.bursting .crate-body,
.crate-flying.bursting .crate-strap { animation: omCrateDrop .32s ease-in forwards; }

/* --- Keyframes --- */
@keyframes omSlotFill {
  0% { transform: scale(.4); opacity: 0; }
  60% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
/* La secousse s'ajoute au transform de vol : le clone garde son
   translate/scale dans une variable CSS posée en JS (--fly). */
@keyframes omCrateShake {
  0%, 100% { transform: var(--fly) translate3d(0,0,0) rotate(0deg); }
  12% { transform: var(--fly) translate3d(-2px,0,0) rotate(-.7deg); }
  24% { transform: var(--fly) translate3d(2px,-1px,0) rotate(.6deg); }
  36% { transform: var(--fly) translate3d(-1px,1px,0) rotate(-.4deg); }
  48% { transform: var(--fly) translate3d(1px,0,0) rotate(.3deg); }
  60% { transform: var(--fly) translate3d(0,-2px,0) rotate(0deg); }
}
@keyframes omLidTense {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  55% { transform: translateY(-4px) rotate(-1.2deg); }
  75% { transform: translateY(-1px) rotate(.4deg); }
}
@keyframes omSeamPulse {
  0%, 100% { opacity: .45; }
  55% { opacity: 1; }
}
@keyframes omCrateBurst {
  0% { transform: translateY(0) rotate(0); opacity: 1; }
  45% { transform: translateY(-14px) rotate(-9deg); opacity: 1; }
  100% { transform: translateY(-70px) rotate(-26deg); opacity: 0; }
}
@keyframes omCrateDrop {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(16px) scale(.94); opacity: 0; }
}

@media (max-width: 760px) {
  .inventory { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  .crate-flying, .crate-flying .crate-lid { animation: none !important; }
  .crate-flying { transition: none; }
}

.result-label {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.result-text {
  min-width: 0;
  font-size: var(--fs-2xl);
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.result-text.idle { color: var(--text-dim); }
.result-text.spinning { color: var(--text-dim); }
.result-text.won {
  color: var(--text-strong);
  text-shadow: 1px 0 rgba(255,59,48,.3), -1px 0 rgba(0,213,255,.3);
  animation: gcResultIn .2s steps(2) both;
}
@keyframes gcResultIn { from { transform: translateY(6px); } to { transform: none; } }

/* --- History --- */
.history-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.history-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.history-list {
  list-style: none;
  margin: 0;
  padding: 0 8px 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 296px;
  overflow-y: auto;
}

.history-item {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 13px;
  background: var(--surface-1);
  box-shadow: var(--block), inset 0 0 0 4px var(--hairline);
}
.history-item:hover { background: var(--surface-2); }

.history-item .history-thumb {
  flex: 0 0 auto;
  width: 74px;
  height: 34px;
  overflow: hidden;
  position: relative;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 2px var(--outline);
}
.history-item .history-thumb img {
  position: absolute;
  inset: 2px;
  width: calc(100% - 4px);
  height: calc(100% - 4px);
  object-fit: cover;
}

.history-item .history-thumb .history-logo {
  inset: 5px;
  width: calc(100% - 10px);
  height: calc(100% - 10px);
  object-fit: contain;
  filter: drop-shadow(1px 1px 0 rgba(0,0,0,.95));
}

.history-item .history-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-lg);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.history-item .history-time {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  color: var(--text-dim);
}

/* État vide : bloc hachuré, phrase centrée. */
.history-empty {
  margin: 0;
  padding: 22px 16px;
  font-family: var(--font-ui);
  font-size: 21px;
  text-align: center;
  color: var(--text-dim);
  background: var(--surface-1) var(--hatch);
  box-shadow: var(--block);
}

/* --- Admin --- */
.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
/* La barre de rareté (réutilise .rarity-spectrum-block de la landing,
   audit design F-14) occupe toute la largeur de la grille de stats. */
.admin-stats .admin-rarity-spectrum { grid-column: 1 / -1; max-width: none; }
.admin-rarity-spectrum .rarity-spectrum-legend { justify-content: flex-start; }
.admin-stat-card {
  background: var(--surface-1);
  box-shadow: var(--block-panel);
  padding: 12px 14px;
}
.admin-stat-card .value {
  font-family: var(--font-mono);
  font-size: var(--fm-2xl);
  font-weight: 700;
  color: var(--text-strong);
}
.admin-stat-card .label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-top: 6px;
}

.panel {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Journal de reconstruction : mono 12px sur fond noir, scanlines fixes. */
.admin-log {
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  color: var(--text-muted);
  white-space: pre-wrap;
  max-height: 160px;
  overflow-y: auto;
  background: var(--bg) repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 4px);
  box-shadow: var(--block);
  padding: 10px 12px;
}
.admin-log:empty { display: none; }

.admin-search { flex: none; width: 100%; max-width: 340px; }

.list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 13px;
  background: var(--surface-1);
  /* Pas d'ombre dure : une liste de 20 lignes deviendrait illisible. */
  box-shadow: var(--block), inset 0 0 0 4px var(--hairline);
}
.row:hover { background: var(--surface-2); }
@media (max-width: 700px) {
  .row { flex-wrap: wrap; }
  .row .row-main { flex-basis: 100%; }
}
.row-thumb {
  position: relative;
  width: 74px;
  height: 34px;
  flex-shrink: 0;
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 2px var(--outline);
}
.row-avatar {
  width: 32px;
  height: 32px;
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  border: 3px solid var(--outline);
  color: var(--ink);
  font-family: var(--font-title);
  font-size: 10px;
}
.row .row-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.row .row-title {
  font-size: var(--fs-lg);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.row .row-sub {
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  color: var(--text-dim);
}
.row select {
  appearance: none;
  background: var(--surface-2) linear-gradient(var(--accent), var(--accent)) no-repeat right 10px center / 6px 6px;
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  padding: 4px 26px 4px 8px;
}

.admin-amount-control {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.admin-amount-input {
  width: 96px;
  min-height: 32px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-mono);
  font-size: var(--fm-lg);
  padding: 0 8px;
  text-align: center;
}
.admin-amount-input:focus { border-color: var(--accent); outline: none; }
.admin-amount-input::placeholder { color: var(--text-disabled); }
.admin-amount-input::-webkit-outer-spin-button,
.admin-amount-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* --- Pagination --- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 8px;
}
.pagination-btn { padding: 0; min-width: 32px; min-height: 32px; font-family: var(--font-mono); font-size: var(--fm-lg); font-weight: 700; }
.pagination-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  color: var(--text-secondary);
  white-space: nowrap;
}
/* Numéro de page saisissable. */
.pagination-input {
  box-sizing: content-box;
  padding: 4px;
  text-align: center;
  font: inherit;
  color: var(--text-strong);
  background: var(--surface-2);
  border: 3px solid var(--outline);
  -moz-appearance: textfield;
  appearance: textfield;
}
.pagination-input::-webkit-outer-spin-button,
.pagination-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pagination-input:focus { border-color: var(--accent); outline: none; }

/* --- Profil : vitrine / liste de souhaits --- */
/* 4 emplacements (8 pour un VIP) : toujours des lignes pleines, 4 colonnes
   dès que la section le permet, sinon 2 (2 × 2, ou 4 × 2 en VIP). */
.profile-slots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.profile-slots-panel { container-type: inline-size; container-name: pslots; }
@container pslots (min-width: 480px) {
  .profile-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* Vide : contour 3px pointillé et « + » jaune. Rempli : jaquette cernée de
   la couleur de rareté. */
.profile-slot {
  position: relative;
  aspect-ratio: 920 / 430;
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
  border: 3px solid var(--rarity-edge, var(--hairline));
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.profile-slot:hover { transform: translate(-2px, -2px); box-shadow: var(--shadow-sm); }
.profile-slot.empty { color: var(--accent); font-size: 20px; background: transparent; border: 3px dashed #2c2c34; }
.profile-slot.empty:hover { border-color: var(--accent); }
.profile-slot-name {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 3px 8px;
  background: rgba(8,8,10,.82);
  font-size: var(--fs-sm);
  line-height: 1.1;
  color: var(--text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Réorganiser par glisser-déposer : le jeu saisi reste en creux à sa place,
   une copie suit le pointeur, l'emplacement visé s'encadre de jaune. */
.profile-slots-hint { margin-left: auto; font-size: var(--fs-xs); color: var(--text-dim); }
.profile-slots .profile-slot:not(.empty) { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.profile-slot.dragging { opacity: .35; }
.profile-slot.drop-target { outline: 3px solid var(--accent); outline-offset: 2px; }
.profile-slot-ghost {
  position: fixed;
  z-index: 1000;
  top: 0;
  left: 0;
  margin: 0;
  pointer-events: none;
  opacity: .92;
  box-shadow: var(--shadow-lg);
  cursor: grabbing;
}
.profile-slot-ghost .profile-slot-remove { display: none; }
@media (hover: none) { .profile-slots-hint { display: none; } }
/* Souhait déjà obtenu : badge vert en haut à gauche. */
.profile-slot-owned {
  position: absolute;
  z-index: 2;
  top: 6px;
  left: 6px;
  padding: 3px 6px;
  background: var(--success);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--outline);
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.profile-slot-remove {
  position: absolute;
  z-index: 2;
  top: 5px;
  right: 5px;
  width: 28px;
  height: 28px;
  border: none;
  background: var(--surface-2);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--block);
}
.profile-slot-remove:hover { background: var(--danger); color: var(--text-strong); }
.profile-picker-list { max-height: 320px; overflow-y: auto; }
#playerCollectionList { max-height: 400px; overflow-y: auto; }

/* --- Succès --- */
/* Cartes compactes (elles étaient jugées trop grosses). */
.achievements-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.achievement-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
/* Débloqué : contour jaune. */
.achievement-card.unlocked { box-shadow: inset 0 0 0 3px var(--accent), var(--shadow-md); }
/* Grille : icône à gauche, texte à droite, « Réclamer » dessous sur toute la
   largeur (en flex avec retour à la ligne, l'icône partait seule sur sa ligne
   dès que la description était longue). */
.achievement-card { display: grid; grid-template-columns: 34px minmax(0, 1fr); grid-template-rows: 1fr auto; align-items: start; }
.achievement-card > .btn { grid-column: 1 / -1; }
/* Pas d'opacity globale : elle cassait le contraste du texte verrouillé
   (≈3:1). L'état verrouillé passe par des couleurs explicites sur
   chaque enfant à la place (audit design F-24). */
.achievement-icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  background: var(--surface-2);
  box-shadow: var(--block);
  color: var(--accent);
}
.achievement-icon i {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.achievement-card.locked .achievement-icon {
  background: var(--surface-2);
  color: var(--text-dim);
}
.achievement-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; } /* pousse le tag « réclamé » / le bouton contre le bord droit */
.achievement-name { font-family: var(--font-title); font-size: 9px; line-height: 1.5; color: var(--text-strong); }
.achievement-card.locked .achievement-name { color: var(--text-muted); }
.achievement-desc { font-size: var(--fs-sm); line-height: 1.1; color: var(--text-muted); }
.achievement-card.locked .achievement-desc { color: var(--text-dim); }
.achievement-progress {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}
.achievement-progress-track {
  position: relative;
  flex: 1 1 auto;
  height: 14px;
  padding: 3px;
  background: var(--surface-2);
  box-shadow: var(--block);
}
.achievement-progress-track::after {
  content: '';
  position: absolute;
  inset: 3px;
  background-image: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), var(--outline) calc(10% - 2px) 10%);
}
.achievement-progress-fill {
  height: 100%;
  background: var(--accent);
}
.achievement-progress-count {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  color: var(--text-muted);
}
.achievement-reward { display: inline-flex; align-items: center; gap: 5px; margin-top: 4px; font-family: var(--font-mono); font-size: var(--fm-sm); font-weight: 700; color: var(--accent); }
.achievement-reward .fi { display: flex; font-size: 11px; }
.achievement-card.locked .achievement-reward { color: var(--text-muted); }
/* Déjà obtenus : section repliée en bas, cartes en retrait. */
.achievements-claimed { margin-top: 6px; }
.achievements-claimed > summary {
  cursor: pointer;
  padding: 8px 0;
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.achievements-claimed > summary:hover { color: var(--text-strong); }
.achievements-claimed .achievements-grid { margin-top: 8px; }
.achievement-card.claimed { background: transparent; box-shadow: inset 0 0 0 2px var(--hairline); }
.achievement-card.claimed .achievement-icon { background: transparent; color: var(--text-dim); box-shadow: inset 0 0 0 2px var(--hairline); }
.achievement-card.claimed .achievement-name { color: var(--text-muted); }
.achievement-card.claimed .achievement-desc { color: var(--text-dim); }
#achievementsClaimAll { margin-left: 12px; }

/* --- Paramètres --- */
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 10px 0;
  color: var(--text);
  font-size: var(--fs-md);
}
.settings-row + .settings-row { border-top: 3px solid var(--hairline); }
@media (max-width: 600px) {
  .settings-row { flex-wrap: wrap; }
  .settings-row > span:not(.toggle-switch) { flex-basis: 100%; }
  /* Ligne d'interrupteur : libellé à gauche, interrupteur à droite. */
  label.settings-row { flex-wrap: nowrap; }
  label.settings-row > span:not(.toggle-switch) { flex-basis: auto; }
  .settings-row > button { width: 100%; }
}
/* --- Sous-réglages (tic de défilement, un son par rareté) : en retrait,
   un cran plus discrets que l'interrupteur général qu'ils affinent. --- */
.settings-row-sub {
  padding: 8px 0 8px 24px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
/* Rangée de son : libellé, bouton « écouter », interrupteur. */
.settings-row-sound { flex-wrap: nowrap; }
.settings-row-sound > label { flex: 1 1 auto; min-width: 0; cursor: pointer; }
.settings-row-sound > .btn-icon { margin-left: auto; }
.settings-row-sound > .toggle-switch { margin-left: 4px; }
/* Bouton carré à icône seule. */
.btn-icon { width: 32px; padding: 0; color: var(--accent); }
.btn-icon .fi { display: flex; font-size: 12px; }
@media (max-width: 760px) {
  .btn-icon { width: 44px; }
  /* Plus précis que « .settings-row > button { width: 100% } » (petit écran). */
  .settings-row-sound > button.btn-icon { width: 44px; flex: none; }
}
.settings-row-sub .rarity-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 8px;
}
/* Petit texte d'explication sous un réglage (ou sous le titre d'une section). */
.settings-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.settings-desc { font-size: var(--fs-xs); color: var(--text-dim); line-height: 1.2; }
p.settings-desc { margin: 0 0 6px; max-width: 560px; }
p.settings-group-desc { margin-top: 10px; }
/* Interrupteur carré à deux positions, sans transition fluide. */
.toggle-switch {
  position: relative;
  display: inline-block;
  width: 46px;
  height: 22px;
  flex-shrink: 0;
}
/* Case invisible par-dessus le curseur dessiné : c'est elle qui reçoit le clic
   (sinon le curseur, posé après elle, l'intercepte et rien ne bascule quand
   l'interrupteur n'est pas dans un <label>). */
.toggle-switch input {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.toggle-switch input:focus-visible + .toggle-slider { outline: 3px solid var(--accent); outline-offset: 3px; }
label.settings-row { cursor: pointer; }
.toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--surface-2);
  box-shadow: var(--block);
  cursor: pointer;
}
.toggle-slider::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  left: 3px;
  top: 3px;
  background: var(--text-dim);
}
.toggle-switch input:checked + .toggle-slider {
  background: var(--surface-2);
}
.toggle-switch input:checked + .toggle-slider::before {
  transform: translateX(24px);
  background: var(--accent);
}

.danger-zone {
  box-shadow: inset 0 0 0 3px var(--danger), var(--shadow-md);
}
.danger-zone .section-label { color: var(--danger); }
.danger-zone .settings-row span { color: var(--text-secondary); max-width: 420px; }

/* --- Toasts (remplacent alert()) --- */
.toast-region {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(360px, calc(100vw - 40px));
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  cursor: pointer;
  padding: 10px 14px 10px 20px;
  background: var(--surface-2);
  box-shadow: var(--block), inset 6px 0 0 0 var(--accent), var(--shadow-sm);
  color: var(--text-strong);
  font-size: var(--fs-md);
  line-height: 1.2;
  animation: omToastIn .16s steps(2) both;
}
.toast-error { box-shadow: var(--block), inset 6px 0 0 0 var(--danger), var(--shadow-sm); }
.toast-success { box-shadow: var(--block), inset 6px 0 0 0 var(--success), var(--shadow-sm); }
/* Apparition sans fondu : une translation de 8px, par paliers. */
@keyframes omToastIn {
  0% { transform: translateY(8px); }
  100% { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

/* --- Marché : état de mon enchère --- */
.market-bid-state {
  align-self: flex-start;
  font-family: var(--font-title);
  font-size: 8px;
  line-height: 1;
  text-transform: uppercase;
  padding: 5px 8px;
  background: var(--bg);
}
.market-bid-state.leading { color: var(--success); box-shadow: inset 0 0 0 3px var(--success); }
.market-bid-state.outbid { color: var(--danger); box-shadow: inset 0 0 0 3px var(--danger); }

/* --- Modale de confirmation --- */
.modal-card.confirm-card { max-width: 420px; }
.confirm-message { margin: 0; font-size: var(--fs-md); line-height: 1.25; color: var(--text-muted); }
.confirm-typed { display: flex; flex-direction: column; gap: 8px; font-size: var(--fs-sm); color: var(--text-secondary); }
.confirm-typed input {
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  padding: 8px 12px;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
}
.confirm-typed input:focus { border-color: var(--accent); outline: none; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* --- État vide avec action --- */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 22px 16px;
  text-align: center;
  background: var(--surface-1) var(--hatch);
  box-shadow: var(--block);
}
.empty-state p { margin: 0; font-size: 21px; color: var(--text-dim); }

/* --- Amis --- */
.friend-request-form { display: flex; gap: 10px; flex-wrap: wrap; }
.friend-search { position: relative; flex: 1 1 240px; display: flex; }
.friend-request-form input {
  flex: 1 1 240px;
  min-height: 40px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  padding: 0 12px;
}
.friend-suggest {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 6px;
  background: var(--surface-2);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.friend-suggest-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 6px 8px;
  border: 0;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-md);
  text-align: left;
  cursor: pointer;
}
.friend-suggest-item .row-avatar { flex: none; }
/* Survol jaune : la ligne devient un aplat, texte à l'encre. */
.friend-suggest-item:hover, .friend-suggest-item.active { background: var(--accent); color: var(--ink); }
.friend-suggest-item:hover .friend-suggest-name, .friend-suggest-item.active .friend-suggest-name,
.friend-suggest-item:hover .friend-suggest-meta, .friend-suggest-item.active .friend-suggest-meta { color: var(--ink); }
.friend-suggest-item:disabled { cursor: default; opacity: .45; background: transparent; color: var(--text); }
.friend-suggest-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-strong); }
.friend-suggest-meta { flex: none; font-size: var(--fs-xs); color: var(--text-muted); }
.friend-suggest-empty { padding: 10px; font-size: var(--fs-md); color: var(--text-dim); }
.friend-suggest-title {
  padding: 6px 8px 4px;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.friend-request-form input::placeholder { color: var(--text-disabled); }
.friend-request-form input:focus { border-color: var(--accent); outline: none; }

.friends-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 14px;
}
.friend-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.friend-card-header { display: flex; align-items: center; gap: 12px; }
.friend-card-avatar { width: 32px; height: 32px; }
/* .row-main/-title/-sub sont scopées à ".row" en descendant
   direct (voir plus haut) : .friend-card-header n'a pas cette classe,
   d'où ces règles dédiées (sinon nom+compteur s'affichent collés). */
.friend-card-header .row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.friend-card-header .row-title { font-size: var(--fs-lg); color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.friend-card-header .row-sub { font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--text-dim); }
.friend-card-showcase { display: flex; gap: 6px; }
.friend-card-showcase-slot {
  flex: 1 1 0;
  min-width: 0;
  width: auto;
  height: auto;
  aspect-ratio: 920 / 430;
}
.friend-card-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.friend-card-actions .btn { flex: 1 1 auto; }

.friend-leaderboard-rank {
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  color: var(--text-dim);
  min-width: 28px;
  flex-shrink: 0;
}
/* Ma ligne : cerclée de jaune. */
.row.friend-leaderboard-me {
  box-shadow: inset 0 0 0 3px var(--accent);
  background: var(--surface-2);
}

/* .modal-card (même spécificité, déclarée plus bas) imposait sa largeur. */
.modal-card.friend-collection-card { max-width: 720px; max-height: 82vh; overflow-y: auto; }
/* Collection d'un ami : recherche + tri sur une ligne, raretés et « jeux que je n'ai pas » dessous. */
.friend-collection-card .album-toolbar { margin-bottom: 10px; }
.friend-collection-toolbar { flex-wrap: nowrap; }
.friend-collection-toolbar .album-search { flex: 1 1 auto; min-width: 0; }
.friend-collection-rarities { display: flex; flex-wrap: wrap; gap: 7px; }
@media (max-width: 480px) { .friend-collection-toolbar { flex-wrap: wrap; } }

/* Pastille de navigation : carré vert cerné. */

/* --- Duels --- */
/* En ligne : carré vert ; hors ligne : carré éteint. */
.duel-online-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--outline-inner);
  flex-shrink: 0;
}
.duel-online-dot.online { background: var(--success); }

.duels-queue-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
/* Pendant la recherche : clignote par paliers. */
.duels-queue-status {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--accent);
}
.duels-queue-status:not(:empty) { animation: gcBlink 1s steps(1) infinite; }

.duels-stats-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-family: var(--font-mono);
}
.duels-stats-row > div {
  min-width: 140px;
  padding: 12px 16px;
  background: var(--surface-2);
  box-shadow: var(--block), var(--shadow-sm);
}
.duels-stats-row .value { font-size: 30px; font-weight: 700; line-height: 1.1; color: var(--text-strong); }
.duels-stats-row .label { font-size: 9px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--text-dim); margin-top: 6px; }

.duel-team-picker-list { max-height: 320px; overflow-y: auto; }
.duel-team-picker-list .row { cursor: pointer; }
.duel-team-picker-list .row.selected {
  background: var(--surface-3);
  box-shadow: inset 0 0 0 3px var(--accent);
}

/* --- Duels : modale de combat --- */
/* .modal-card.duel-battle-card (spécificité 2 classes) pour l'emporter sur
   .modal-card { max-width: 380px } malgré son ordre plus tardif dans la feuille. */
.modal-card.duel-battle-card { max-width: 720px; position: relative; overflow: hidden; }

.duel-battle-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Le conteneur défile (overflow-y) et rogne donc aussi les côtés : marge pour
     que le cadre doré des avatars VIP ne soit pas coupé. */
  padding: 6px 8px 0;
}
.duel-battle-side .vip-frame {
  box-shadow: 0 0 0 3px var(--accent);
}
.duel-battle-side { display: flex; align-items: center; gap: 10px; min-width: 0; }
.duel-battle-side-right { flex-direction: row-reverse; }
.duel-battle-side .friend-card-avatar { width: 32px; height: 32px; }
.duel-battle-name {
  font-size: var(--fs-lg);
  color: var(--text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.duel-battle-round-count {
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dim);
  flex-shrink: 0;
}

/* --- Arène : toi | centre | adversaire --- */
.duel-battle-arena {
  display: grid;
  grid-template-columns: 1fr 210px 1fr;
  gap: 14px;
  align-items: start;
  padding: 6px 0 2px;
}
.duel-battle-sidecol {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}

/* --- Portrait : la carte active --- */
.duel-portrait { position: relative; width: 190px; }
/* Carte active : jaquette, PV en barre segmentée, ATK en badge, liseré de rareté. */
.duel-portrait-inner {
  position: relative;
  padding: 9px;
  background: var(--surface-1);
  box-shadow: inset 0 0 0 3px var(--rarity, var(--outline)), var(--shadow-md);
  animation: omBreathe2 3.4s steps(2) infinite;
}
/* décalage pour éviter le battement synchrone des deux camps */
#duelBattleOpponentSide .duel-portrait-inner { animation-delay: .7s; }
/* pendant TA décision, plus rien ne bouge */
.duel-battle-arena.deciding .duel-portrait-inner { animation-play-state: paused; }

.duel-portrait .duel-card-media {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 108px;
}
.duel-portrait-name {
  padding: 6px 2px 0;
  font-size: var(--fs-md);
  color: var(--text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.duel-portrait-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 0 0;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
}
.duel-portrait-hp { color: var(--text-muted); }
.duel-portrait-atk { padding: 2px 5px; background: var(--accent); color: var(--ink); box-shadow: inset 0 0 0 2px var(--outline); }

.duel-portrait-hp-track, .duel-card-hp-track {
  position: relative;
  height: 12px;
  padding: 3px;
  margin: 7px 0 0;
  background: var(--surface-2);
  box-shadow: var(--block);
}
.duel-portrait-hp-track::after, .duel-card-hp-track::after {
  content: '';
  position: absolute;
  inset: 3px;
  background-image: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), var(--outline) calc(10% - 2px) 10%);
}
.duel-hp-fill {
  height: 100%;
  background: var(--success);
}
.duel-hp-fill.low { background: var(--danger); }

/* voile rouge d'impact */
/* Voile rouge d'impact : un aplat, par paliers. */
.duel-portrait-tint {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: rgba(255,59,48,.35);
}
.duel-portrait-tint.hit { animation: omHitTint .5s ease-out; }
.duel-portrait-inner.hit { animation: omHitShake .42s cubic-bezier(.36,.07,.19,.97); }
.duel-portrait-inner.ko { animation: omKo .52s cubic-bezier(.4,.1,.7,.9) forwards; }
.duel-portrait-inner.promote { animation: omPromote .48s cubic-bezier(.2,1.15,.35,1) both; }

/* calque des nombres flottants : hors du flux, ne décale jamais rien */
.duel-fx {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}
.duel-dmg {
  position: absolute;
  left: 50%;
  top: 34%;
  transform: translate(-50%, 0);
  font-family: var(--font-title);
  font-size: 18px;
  color: var(--danger);
  text-shadow: 3px 3px 0 var(--outline);
  animation: omDmgFloat .9s steps(6) forwards;
}
.duel-dmg-ring {
  position: absolute;
  left: 50%;
  top: 34%;
  width: 70px;
  height: 70px;
  margin: -35px 0 0 -35px;
  border: 3px solid var(--danger);
  animation: omRing .5s steps(4) forwards;
}

/* --- Banc : les deux réservistes --- */
.duel-bench { display: flex; gap: 8px; }
.duel-card {
  position: relative;
  width: 64px;
  overflow: hidden;
  background: var(--surface-1);
  padding: 4px;
  box-shadow: inset 0 0 0 3px var(--rarity, var(--outline));
}
/* K.O. : atténué, croix jaune par-dessus. */
.duel-card.duel-card-dead { opacity: .3; }
.duel-card.duel-card-dead::after {
  content: '\00D7';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-size: 40px;
  line-height: 1;
  color: var(--accent);
}
.duel-card .duel-card-media { width: 100%; height: 34px; }
.duel-card-hp-track { height: 10px; margin: 4px 0 0; }

/* --- Centre : axe, plaques, verdict --- */
.duel-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding-top: 6px;
}
.duel-axis-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  background: var(--accent);
  color: var(--ink);
  box-shadow: var(--block), var(--shadow-sm);
  font-family: var(--font-title);
  font-size: 9px;
  line-height: 1.4;
  text-transform: uppercase;
  white-space: nowrap;
}
.duel-axis-chip.reveal, .duel-battle-axis.reveal {
  animation: omAxisIn .34s cubic-bezier(.2,1.1,.35,1) both;
}
.duel-plates {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  justify-content: center;
}
.duel-plates-vs {
  font-family: var(--font-title);
  font-size: 9px;
  color: var(--text-dim);
}
/* Plaques de valeur carrées. */
.duel-plate {
  flex: 1 1 0;
  min-width: 0;
  height: 52px;
  background: var(--surface-2);
  box-shadow: var(--block);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--fm-lg);
  font-weight: 700;
  color: var(--text-dim);
}
.duel-plate.revealed {
  color: #fff;
  animation: omPlateFlip .26s cubic-bezier(.2,1.1,.35,1) both;
}
.duel-plate.plate-win { box-shadow: inset 0 0 0 3px var(--success); }
.duel-plate.plate-lose { box-shadow: inset 0 0 0 3px var(--danger); }

.duel-verdict {
  min-height: 22px;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-dim);
  text-align: center;
  white-space: nowrap;
}
.duel-verdict.waiting { animation: gcBlink 1s steps(1) infinite; }
.duel-verdict.ok { color: var(--success); animation: omVerdict .3s cubic-bezier(.2,1.2,.35,1) both; }
.duel-verdict.bad { color: var(--danger); animation: omVerdict .3s cubic-bezier(.2,1.2,.35,1) both; }

/* --- Bloc de manche --- */
.duel-battle-round {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 0;
  border-top: 3px solid var(--hairline);
  border-bottom: 3px solid var(--hairline);
}
.duel-battle-axis { font-size: var(--fs-lg); color: var(--text-strong); text-align: center; }
.duel-battle-turn-hint {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}
.duel-think { display: inline-flex; gap: 3px; margin-left: 2px; }
.duel-think span {
  width: 3px;
  height: 3px;
  background: var(--text-tertiary);
  animation: omThink 1.1s ease-in-out infinite;
}
.duel-think span:nth-child(2) { animation-delay: .16s; }
.duel-think span:nth-child(3) { animation-delay: .32s; }

/* PLUS / MOINS : deux boutons principaux, la moitié chacun. */
.duel-battle-guess-buttons { display: flex; gap: 12px; width: 100%; }
.duel-battle-guess-buttons .btn { flex: 1 1 0; min-height: 48px; }
.duel-battle-guess-buttons .btn.picked {
  background: var(--accent-hover);
  transform: translate(3px, 3px);
  box-shadow: var(--block), 1px 1px 0 0 var(--outline);
}
.duel-battle-guess-buttons .btn.unpicked { opacity: .35; }

/* Compte à rebours du tour : gros, dans la zone vide sous « plus ou moins ? ». */
.duel-battle-timer {
  font-family: var(--font-mono);
  font-size: var(--fm-2xl);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
  min-height: 24px;
  margin-top: 4px;
}
/* Minuteur du tour en barre segmentée, vidée par pas de 10 %. */
.duel-timer-bar {
  position: relative;
  width: 100%;
  height: 14px;
  padding: 3px;
  background: var(--surface-2);
  box-shadow: var(--block);
}
.duel-timer-bar::after {
  content: '';
  position: absolute;
  inset: 3px;
  background-image: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), var(--outline) calc(10% - 2px) 10%);
}
.duel-timer-bar > span { display: block; height: 100%; width: 0; background: var(--accent); }
.duel-timer-bar.urgent > span { background: var(--danger); }
.duel-battle-timer.urgent { color: var(--danger); animation: gcBlink 1s steps(1) infinite; }
@keyframes omTimerUrgent {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

/* --- Journal --- */
/* Journal de combat : mono 12px, fond noir, contour 3px. */
.duel-battle-log {
  max-height: 110px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  background: var(--bg);
  box-shadow: var(--block);
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  color: var(--text-muted);
}
.duel-battle-log:empty { display: none; }
.duel-battle-log .log-ok { color: var(--success); }
.duel-battle-log .log-bad { color: var(--danger); }

/* --- Fin de match : calque plein cadre --- */
/* Fin de match : bandeau plein cadre. */
.duel-over {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(8,8,10,.92) repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 4px);
  animation: omOverIn .2s steps(2) both;
}
.duel-over.hidden { display: none; }
.duel-over-glow { display: none; }
.duel-over-confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.duel-over-confetti span {
  position: absolute;
  top: -10px;
  opacity: 0;
  animation: omConfetti 2s cubic-bezier(.3,.5,.5,1) forwards;
}
.duel-over-stack {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  animation: omOverText .42s cubic-bezier(.2,1.15,.35,1) both;
}
.duel-over-kicker {
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--success);
}
.duel-over.lost .duel-over-kicker { color: var(--danger); }
.duel-over-title {
  font-family: var(--font-title);
  font-size: 20px;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--text-strong);
  text-align: center;
  text-shadow: var(--glitch-text), 0 4px 0 var(--outline);
}
.duel-over-reward {
  font-family: var(--font-mono);
  font-size: var(--fm-2xl);
  font-weight: 700;
  color: var(--accent);
  animation: omOverText .3s steps(3) .3s both;
}
.duel-over-sub {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-muted);
  text-align: center;
  max-width: 420px;
}

/* --- Keyframes --- */
@keyframes omDmgFloat {
  0%   { opacity: 0; transform: translate(-50%, 6px) scale(.7); }
  18%  { opacity: 1; transform: translate(-50%, -2px) scale(1.25); }
  100% { opacity: 0; transform: translate(-50%, -52px) scale(1); }
}
@keyframes omRing {
  0%   { opacity: .8; transform: scale(.6); }
  100% { opacity: 0; transform: scale(1.9); }
}
@keyframes omHitShake {
  0%, 100% { transform: translate3d(0,0,0); }
  15% { transform: translate3d(-7px,2px,0) rotate(-1.2deg); }
  32% { transform: translate3d(6px,-2px,0) rotate(1deg); }
  52% { transform: translate3d(-4px,1px,0) rotate(-.6deg); }
  72% { transform: translate3d(3px,0,0) rotate(.3deg); }
}
@keyframes omHitTint {
  0% { opacity: 0; }
  12% { opacity: .85; }
  100% { opacity: 0; }
}
@keyframes omKo {
  0%   { transform: none; opacity: 1; filter: grayscale(0); }
  22%  { transform: translateY(-8px) scale(1.03); filter: grayscale(.4); }
  100% { transform: translateY(34px) scale(.86) rotate(-4deg); opacity: .14; filter: grayscale(1); }
}
@keyframes omPromote {
  0%   { opacity: 0; transform: translateY(26px) scale(.92); }
  62%  { opacity: 1; transform: translateY(-4px) scale(1.02); }
  100% { opacity: 1; transform: none; }
}
@keyframes omAxisIn {
  0%   { opacity: 0; transform: translateY(-10px) scale(.94); }
  100% { opacity: 1; transform: none; }
}
@keyframes omPlateFlip {
  0%   { transform: rotateX(-90deg); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
@keyframes omVerdict {
  0%   { opacity: 0; transform: scale(.8); }
  22%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes omSuspense {
  0%, 100% { opacity: .28; letter-spacing: .28em; }
  50%      { opacity: .85; letter-spacing: .4em; }
}
@keyframes omBreathe2 {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
@keyframes omThink {
  0%, 80%, 100% { opacity: .2; transform: translateY(0); }
  40%           { opacity: 1; transform: translateY(-3px); }
}
@keyframes omOverIn {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes omOverText {
  0%   { opacity: 0; transform: translateY(14px) scale(.94); }
  100% { opacity: 1; transform: none; }
}
@keyframes omGlowPulse {
  0%, 100% { opacity: .25; transform: scale(.96); }
  50%      { opacity: .7; transform: scale(1.04); }
}
@keyframes omConfetti {
  0%   { opacity: 0; transform: translate3d(0,-30px,0) rotate(0); }
  12%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--cx), 340px, 0) rotate(var(--cr)); }
}

@media (max-width: 760px) {
  .duel-battle-arena { grid-template-columns: 1fr; }
  .duel-portrait { width: 100%; max-width: 220px; }
  .duel-center { order: 2; }
  #duelBattleOpponentSide { order: 3; }
}
/* Coupé, pas ralenti — comme le reste de l'app. */
@media (prefers-reduced-motion: reduce) {
  .duel-battle-card *, .duel-battle-card {
    animation: none !important;
    transition: none !important;
  }
}

/* --- Devise : sous le pseudo, dans la carte joueur --- */
.sidebar-currency {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--fm-lg);
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}
.sidebar-currency i { color: var(--accent); font-size: 13px; display: flex; }

/* --- Marche --- */
.market-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}

.market-card {
  position: relative;
  overflow: hidden;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
  display: flex;
  flex-direction: column;
}
/* Meilleur enchérisseur : liseré vert. */
.market-card.leading { box-shadow: inset 0 0 0 3px var(--success), var(--shadow-md); }

.market-card .market-art-wrap {
  position: relative;
  aspect-ratio: 920 / 430;
  margin: 4px 4px 0;
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
}
.market-card .market-art-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(8,8,10,.35);
}
.market-card .market-art-wrap img.bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.market-card .market-art-wrap img.logo {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 78%;
  max-height: 62%;
  object-fit: contain;
  filter: drop-shadow(2px 2px 0 rgba(0,0,0,.95));
}
.market-card .market-art-wrap .rarity-badge {
  position: absolute;
  z-index: 2;
  top: 7px;
  left: 7px;
}
.market-card .market-timer {
  position: absolute;
  z-index: 2;
  top: 7px;
  right: 7px;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  padding: 3px 6px;
  box-shadow: inset 0 0 0 2px var(--outline);
}
/* Dernière minute : rouge, clignote à 1 Hz par paliers (pas de fondu). */
.market-card .market-timer.urgent {
  background: var(--bg);
  color: var(--danger);
  box-shadow: inset 0 0 0 2px var(--danger);
  animation: gcBlink 1s steps(1) infinite;
}

.market-card .market-info {
  padding: 12px 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.market-card .market-name {
  font-size: var(--fs-lg);
  color: var(--text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.market-card .market-bid-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.market-card .market-bid-value {
  font-family: var(--font-mono);
  font-size: var(--fm-xl);
  font-weight: 700;
  color: var(--accent);
}
.market-card .market-bid-form {
  display: flex;
  gap: 6px;
}
/* Un seul bouton, au montant fixé par le serveur : il prend toute la largeur. */
.market-card .market-bid-form .btn { flex: 1; }
/* Filtres « jeux que je n'ai pas » / « liste de souhaits ». */
.market-extra-filters { gap: 7px; }
/* Étiquettes sur la carte : souhaité (jaune), déjà à toi (neutre). */
.market-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.market-tag { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px; font-family: var(--font-mono); font-size: var(--fm-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; box-shadow: inset 0 0 0 2px currentColor; }
.market-tag .fi { display: flex; font-size: 10px; }
.market-tag.wished { color: var(--accent); }
.market-tag.owned { color: var(--text-dim); }
/* Cote : prix moyen des dernières ventes, vert sous la cote, rouge au-dessus. */
.market-cote { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: var(--fs-sm); color: var(--text-dim); }
.market-cote-value { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--text-muted); }
.market-cote-value.good { color: var(--success); }
.market-cote-value.high { color: var(--danger); }
.market-cote-value.none { font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 400; color: var(--text-dim); }
/* Vendeur et meilleur enchérisseur : libellé à gauche, pseudo à droite. */
.market-people { display: flex; flex-direction: column; gap: 3px; }
.market-person { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-width: 0; font-size: var(--fs-sm); color: var(--text-dim); }
.market-person-label { flex: none; }
.market-person-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-strong); }
.market-person-name.me { color: var(--accent); }
.market-person-name.empty { color: var(--text-dim); }
.row-main .market-person { justify-content: flex-start; }
.market-card .market-seller {
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  color: var(--text-dim);
}
/* Mes ventes : enchère en cours (jaune) et temps restant, à droite. */
.market-row-bid {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--fm-xl);
  font-weight: 700;
  color: var(--accent);
}
.market-row-time {
  flex: none;
  min-width: 64px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  color: var(--text-dim);
}

/* --- Modales --- */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(8,8,10,.86) repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.modal-card {
  position: relative;
  width: 100%;
  max-width: 480px;
  background: var(--surface-1);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: var(--block-panel), var(--shadow-lg);
}
.modal-card h3 {
  margin: 0;
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--text-strong);
}
/* Espace pour le bouton de fermeture, maintenant dans la carte plutôt que
   flottant à l'extérieur (audit design F-20). Seulement les titres juste
   sous le bouton (enfant direct) : #gdName est ailleurs dans une colonne
   étroite, ce padding le ferait inutilement déborder. */
.modal-card > h3 {
  padding-right: 44px;
}

.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 5;
  background: var(--surface-2);
  border: none;
  color: var(--text);
  width: 32px;
  height: 32px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--block);
}
/* --- En-tête Caisses + modale d'explications --- */
.cases-title-block { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; }
/* Téléphone : le bouton d'aide (44 px, cible tactile) toujours sous le titre.
   À côté d'un titre court (Duels), il le recentrait plus bas que sur les
   autres pages. */
@media (max-width: 760px) {
  .cases-title-block { flex-direction: column; align-items: flex-start; }
}
.cases-info-link { padding: 5px 11px; font-size: var(--fs-md); }

.cases-info-card { max-width: 560px; max-height: 82vh; overflow-y: auto; }
.cases-info-block { display: flex; flex-direction: column; gap: 8px; }
.cases-info-block h4 {
  margin: 0;
  font-family: var(--font-title);
  font-size: 10px;
  font-weight: 400;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--text-strong);
}
.cases-info-block p {
  margin: 0;
  font-size: var(--fs-md);
  line-height: 1.2;
  color: var(--text-muted);
}
.cases-info-sublabel {
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  color: var(--text-tertiary);
}
.cases-info-rarity-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cases-info-rarity-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--fs-xs);
  color: var(--text);
}
.cases-info-rarity-list .mono-note-value {
  font-family: var(--font-mono);
  color: var(--text-secondary);
}

.modal-close:hover { background: var(--surface-3); color: var(--text-strong); }
.modal-close i {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.modal-game-art {
  position: relative;
  aspect-ratio: 920 / 430;
  overflow: hidden;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 3px var(--outline);
}
.modal-game-art::after {
  content: '';
  position: absolute;
  inset: 3px;
  background: rgba(8,8,10,.35);
}
.modal-game-art img:first-child {
  position: absolute;
  inset: 3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  object-fit: cover;
}
.modal-game-art img#gdLogo {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 78%;
  max-height: 60%;
  object-fit: contain;
  filter: drop-shadow(2px 2px 0 rgba(0,0,0,.95));
}
.modal-name-fallback {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  text-align: center;
  color: var(--text-strong);
  font-size: var(--fs-xl);
}

.modal-card-wide { max-width: 720px; }

.modal-game-detail {
  display: flex;
  gap: 20px;
}
.modal-game-media {
  flex: 0 0 42%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
/* Nom du jeu : une phrase, donc VT323 (Press Start 2P reste aux libellés). */
.modal-game-media h3 {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 28px;
  line-height: 1.05;
  text-transform: none;
  color: var(--text-strong);
}
.modal-game-stats {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  /* Le bouton fermer (32 px, en haut à droite de la carte) recouvrait la
     valeur de la première ligne. */
  padding-top: 34px;
}
.modal-stat-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 3px solid var(--hairline);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.modal-stat-value {
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  font-weight: 700;
  color: var(--text-strong);
  text-align: right;
  white-space: nowrap;
}
.modal-steam-link { margin-top: 2px; color: var(--accent); }
.modal-steam-link:hover { color: var(--accent-hover); }

@media (max-width: 560px) {
  .modal-game-detail { flex-direction: column; }
  .modal-game-media { flex: none; }
  .modal-game-stats { padding-top: 0; }
}

.listing-market-stats {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--surface-2);
  box-shadow: var(--block);
  padding: 12px 14px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.listing-market-stats .stat-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.listing-market-stats .stat-value {
  font-family: var(--font-mono);
  font-size: var(--fm-lg);
  font-weight: 700;
  color: var(--accent);
}
.listing-market-stats .stat-sales {
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  color: var(--text-disabled);
}
.listing-market-stats.empty {
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--text-dim);
  text-align: center;
  background: var(--surface-2) var(--hatch);
}

.listing-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: var(--fs-md);
  color: var(--text-muted);
}
.listing-field input {
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-mono);
  font-size: var(--fm-xl);
  font-weight: 700;
  padding: 8px 12px;
}
.listing-field input:focus { border-color: var(--accent); outline: none; }

.duration-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.btn-option.active {
  background: var(--accent);
  color: var(--ink);
}
.btn-option.active:hover:not(:disabled) { background: var(--accent-hover); color: var(--ink); }

/* Erreur : bloc au contour rouge. */
.listing-error {
  padding: 8px 12px;
  font-size: var(--fs-md);
  color: var(--danger);
  box-shadow: inset 0 0 0 3px var(--danger);
}

/* Cibles tactiles < 44px sous mobile (audit design F-31) : desktop garde
   la taille compacte "sm" (32px) définie plus haut. Placé en fin de
   fichier pour gagner le conflit de cascade à spécificité égale contre
   ces mêmes règles "sm" déclarées avant. */
@media (max-width: 760px) {
  .btn, .tag-chip {
    min-height: 44px;
  }
}

/* Enchère ouverte par un lien (#market/<id>) : brève mise en évidence. */
.market-card-linked { animation: omLinkedPulse 1.1s ease-out 2; }
@keyframes omLinkedPulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  40% { box-shadow: 0 0 0 3px var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .market-card-linked { animation: none; box-shadow: 0 0 0 3px var(--accent); }
}

/* Modale de combat : le contenu défile dans la carte (le calque de fin,
   lui, reste plein cadre) et le bloc de réponse reste collé en bas —
   Plus/Moins ne doivent jamais sortir de l'écran pendant que le
   minuteur tourne (audit P2-10). */
.modal-card.duel-battle-card { max-height: 92vh; }
.duel-battle-scroll {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
@media (max-width: 900px) {
  .duel-battle-round {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: #12161d;
  }
}

/* Lien d'évitement : hors écran, visible dès qu'il prend le focus (Tab). */
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 1100;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--ink);
  font-size: var(--fs-md);
  box-shadow: var(--block), var(--shadow-sm);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }
#mainContent:focus { outline: none; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* P3-08 : réglage « réduire les animations ». Le flash plein cadre, les
   étincelles, la secousse de scène et toute animation CSS restante sont
   neutralisés ; le défilement du reel (piloté en JS) et les confettis sont
   coupés côté TypeScript (motion.ts). Durée quasi nulle plutôt que
   « animation: none » pour que les états finaux (résultat affiché) restent
   appliqués. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .flash.show { animation: none; opacity: 0; }
  .sparks span { display: none; }
}

/* --- Actions sous le résultat d'un tirage (audit P2-16) --- */
/* Hauteur réservée : les boutons apparaissent sans pousser le stock. */
/* Actions sur le jeu tiré (Voir la fiche…) : dans la barre de résultat, à
   droite, à côté du nom et de la rareté. */
.result-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-left: auto;
  flex-shrink: 0;
}
.result-actions:empty { display: none; }
@media (max-width: 760px) {
  .result-bar { flex-wrap: wrap; }
  .result-actions { width: 100%; justify-content: flex-start; margin-left: 0; }
}

/* --- Bande de statistiques du profil (audit P2-14) --- */
.profile-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}
.stat-tile {
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-sm);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.stat-tile-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.stat-tile-value {
  font-family: var(--font-mono);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 700;
  line-height: 1.1;
  color: var(--text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.stat-tile-value.mono {
  font-family: var(--font-mono);
}
.stat-tile-sub {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Répartition : segments carrés séparés par le contour. */
.rarity-bar {
  display: flex;
  gap: 3px;
  height: 16px;
  margin: 7px 3px 3px;
  overflow: hidden;
  background: var(--outline);
  box-shadow: 0 0 0 3px var(--outline);
}
.rarity-bar > span { display: block; height: 100%; }
.rarity-bar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  color: var(--text-muted);
}
.rarity-bar-legend i {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 5px;
}

/* --- Objectifs de collection (audit P3-15) --- */
.goals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); /* album + raretés : une rangée si ça tient */
  gap: 10px;
}
.goal {
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-sm);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.goal-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.goal-name { font-family: var(--font-title); font-size: 9px; line-height: 1.4; text-transform: uppercase; color: var(--goal-tone, var(--text-strong)); white-space: nowrap; }
.goal-count { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--text-strong); white-space: nowrap; }
/* Barre segmentée : remplissage par pas de 10 %, dix cases séparées. */
.goal-track {
  position: relative;
  height: 16px;
  padding: 3px;
  background: var(--surface-2);
  box-shadow: var(--block);
}
.goal-track::after {
  content: '';
  position: absolute;
  inset: 3px;
  background-image: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), var(--outline) calc(10% - 2px) 10%);
}
.goal-fill {
  height: 100%;
  background: var(--goal-tone, var(--accent));
}
.goal-next {
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.goal.done .goal-next { color: var(--success); }
@media (max-width: 720px) {
  .goals {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 158px;
    overflow-x: auto;
    padding-bottom: 4px;
  }
}

/* Montant en pièces dans un bouton : même teinte que le solde. */
.coin-amount {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 6px;
  color: var(--currency);
  font-family: var(--font-mono);
}

/* --- VIP --- */
.vip-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 8px;
  padding: 4px 6px;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--font-title);
  font-size: 8px;
  line-height: 1;
  vertical-align: middle;
  box-shadow: inset 0 0 0 2px var(--outline);
}
/* Cadre doré autour de l'avatar des abonnés. */
.vip-frame {
  box-shadow: 0 0 0 3px var(--accent), 0 0 0 6px rgba(255,233,0,.5);
}
.vip-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 8px;
  border: none;
  background: var(--surface-2);
  color: var(--accent);
  font-family: var(--font-title);
  font-size: 9px;
  line-height: 1.3;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: var(--block), var(--shadow-sm);
}
.vip-nav-btn i { font-size: 12px; }
.vip-nav-btn:active { transform: translate(3px, 3px); box-shadow: var(--block), 1px 1px 0 0 var(--outline); }
.vip-nav-btn { white-space: nowrap; }
/* En-tête mobile : « Devenir VIP » se réduit à « VIP » (place comptée). */
@media (max-width: 760px) {
  .vip-nav-btn { padding: 6px 10px; }
  .vip-nav-btn #vipNavLabel { font-size: 0; }
  .vip-nav-btn #vipNavLabel::after { content: 'VIP'; font-size: 9px; }
}
.vip-nav-btn:hover { background: var(--surface-3); color: var(--text-strong); }
/* Abonné ou non : même boîte que la monnaie (tout le pied de colonne partage
   le même traitement). */
.modal-card.vip-card { max-width: 440px; }
.vip-status { color: var(--text-secondary); font-size: var(--fs-sm); }
.vip-status.active { color: var(--currency); }
.vip-perks {
  list-style: none;
  margin: 14px 0 18px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: var(--fs-sm);
  color: var(--text);
}
.vip-perks li { padding-left: 22px; position: relative; }
.vip-perks li::before { content: ''; position: absolute; left: 2px; top: .45em; width: 6px; height: 6px; background: var(--accent); }
.section-count {
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  font-weight: 700;
  color: var(--text-muted);
}

/* Précision plus petite après le libellé d'un bouton (ex. heure de dispo). */
.btn-note {
  font-family: var(--font-mono);
  font-size: var(--fm-sm);
  opacity: .8;
}

/* Page Caisses sur ordinateur : exactement la hauteur de la fenêtre. L'historique
   prend la place qui reste (défilement interne), donc aucun défilement de la page
   quelle que soit la hauteur — sous 690 px de contenu, la page défile normalement. */
@media (min-width: 761px) {
  #casesPanel {
    height: calc(100vh - var(--pad-top) - var(--pad-bottom));
    min-height: 860px;
  }
  #casesPanel .history-section {
    flex: 1 1 0;
    min-height: 130px;
    display: flex;
    flex-direction: column;
  }
  #casesPanel .history-list {
    flex: 1 1 0;
    min-height: 64px;
    max-height: none;
  }
}

/* Page Profil sur ordinateur : emplacements plus plats (et avatar plus petit) quand
   la fenêtre est basse, pour que vitrine + souhaits tiennent sans défiler, même
   avec les 2 rangées d'un VIP. */
@media (min-width: 761px) and (max-height: 1000px) {
  .profile-slot { aspect-ratio: 920 / 360; }
  .profile-avatar { width: 68px; height: 68px; }
}
@media (min-width: 761px) and (max-height: 900px) {
  .profile-slot { aspect-ratio: 920 / 300; }
}
@media (min-width: 761px) and (max-height: 800px) {
  .profile-slot { aspect-ratio: 920 / 230; }
  .profile-avatar { width: 56px; height: 56px; }
}

/* --- Mini-jeux : salle permanente --- */
.room-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 20px;
  align-items: start;
}
@media (max-width: 900px) {
  .room-layout { grid-template-columns: minmax(0, 1fr); }
}
.room-round-top {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* La question de la manche : un vrai titre, lisible d'un coup d'œil. */
/* La question de la manche : Press Start 2P, lisible d'un coup d'œil. */
.room-question {
  margin: 4px 0 0;
  text-align: center;
  font-family: var(--font-title);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--text-strong);
  text-wrap: balance;
}
.room-answered { font-size: var(--fs-md); color: var(--text-muted); white-space: nowrap; }
.room-timer {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 3px 7px;
  font-family: var(--font-mono);
  font-size: var(--fm-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--accent);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--outline);
}
.room-timer:empty { display: none; }
.room-timer.urgent { background: var(--bg); color: var(--danger); box-shadow: inset 0 0 0 2px var(--danger); }
/* Barre segmentée, vidée par pas de 10 % (room.ts). */
.room-progress { position: relative; height: 16px; padding: 3px; background: var(--surface-2); box-shadow: var(--block); }
.room-progress::after { content: ''; position: absolute; inset: 3px; background-image: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), var(--outline) calc(10% - 2px) 10%); }
.room-progress-fill { height: 100%; background: var(--accent); }
.room-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  min-height: 200px;
  justify-content: center;
}
.room-game-wrap { min-width: 0; width: min(300px, 100%); display: flex; flex-direction: column; gap: 8px; }
.room-game { position: relative; overflow: hidden; aspect-ratio: 920 / 430; background: var(--surface-2) var(--hatch); box-shadow: inset 0 0 0 3px var(--outline); }
.room-game .gamecard-logo { max-width: 70%; max-height: 60%; }
.room-game-name {
  font-size: var(--fs-md);
  color: var(--text-strong);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.room-answer { display: flex; flex-direction: column; align-items: center; gap: 12px; width: min(340px, 100%); }
.room-answer-value {
  font-family: var(--font-mono);
  font-size: var(--fm-2xl);
  font-weight: 700;
  color: var(--accent);
}
/* Curseur carré : piste 10px, poignée jaune 20px. */
.room-slider {
  width: 100%;
  height: 20px;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
}
.room-slider::-webkit-slider-runnable-track { height: 10px; background: var(--surface-2); box-shadow: var(--block); }
.room-slider::-moz-range-track { height: 10px; background: var(--surface-2); box-shadow: var(--block); }
.room-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -5px;
  border: none;
  background: var(--accent);
  box-shadow: inset 0 0 0 3px var(--outline);
}
.room-slider::-moz-range-thumb { width: 20px; height: 20px; border: none; background: var(--accent); box-shadow: inset 0 0 0 3px var(--outline); }
.room-slider:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.room-price-field {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  font-size: var(--fs-xl);
  color: var(--text-muted);
}
.room-price-input {
  width: 8ch;
  padding: 10px 0;
  text-align: right;
  font: inherit;
  font-family: var(--font-mono);
  color: #fff;
  background: transparent;
  border: none;
  outline: none;
  -moz-appearance: textfield;
  appearance: textfield;
}
.room-price-input::-webkit-outer-spin-button,
.room-price-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.room-price-field:focus-within { border-color: var(--accent); }
.room-submit { min-width: 160px; }
.room-choices { display: flex; gap: 12px; width: 100%; min-width: 0; justify-content: center; }
/* Choix : blocs pleine largeur, sélectionné en jaune. */
.room-choice {
  flex: 1 1 0;
  min-width: 0; /* un nom long ne doit pas élargir la carte (il est tronqué) */
  max-width: 260px;
  padding: 9px;
  background: var(--surface-2);
  border: none;
  box-shadow: var(--block), var(--shadow-sm);
  cursor: pointer;
  color: inherit;
}
.room-choice:hover:not(:disabled) { background: var(--surface-3); }
.room-choice:active:not(:disabled) { transform: translate(3px, 3px); box-shadow: var(--block), 1px 1px 0 0 var(--outline); }
.room-choice.selected { background: var(--accent); }
.room-choice.selected .room-game-name { color: var(--ink); }
.room-choice:disabled { cursor: default; opacity: .6; }
.room-choice .room-game-wrap { width: 100%; }
.room-choice-result { cursor: default; text-align: center; }
/* Retour : liseré vert (bonne réponse) ou rouge (la mienne, fausse), sans secousse. */
.room-choice-result.correct { box-shadow: inset 0 0 0 3px var(--success), var(--shadow-sm); }
.room-choice-result.yours:not(.correct) { box-shadow: inset 0 0 0 3px var(--danger), var(--shadow-sm); }
.room-choice-value { margin-top: 8px; font-family: var(--font-mono); font-size: var(--fm-lg); font-weight: 700; color: var(--text-strong); }
.room-feedback { min-height: 22px; font-size: var(--fs-md); color: var(--text-muted); text-align: center; }
.room-reveal-head { display: flex; gap: 28px; align-items: center; justify-content: center; flex-wrap: wrap; }
.room-correct { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.room-correct-label { font-size: var(--fs-sm); color: var(--text-muted); }
.room-correct-value { font-family: var(--font-mono); font-size: var(--fm-2xl); font-weight: 700; color: var(--success); }
.room-mine { display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: var(--fs-md); color: var(--text); }
.room-score { font-family: var(--font-mono); font-size: var(--fm-xl); font-weight: 700; color: var(--text-strong); }
.room-reward { color: var(--currency); font-family: var(--font-mono); }
.room-reward .coin-amount { margin-left: 0; }
.room-podium { list-style: none; margin: 0; padding: 0; width: min(420px, 100%); display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); }
.room-podium li { display: flex; align-items: baseline; gap: 10px; color: var(--text); }
.room-podium li > :first-child { flex: 1 1 auto; min-width: 0; }
.room-podium-guess {
  min-width: 0;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-secondary);
}
.room-podium-title { font-family: var(--font-title); font-size: 9px; line-height: 1.5; text-transform: uppercase; color: var(--text-muted); margin-bottom: 4px; }
.room-podium-pts { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--text-strong); }
.room-board-list { display: flex; flex-direction: column; gap: 6px; }
.room-board .panel-header { flex-wrap: wrap; }
.room-board-row {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  background: var(--surface-1);
  box-shadow: var(--block), inset 0 0 0 4px var(--hairline);
  font-size: var(--fs-md);
}
.room-board-row.me { box-shadow: inset 0 0 0 3px var(--accent); background: var(--surface-2); }
.room-board-rank { font-family: var(--font-mono); font-size: var(--fm-sm); font-weight: 700; color: var(--text-dim); }
.room-board-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-strong); }
.room-board-pts { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--accent); }
.room-board-empty { margin: 0; padding: 18px 12px; font-size: var(--fs-md); text-align: center; color: var(--text-dim); background: var(--surface-1) var(--hatch); box-shadow: var(--block); }
.room-board-you { font-size: var(--fs-sm); color: var(--text-muted); }
/* Réponse validée : la saisie est figée. */
.room-stage.locked .room-slider,
.room-stage.locked .room-price-field { opacity: .6; }
.room-breakdown { font-size: var(--fs-sm); color: var(--text-muted); }
.room-podium-time { flex-shrink: 0; font-family: var(--font-mono); font-size: var(--fm-md); color: var(--text-dim); }

/* --- Bandeau de déploiement --- */
.deploy-banner {
  position: fixed;
  top: max(12px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 1100;
  max-width: min(560px, calc(100vw - 24px));
  padding: 10px 16px;
  background: var(--surface-2);
  box-shadow: inset 0 0 0 3px var(--accent), var(--shadow-sm);
  color: var(--text-strong);
  font-size: var(--fs-md);
  line-height: 1.2;
  text-align: center;
  pointer-events: none;
}

/* --- Échanges --- */
.trade-friend-select { align-self: flex-start; min-width: 240px; max-width: 100%; }
.trade-compose {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
.trade-col { display: flex; flex-direction: column; gap: 10px; align-items: stretch; min-width: 0; }
.trade-col > .btn { align-self: flex-start; }
.trade-col-title { font-family: var(--font-title); font-size: 9px; line-height: 1.4; text-transform: uppercase; color: var(--text-muted); }
/* Carré de 32px entre « tu donnes » et « tu reçois ». */
.trade-arrows {
  align-self: center;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  box-shadow: var(--block);
  color: var(--accent);
  font-size: 14px;
}
.trade-arrows i { display: flex; }
.trade-empty { font-size: var(--fs-md); color: var(--text-dim); padding: 6px 2px; }
/* Pièces dans un échange : champ du formulaire, ligne dans les cartes. */
.trade-coins { display: inline-flex; align-items: center; gap: 8px; align-self: flex-start; padding: 4px 10px; background: var(--surface-2); box-shadow: var(--block); color: var(--accent); }
.trade-coins .fi { display: flex; font-size: 13px; }
.trade-coins input { width: 90px; background: none; border: 0; outline: none; color: var(--text-strong); font-family: var(--font-mono); font-size: var(--fm-lg); font-weight: 700; }
.trade-coins span { font-size: var(--fs-sm); color: var(--text-muted); }
.trade-coins:focus-within { box-shadow: inset 0 0 0 3px var(--accent); }
.trade-coins-line { display: flex; align-items: center; gap: 8px; padding: 4px 2px; font-family: var(--font-mono); font-size: var(--fm-lg); font-weight: 700; color: var(--accent); }
.trade-coins-line .fi { display: flex; font-size: 13px; }
/* Bandeau « Contre-proposition à X ». */
.trade-counter-banner { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 10px 14px; background: var(--surface-2); box-shadow: inset 6px 0 0 0 var(--accent), var(--block); font-size: var(--fs-md); color: var(--text-strong); }
.trade-counter-banner .btn { margin-left: auto; }
.trade-picker-list { max-height: 320px; overflow-y: auto; }
.trade-picker-list .row { cursor: pointer; }
.trade-picker-list .row.selected {
  background: var(--surface-3);
  box-shadow: inset 0 0 0 3px var(--accent);
}
.trade-list { display: flex; flex-direction: column; gap: 12px; }
.trade-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.trade-card-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.trade-card-head .row-avatar { flex: none; }
.trade-card-who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.trade-card-meta { font-size: var(--fs-xs); color: var(--text-dim); }
/* Badge d'état : contour et texte de la couleur de l'état. */
.trade-card-status {
  font-family: var(--font-title);
  font-size: 8px;
  line-height: 1;
  text-transform: uppercase;
  padding: 5px 8px;
  background: var(--bg);
  color: var(--text-muted);
  box-shadow: inset 0 0 0 3px currentColor;
}
.trade-card-status.accepted { color: var(--success); }
.trade-card-status.declined, .trade-card-status.cancelled { color: var(--danger); }
.trade-card-status.countered { color: var(--accent); }
.trade-card-body { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 12px; align-items: start; }
.trade-card-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.trade-game { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 10px; background: var(--surface-1); box-shadow: var(--block), inset 0 0 0 4px var(--hairline); }
.trade-game .row-thumb { flex: none; }
.trade-game .rarity-badge { flex: none; }
.trade-game-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: var(--fs-md); }
.trade-game-remove { flex: none; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; border: 0; background: var(--surface-2); box-shadow: var(--block); color: var(--text-muted); cursor: pointer; font-size: 14px; padding: 0; }
.trade-game-remove:hover { background: var(--danger); color: var(--text-strong); }
@media (max-width: 700px) {
  .trade-compose, .trade-card-body { grid-template-columns: 1fr; }
  .trade-arrows { transform: rotate(90deg); justify-self: center; align-self: center; }
}

/* --- Liens légaux (barre latérale et page de connexion) --- */
.legal-links {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 12px;
  margin: 0;
  font-size: var(--fs-xs);
}
.legal-links a { color: var(--text-dim); text-decoration: none; }
.legal-links a:hover { color: var(--text-strong); }
.legal-links-login { margin-top: 18px; justify-content: center; }

/* --- Page légale autonome (legal.html) --- */
.legal-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 16px 80px;
}
.legal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding-bottom: 20px;
  border-bottom: 3px solid var(--hairline);
}
.legal-wordmark { text-decoration: none; }
.legal-header-actions { display: flex; gap: 10px; align-items: center; }
/* Sommaire en blocs carrés. */
.legal-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 22px 0;
}
.legal-toc a { padding: 5px 10px; color: var(--accent); text-decoration: none; font-size: var(--fs-md); background: var(--surface-2); box-shadow: var(--block), var(--shadow-sm); }
.legal-toc a:hover { background: var(--accent); color: var(--ink); }
.legal-updated { font-family: var(--font-mono); font-size: var(--fm-sm); color: var(--text-dim); margin: 0 0 8px; }
.legal-section {
  padding-top: 26px;
  margin-top: 26px;
  border-top: 3px solid var(--hairline);
  /* L'ancre ne doit pas coller au bord haut de la fenêtre. */
  scroll-margin-top: 16px;
}
.legal-section h1 { font-family: var(--font-title); font-size: 13px; font-weight: 400; line-height: 1.5; margin: 0 0 16px; color: var(--text-strong); text-shadow: 0 3px 0 var(--outline); }
.legal-section h2 { font-family: var(--font-title); font-size: 11px; font-weight: 400; line-height: 1.5; margin: 24px 0 10px; color: var(--text-strong); }
.legal-section p, .legal-section li { font-size: 21px; line-height: 1.5; color: var(--text); }
.legal-section p { margin: 0 0 10px; }
.legal-section ul { margin: 0 0 12px; padding-left: 20px; list-style: square; }
.legal-section li::marker { color: var(--accent); }
.legal-section li { margin-bottom: 6px; }
.legal-section strong { color: var(--text-strong); }
.legal-section a { color: var(--accent); }
.legal-note {
  padding: 10px 14px;
  background: var(--surface-1);
  box-shadow: var(--block);
}

/* --- Case d'acceptation à l'inscription --- */
.auth-consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--fs-sm);
  line-height: 1.2;
  color: var(--text-muted);
  cursor: pointer;
}
.auth-consent input { margin-top: 3px; flex: none; }
.auth-consent a { color: var(--accent); }

/* Pied de page légal du contenu : affiché seulement sous 760px, où les liens
   de la barre latérale sont masqués (voir la media query plus haut). */
.content-legal {
  display: none;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.content-legal .legal-links { justify-content: center; }
/* Doit rester après la règle de base ci-dessus : à spécificité égale, la
   dernière l'emporte. Placée plus haut dans le fichier, elle était écrasée et
   les liens légaux n'apparaissaient alors nulle part sur mobile. */
@media (max-width: 760px) {
  .content-legal { display: block; }
}

/* --- Abonnement VIP (modale et Paramètres) --- */
.vip-test-banner {
  margin: 0;
  padding: 8px 12px;
  font-size: var(--fs-md);
  line-height: 1.2;
  background: var(--bg);
  color: var(--accent);
  box-shadow: inset 0 0 0 3px var(--accent);
}
.vip-sub-state { margin: 0; font-size: var(--fs-md); color: var(--text); }
/* Libellés longs (« Redirection vers le paiement sécurisé… », prix + période) :
   ce bouton passe à la ligne au lieu de déborder de la fenêtre. */
#vipSubscribeBtn { white-space: normal; height: auto; padding-top: 12px; padding-bottom: 12px; }
#vipManageBtn { align-self: center; }

/* Page Admin : liste et formulaire des annonces. */
.admin-announce-row .row-title { white-space: normal; }
.admin-announce-live { color: var(--success); }
.admin-announce-form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; padding: 14px; background: var(--surface-2); box-shadow: var(--block); }
.admin-announce-field { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--text-muted); }
.admin-announce-field textarea,
.admin-announce-field input {
  width: 100%;
  padding: 8px 10px;
  background: var(--surface-1);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
}
.admin-announce-field textarea:focus,
.admin-announce-field input:focus { border-color: var(--accent); outline: none; }
.admin-announce-form-actions { display: flex; gap: 8px; }

/* Bandeaux d'annonce, en haut du contenu (voir announcements.ts). */
.announcements:not(:empty) { display: flex; flex-direction: column; gap: 10px; }

.promo-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-bottom: 18px;
  padding: 12px 14px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), inset 6px 0 0 0 var(--accent), var(--shadow-md);
  padding-left: 20px;
}
.promo-banner-text { flex: 1 1 260px; min-width: 0; font-size: var(--fs-md); color: var(--text-strong); }
.promo-banner-close {
  flex: none;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  background: var(--surface-2);
  box-shadow: var(--block);
  color: var(--text-muted);
  font-size: 14px;
  cursor: pointer;
}
.promo-banner-close:hover { background: var(--surface-3); color: var(--text-strong); }

/* --- Nouveautés (changelog) --- */
.changelog-list { display: flex; flex-direction: column; gap: 14px; }
.changelog-entry {
  padding: 18px 20px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
/* Pas encore lue : liseré gauche jaune. */
.changelog-entry.unread { box-shadow: var(--block-panel), inset 6px 0 0 0 var(--accent), var(--shadow-md); padding-left: 26px; }
/* Carte d'une journée, repliable : la date, puis (repliée) les titres des
   sorties et le nombre de lignes. */
.changelog-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; list-style: none; cursor: pointer; }
.changelog-head::-webkit-details-marker { display: none; }
.changelog-entry[open] > .changelog-head { margin-bottom: 16px; }
.changelog-head h2 { margin: 0; font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.changelog-head:hover h2 { color: var(--text-strong); }
.changelog-titles { flex: 1 1 200px; min-width: 0; font-size: var(--fs-md); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.changelog-entry[open] .changelog-titles { display: none; }
.changelog-count { margin-left: auto; font-family: var(--font-mono); font-size: var(--fm-xs); color: var(--text-dim); }
/* Téléphone : date, nombre et flèche sur une ligne, titres des sorties dessous. */
@media (max-width: 760px) {
  .changelog-titles { order: 5; flex-basis: 100%; white-space: normal; }
}
.changelog-chevron { display: flex; font-size: 16px; color: var(--text-dim); transition: transform .15s steps(2); }
.changelog-entry[open] .changelog-chevron { transform: rotate(90deg); }
/* Une rubrique par groupe de lignes (Caisses, Mini-jeux…). */
.changelog-body { column-width: 340px; column-gap: 40px; }
.changelog-group { break-inside: avoid; margin-bottom: 18px; }
.changelog-group:last-child { margin-bottom: 0; }
.changelog-group h3 { margin: 0 0 10px; font-family: var(--font-title); font-size: 10px; font-weight: 400; line-height: 1.5; color: var(--accent); }
.changelog-new { color: var(--success); }
.changelog-entry ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
/* Puce : carré jaune de 6px. */
.changelog-entry li { position: relative; padding-left: 18px; font-size: var(--fs-md); line-height: 1.2; color: var(--text); }
.changelog-entry li::before { content: ''; position: absolute; left: 2px; top: .4em; width: 6px; height: 6px; background: var(--accent); }

/* --- Caisses disponibles et chrono de la suivante, dans le menu (ordinateur) ---
   Badge mono « 3 · 6:16 » : jaune sur la barre, encre sur l'entrée active
   (elle-même jaune). */
.nav-case-timer {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 5px;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  text-transform: none;
  background: var(--accent);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--outline);
}
.side-nav-item.active .nav-case-timer { background: var(--ink); color: var(--accent); box-shadow: none; }
.nav-case-dot { opacity: .6; }
.nav-case-timer.full .nav-case-time { font-family: var(--font-ui); font-size: 15px; font-weight: 400; line-height: 1; }

/* --- Fiche d'un autre joueur, ouverte au clic sur son pseudo ou son avatar --- */
.player-link { cursor: pointer; }
.player-link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in oklab, currentColor 45%, transparent);
}
.player-link:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.player-link-avatar { cursor: pointer; }
.player-link-avatar:hover { box-shadow: 0 0 0 3px var(--accent); }

.modal-card.player-profile-card { max-width: 720px; max-height: 88vh; overflow-y: auto; gap: 18px; }
.player-profile-header { padding-right: 48px; }
.player-profile-card .profile-stats { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.player-profile-card .stat-tile-value { font-size: 20px; }
.player-profile-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.player-profile-actions:empty { display: none; }
.player-friend-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  font-family: var(--font-title);
  font-size: 8px;
  line-height: 1;
  text-transform: uppercase;
  background: var(--bg);
  color: var(--success);
  box-shadow: inset 0 0 0 3px var(--success);
}
.player-friend-chip i { display: inline-flex; }
/* Lecture seule : ni curseur de main, ni agrandissement au survol. */
.profile-slot.readonly { cursor: default; }
.profile-slot.readonly:hover { transform: none; }
.profile-slots.is-empty { display: block; }
.profile-slots.is-empty .history-empty { padding: 4px 0 0; }
@media (max-width: 760px) {
  .modal-card.player-profile-card { padding: 18px; }
  .player-profile-header { gap: 14px; }
  .player-profile-header .profile-avatar { width: 64px; height: 64px; }
  .player-profile-card .profile-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .player-profile-card .stat-tile { padding: 12px; }
}

/* En-tête mobile (Glitchcraft) : marque, monnaie, avatar, VIP et déconnexion
   tiennent sur 375px. Placé en fin de fichier pour passer après les règles
   de base des mêmes boîtes. */
@media (max-width: 760px) {
  .sidebar { gap: 8px; padding: 10px 12px; }
  .sidebar-footer { gap: 8px; }
  .sidebar-wordmark span:last-child { font-size: 20px; }
  /* Carte joueur réduite : avatar + pièces (le pseudo reste pour les lecteurs d'écran). */
  .sidebar-player { gap: 8px; padding: 8px 9px 8px 8px; box-shadow: var(--block); }
  .sidebar-player .user-avatar { width: 22px; height: 22px; border-width: 2px; font-size: 8px; }
  .sidebar-player .vip-frame { box-shadow: 0 0 0 2px var(--accent); }
  .vip-nav-btn { padding: 7px 8px; }
}

/* Idée corrigée par son auteur, réponse de l'équipe, et éditeur dans la carte. */
.suggestion-edited { margin-left: 8px; font-size: var(--fs-sm); color: var(--text-dim); }
.suggestion-reply {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  box-shadow: inset 4px 0 0 0 var(--accent);
}
.suggestion-reply p { margin: 4px 0 0; font-size: var(--fs-md); color: var(--text); }
.suggestion-reply-label { font-family: var(--font-mono); font-size: var(--fm-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.suggestion-editor { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.suggestion-editor textarea {
  width: 100%;
  resize: vertical;
  min-height: 64px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
}
.suggestion-editor textarea:focus { border-color: var(--accent); outline: none; }
.suggestion-editor-actions { display: flex; gap: 8px; }

/* Page Suggestions : formulaire, puis idées avec vote à gauche. */
.suggestion-form { display: flex; flex-direction: column; gap: 10px; }
.suggestion-form textarea {
  width: 100%;
  resize: vertical;
  min-height: 72px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
}
.suggestion-form textarea:focus { border-color: var(--accent); outline: none; }
.suggestion-form textarea::placeholder { color: var(--text-disabled); }
.suggestion-form-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.suggestion-form-foot .settings-desc { flex: 1 1 240px; }
.suggestion-counter { font-family: var(--font-mono); font-size: var(--fm-sm); color: var(--text-dim); }
.suggestion-toolbar { margin-top: 18px; }
.suggestion-list { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.suggestion-card {
  display: flex;
  gap: 14px;
  padding: 14px 16px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-md);
}
.suggestion-card.suggestion-done, .suggestion-card.suggestion-rejected { opacity: .78; }
.suggestion-vote {
  flex: 0 0 52px;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 0 8px;
  background: var(--surface-2);
  border: 0;
  box-shadow: inset 0 0 0 3px var(--outline);
  color: var(--text-muted);
  cursor: pointer;
}
.suggestion-vote .fi { font-size: 18px; line-height: 1; }
.suggestion-vote-count { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--text-strong); }
.suggestion-vote:hover:not(:disabled) { box-shadow: inset 0 0 0 3px var(--accent); color: var(--accent); }
.suggestion-vote.voted { background: var(--accent); box-shadow: inset 0 0 0 3px var(--accent); color: var(--ink); }
.suggestion-vote.voted .suggestion-vote-count { color: var(--ink); }
.suggestion-vote:disabled { cursor: default; }
.suggestion-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.suggestion-text { margin: 0; font-size: var(--fs-lg); line-height: 1.2; color: var(--text-strong); overflow-wrap: anywhere; }
.suggestion-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; font-size: var(--fs-sm); color: var(--text-dim); }
.row-avatar.suggestion-avatar { width: 24px; height: 24px; border-width: 2px; font-size: 8px; }
.suggestion-author { color: var(--text-muted); }
.suggestion-meta time { font-family: var(--font-mono); font-size: var(--fm-sm); }
.suggestion-status {
  padding: 2px 8px;
  font-family: var(--font-mono);
  font-size: var(--fm-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  box-shadow: inset 0 0 0 2px currentColor;
}
.suggestion-status-open { color: var(--text-muted); }
.suggestion-status-planned { color: var(--accent); }
.suggestion-status-done { color: var(--success); }
.suggestion-status-rejected { color: var(--danger); }
.suggestion-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.suggestion-status-select { font-size: var(--fs-sm); padding-top: 3px; padding-bottom: 3px; }

/* Page Classement : rang, avatar, pseudo, jeux possédés et % du catalogue. */
.leaderboard-scope { margin-left: auto; }
.leaderboard-list { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.leaderboard-rank {
  min-width: 40px;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: var(--fm-md);
  font-weight: 700;
  color: var(--text-dim);
}
.leaderboard-podium-1 .leaderboard-rank { color: var(--accent); }
.leaderboard-podium-2 .leaderboard-rank, .leaderboard-podium-3 .leaderboard-rank { color: var(--text-strong); }
.leaderboard-score { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.leaderboard-owned { font-family: var(--font-mono); font-size: var(--fm-md); font-weight: 700; color: var(--text-strong); }
.leaderboard-pct { font-family: var(--font-mono); font-size: var(--fm-xs); color: var(--text-dim); }
.leaderboard-gap { text-align: center; color: var(--text-dim); font-family: var(--font-mono); letter-spacing: .3em; }
.leaderboard-hint { margin: 10px 0 0; font-size: var(--fs-md); color: var(--text-dim); }
/* Mobile : la ligne reste sur une rangée (pas de retour à la ligne de .row). */
@media (max-width: 700px) {
  .row.leaderboard-row { flex-wrap: nowrap; gap: 10px; }
  .row.leaderboard-row .row-main { flex-basis: auto; }
  .leaderboard-rank { min-width: 32px; }
}

/* Salle : manche Quiz, la question puis quatre réponses en 2 × 2. */
.room-quiz-question {
  margin: 0;
  font-size: var(--fs-xl);
  line-height: 1.15;
  color: var(--text-strong);
  text-align: center;
}
.room-quiz-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; width: 100%; }
.room-quiz-choice {
  min-height: 56px;
  padding: 10px 14px;
  background: var(--surface-2);
  border: 0;
  box-shadow: inset 0 0 0 3px var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-lg);
  line-height: 1.1;
  text-align: center;
  cursor: pointer;
}
div.room-quiz-choice { display: flex; align-items: center; justify-content: center; cursor: default; }
button.room-quiz-choice:hover:not(:disabled) { box-shadow: inset 0 0 0 3px var(--accent); }
.room-quiz-choice.selected { background: var(--accent); color: var(--ink); box-shadow: inset 0 0 0 3px var(--accent); }
.room-quiz-choice:disabled { cursor: default; }
.room-quiz-choice.correct { box-shadow: inset 0 0 0 3px var(--success); color: var(--success); }
.room-quiz-choice.yours:not(.correct) { box-shadow: inset 0 0 0 3px var(--danger); color: var(--danger); }
@media (max-width: 560px) {
  .room-quiz-choices { grid-template-columns: 1fr; }
}

/* Salle : Pixel Guessr. Le PNG minuscule du serveur est agrandi sans
   lissage (une case = un gros pixel), au format des jaquettes Steam. */
/* Même taille et même format que la carte des autres manches. */
.room-pixel {
  display: block;
  width: min(300px, 100%);
  aspect-ratio: 920 / 430;
  image-rendering: pixelated;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 3px var(--outline);
}
.room-pixel-answer { width: 100%; }
.room-pixel-field { position: relative; width: 100%; }
.room-pixel-input {
  width: 100%;
  padding: 8px 12px;
  background: var(--surface-2);
  border: 3px solid var(--outline);
  color: var(--text-strong);
  font-family: var(--font-ui);
  font-size: var(--fs-lg);
}
.room-pixel-input:focus { border-color: var(--accent); outline: none; }
.room-pixel-suggest {
  position: absolute;
  z-index: 5;
  left: 0;
  right: 0;
  top: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface-1);
  box-shadow: inset 0 0 0 3px var(--outline), var(--shadow-md);
  max-height: 260px;
  overflow-y: auto;
}
.room-pixel-option { padding: 7px 12px; font-size: var(--fs-md); color: var(--text); cursor: pointer; }
.room-pixel-option.active, .room-pixel-option:hover { background: var(--accent); color: var(--ink); }

/* Salle : Clicker. Une cible à la fois dans l'aire de jeu. */
.room-clicker {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--surface-2) var(--hatch);
  box-shadow: inset 0 0 0 3px var(--outline);
  touch-action: manipulation;
  user-select: none;
}
.room-clicker-target {
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  padding: 0;
  border: 0;
  background: var(--accent);
  box-shadow: inset 0 0 0 4px var(--ink), inset 0 0 0 10px var(--accent), inset 0 0 0 14px var(--ink);
  cursor: crosshair;
}
.room-clicker-target:active { background: var(--success); }
.room-clicker-bomb {
  background: var(--danger);
  box-shadow: inset 0 0 0 4px var(--ink), inset 0 0 0 10px var(--danger), inset 0 0 0 14px var(--ink);
  cursor: crosshair;
}
.room-clicker-hurt { color: var(--danger); }
.room-clicker-count { font-family: var(--font-mono); font-size: var(--fm-xl); font-weight: 700; color: var(--accent); text-align: center; }

/* Échanges : recherche et tri côte à côte dans le choix des jeux. */
.trade-picker-toolbar { flex-wrap: nowrap; }
.trade-picker-toolbar .album-search { flex: 1 1 auto; min-width: 0; }
.trade-picker-toolbar .album-select { flex: none; }
@media (max-width: 480px) { .trade-picker-toolbar { flex-wrap: wrap; } }

/* Notifications : cloche à droite du titre du jeu, compteur jaune, menu
   déroulant (une ligne par évènement, les nouvelles surlignées). */
.sidebar-brand { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.notif-bell-wrap { position: relative; flex: none; }
.notif-bell {
  position: relative;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: var(--surface-2);
  box-shadow: var(--block);
  color: var(--text-muted);
  cursor: pointer;
}
.notif-bell .fi { display: flex; font-size: 15px; line-height: 1; }
.notif-bell:hover, .notif-bell[aria-expanded="true"] { color: var(--text-strong); background: var(--surface-3); }
.notif-bell.has-unread { color: var(--accent); }
.notif-bell-count {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--ink);
  box-shadow: 0 0 0 2px var(--outline);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
}
/* Fixe : la barre latérale coupe ce qui dépasse. Placé sous la cloche à
   l'ouverture (notifications.ts). */
.notif-menu {
  position: fixed;
  z-index: 60;
  top: 60px;
  left: 16px;
  width: 340px;
  max-height: min(460px, 70vh);
  display: flex;
  flex-direction: column;
  /* Contenu dans le cadre (4 px, ombre intérieure dessinée sous le contenu) :
     sans ça, les notifications défilaient sous la bordure et la barre de
     défilement longeait le bord. */
  padding: 4px;
  background: var(--surface-1);
  box-shadow: var(--block-panel), var(--shadow-lg);
}
.notif-menu-head { padding: 8px 10px 8px; }
.notif-menu-list { display: flex; flex-direction: column; gap: 4px; padding: 0 4px 4px; overflow-y: auto; }
.notif-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 10px;
  background: var(--surface-1);
  box-shadow: inset 0 0 0 2px var(--hairline);
  color: var(--text);
  text-decoration: none;
}
a.notif-row:hover { background: var(--surface-2); }
.notif-row.unread { box-shadow: inset 4px 0 0 0 var(--accent); background: var(--surface-2); color: var(--text-strong); }
.notif-icon { flex: none; font-size: 14px; line-height: 1.3; color: var(--accent); display: flex; padding-top: 2px; }
.notif-text { flex: 1 1 auto; min-width: 0; font-size: var(--fs-sm); line-height: 1.15; overflow-wrap: anywhere; }
.notif-time { flex: none; font-family: var(--font-mono); font-size: var(--fm-xs); color: var(--text-dim); padding-top: 3px; }
.notif-empty { margin: 0; padding: 6px 6px 10px; font-size: var(--fs-sm); color: var(--text-dim); }
/* Téléphone : le menu occupe la largeur de l'écran, sous l'en-tête. */
@media (max-width: 760px) {
  .sidebar-brand { flex: none; }
  .notif-bell { width: 28px; height: 28px; }
  .notif-menu { position: fixed; top: 62px; left: 8px; right: 8px; width: auto; }
}
