/* Mini-Jeux — identité « Cartoon Pop ». Rondeurs, aplats vifs, contours sticker,
   ressorts. Pas de webfont (offline first) : pile system arrondie + graisses. */

:root {
  --bg: #1a1140;
  --bg2: #2a1a5e;
  --ink: #241a3a;               /* contour sticker, = INK de mascots.js */
  --panel: #2d2170;
  --panel-2: #3a2c8f;
  --text: #fff7ff;
  --muted: #b9a8ff;
  --pop-pink: #ff5470;
  --pop-blue: #2d9cff;
  --pop-green: #3ddc84;
  --pop-yellow: #ffc93c;
  --pop-purple: #a05cff;
  /* Rouge d'ALERTE, distinct du rose décoratif. --pop-pink est trop clair pour porter
     du texte blanc : 3,11:1, sous le seuil lisible de 4,5:1 — or c'est justement le
     message qu'un joueur DOIT pouvoir lire. Celui-ci monte à 5,66:1 en restant un rouge
     franc, qui dit le blocage avant même qu'on ait lu. */
  --pop-red: #c9184a;
  /* Rose ÉCLAIRCI, pour du TEXTE rose posé sur un panneau sombre (boutons « retirer »,
     « supprimer »). --pop-pink n'y atteint que 4,32:1, et ce sont précisément les gestes
     destructeurs qu'il faut lire sans effort. Celui-ci donne 5,99:1 sur --panel et
     4,84:1 sur --panel-2, en restant le même rose à l'œil.
     ⚠️ Pour du TEXTE seulement : les aplats et les bordures gardent --pop-pink, plus franc. */
  --pop-pink-lt: #ff8a9c;
  /* Violet légèrement éclairci, pour les APLATS QUI PORTENT DU TEXTE. Sur le violet
     d'origine, l'encre sombre ne donne que 4,26:1 — juste sous le seuil. Celui-ci monte
     à 5,08:1 et reste le même violet à l'œil. Les aplats sans texte gardent --pop-purple. */
  --pop-purple-lt: #ac70ff;
  --p1: var(--pop-pink);
  --p2: var(--pop-blue);
  --p3: var(--pop-green);
  --p4: var(--pop-yellow);
  --radius: 26px;
  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --font: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  color: var(--text);
  font-family: var(--font);
  background: var(--bg);
}

body {
  position: fixed;
  inset: 0;
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.screen { position: absolute; inset: 0; }
.screen[hidden] { display: none !important; } /* [hidden] doit battre display:flex */
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; }
.flip { transform: rotate(180deg); }

/* ---------- Décor de fond animé (menu / lobby / profils) ---------- */
.decor { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }
.decor .blob {
  position: absolute;
  border-radius: 45% 55% 52% 48%;
  filter: blur(2px);
  opacity: 0.5;
  /* Perf : promu en calque compositeur → le flou est rastérisé UNE fois et l'animation
     (translate/rotate seulement, plus de scale) est faite par le GPU, sans re-flouter à
     chaque frame. Sinon = jank continu sur toutes les pages (home, mon compte…). */
  will-change: transform;
  animation: float 9s var(--spring) infinite alternate;
}
@keyframes float {
  from { transform: translateY(0) rotate(0deg); }
  to { transform: translateY(-26px) rotate(18deg); }
}

/* ---------- Menu ---------- */
#menu {
  z-index: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: max(env(safe-area-inset-top), 20px) 15px calc(env(safe-area-inset-bottom) + 30px);
}

.hero { position: relative; text-align: center; padding: 6px 0 14px; }
.hero-mascots { display: flex; justify-content: center; align-items: flex-end; gap: 0; margin-bottom: -6px; }
.hero-mascots .mascot-view { margin: 0 -6px; filter: drop-shadow(0 6px 0 rgba(0, 0, 0, 0.18)); }
.hero h1 {
  margin: 4px 0 0;
  font-size: clamp(34px, 11vw, 54px);
  font-weight: 900;
  letter-spacing: -1.5px;
  line-height: 0.95;
  background: linear-gradient(180deg, #fff, #ffd6f2 55%, var(--pop-yellow));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 3px 0 rgba(36, 26, 58, 0.35);
  filter: drop-shadow(0 4px 0 var(--ink));
  transform: rotate(-2deg);
}
.hero p { margin: 12px 0 0; color: var(--muted); font-weight: 700; font-size: 15px; }

.menu-actions { display: flex; justify-content: center; gap: 10px; margin: 16px 0 22px; }
.chip-btn {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--panel); border: 3px solid var(--ink);
  border-radius: 999px; padding: 10px 18px; font-weight: 800; font-size: 15px;
  box-shadow: 0 4px 0 var(--ink);
  transition: transform .12s var(--spring), box-shadow .12s;
}
/* ⚠️ SANS CETTE LIGNE, le bouton reste VISIBLE malgré l'attribut `hidden` : un `display`
   posé par l'auteur bat toujours `hidden`, qui ne vaut que par la feuille du navigateur.
   refreshInstall() faisait donc bien son travail sans que rien ne bouge, et la puce
   « Installer l'appli » s'affichait même DANS l'appli déjà installée — où elle ne fait
   rien. Le piège a déjà mordu plusieurs fois sur ce projet. */
.chip-btn[hidden] { display: none; }
.chip-btn:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }
.chip-btn .ico { width: 20px; height: 20px; display: inline-block; }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 15px;
  max-width: 640px;
  margin: 0 auto;
}
.card {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 20px 12px 15px;
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink);
  border-radius: var(--radius);
  box-shadow: 0 6px 0 var(--ink);
  text-align: center;
  transition: transform .14s var(--spring), box-shadow .14s;
  animation: cardIn .4s var(--spring) both;
  /* Perf : les cartes hors écran ne sont ni calculées ni peintes (taille réservée pour
     éviter tout saut de scroll). Allège le layout/paint initial de la grille des 42 jeux. */
  content-visibility: auto;
  contain-intrinsic-size: auto 132px;
}
.card:active { transform: translateY(6px) scale(.99); box-shadow: 0 0 0 var(--ink); }
.card-icon { width: 60px; height: 60px; transition: transform .3s var(--spring); }
.card:hover .card-icon { transform: rotate(-8deg) scale(1.08); }
.card-icon svg { width: 100%; height: 100%; overflow: visible; }
.card-name { font-size: 17px; font-weight: 900; letter-spacing: -.3px; }
.card-badge {
  font-size: 12px; font-weight: 800; color: var(--ink);
  background: var(--pop-yellow); border: 2px solid var(--ink);
  border-radius: 999px; padding: 2px 10px;
}
.card.soon { opacity: .5; }
.card.filtered-out { display: none !important; }
@keyframes cardIn { from { opacity: 0; transform: translateY(16px) scale(.9); } }

/* Filtre de la home — segmented control « sticker » Cartoon Pop */
.menu-filter { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 16px; max-width: 640px; margin: 2px auto 18px; }
/* Boîte de recherche de jeux (live, sans rechargement) */
.menu-search { display: flex; align-items: center; gap: 8px; width: 100%; max-width: 420px; background: var(--panel); border: 3px solid var(--ink); border-radius: 16px; padding: 0 14px; box-shadow: 0 4px 0 var(--ink); }
.menu-search-ico { font-size: 17px; flex: 0 0 auto; opacity: .85; }
.menu-search-input { flex: 1; min-width: 0; background: none; border: 0; outline: none; color: var(--text); font: inherit; font-size: 16px; font-weight: 700; padding: 12px 0; }
.menu-search-input::placeholder { color: var(--muted); font-weight: 600; }
.menu-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; height: 16px; width: 16px; background: var(--muted); border-radius: 50%; -webkit-mask: no-repeat center/12px url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18" stroke="black" stroke-width="3" stroke-linecap="round"/></svg>'); cursor: pointer; }
.filter-group { display: flex; align-items: center; gap: 8px; }
.filter-label { font-size: 11px; font-weight: 900; color: var(--muted); text-transform: uppercase; letter-spacing: .7px; white-space: nowrap; }
.filter-chips { display: inline-flex; gap: 4px; padding: 4px; background: var(--panel); border: 3px solid var(--ink); border-radius: 999px; box-shadow: 0 4px 0 var(--ink); }
.filter-chip {
  font: inherit; font-size: 13px; font-weight: 800; color: var(--text);
  background: transparent; border: none; border-radius: 999px;
  padding: 7px 14px; cursor: pointer; line-height: 1; white-space: nowrap;
  transition: transform .12s var(--spring), background .18s, color .18s;
}
.filter-chip:hover:not(.on) { background: var(--panel-2); }
.filter-chip:active { transform: scale(.88); }
.filter-chip.on { background: var(--pop-yellow); color: var(--ink); box-shadow: inset 0 -2px 0 rgba(36, 26, 58, .25); }
.menu-empty { text-align: center; color: var(--muted); font-weight: 800; margin: 24px auto; }

/* ---------- Lobby ---------- */
#lobby { z-index: 1; display: flex; flex-direction: column; overflow-y: auto; padding: max(env(safe-area-inset-top), 14px) 15px calc(env(safe-area-inset-bottom) + 104px); }
/* ⚠️ #lobby et #profiles sont des conteneurs FLEX EN COLONNE qui défilent. Sans
   flex-shrink:0, le moteur ÉCRASE les enfants pour les faire tenir dans la hauteur au
   lieu de laisser le contenu déborder : l'écran paraît tassé ET plus rien ne défile.
   Ne pas retirer — c'est ce qui rend le défilement possible quand ça ne tient pas. */
#lobby > *, #profiles > * { flex-shrink: 0; }
.back {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 999px;
  padding: 8px 16px; font-weight: 800; box-shadow: 0 3px 0 var(--ink);
}
.back:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.lobby-body { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; margin-top: 8px; }
.lobby-icon { width: 74px; height: 74px; }
.lobby-icon svg { width: 100%; height: 100%; overflow: visible; }
.lobby-body h2 { margin: 4px 0 0; font-size: 28px; font-weight: 900; letter-spacing: -.5px; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }
.lobby-desc { margin: 4px 0 0; color: var(--muted); max-width: 340px; line-height: 1.4; font-weight: 600; font-size: 14px; }

.section-title { margin: 20px 0 10px; font-weight: 800; font-size: 13px; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); text-align: center; }

.count-row { display: flex; justify-content: center; gap: 12px; }
.count-btn {
  width: 62px; height: 62px; border-radius: 50%;
  border: 3px solid var(--ink); background: var(--panel);
  font-size: 26px; font-weight: 900; box-shadow: 0 4px 0 var(--ink);
  transition: transform .12s var(--spring), box-shadow .12s, background .12s;
}
.count-btn.on { background: var(--pop-purple); }
.count-btn:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }

/* Slots joueurs */
.slots { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.slot {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 22px;
  padding: 10px 8px 8px; width: 96px; box-shadow: 0 4px 0 var(--ink);
  transition: transform .12s var(--spring);
}
.slot:active { transform: translateY(3px); }
.slot .mascot-view { pointer-events: none; }
.slot-name { font-weight: 800; font-size: 14px; max-width: 84px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slot-tag { font-size: 11px; color: var(--muted); font-weight: 700; }

/* Chips de réglage */
.chips { display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; }
.opt {
  border: 3px solid var(--ink); background: var(--panel); border-radius: 999px;
  padding: 9px 18px; font-weight: 800; font-size: 15px; box-shadow: 0 3px 0 var(--ink);
  transition: transform .1s var(--spring), background .1s, box-shadow .1s;
}
.opt.on { background: var(--pop-green); color: var(--ink); }
.opt:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }

.play-btn {
  margin: 26px auto 0; display: block; min-width: 220px;
  background: linear-gradient(180deg, var(--pop-yellow), #ff9e2c);
  color: var(--ink); border: 4px solid var(--ink); border-radius: 22px;
  padding: 18px 40px; font-size: 24px; font-weight: 900; letter-spacing: .5px;
  box-shadow: 0 7px 0 var(--ink);
  animation: wiggle 2.4s ease-in-out infinite;
}
.play-btn:active { transform: translateY(7px); box-shadow: 0 0 0 var(--ink); animation: none; }
@keyframes wiggle { 0%, 100% { transform: rotate(-1.5deg); } 50% { transform: rotate(1.5deg); } }

/* ---------- Profils (écran de gestion + feuilles) ---------- */
#profiles { z-index: 1; display: flex; flex-direction: column; overflow-y: auto; padding: max(env(safe-area-inset-top), 14px) 15px calc(env(safe-area-inset-bottom) + 20px); }
/* Personnages et Boutique partagent EXACTEMENT la même grille. ⚠️ width:100% est
   indispensable : #profiles est un conteneur flex en colonne, et des marges auto sur
   l'axe transversal y annulent le « stretch » — la grille se dimensionnait alors à son
   contenu et sortait plus étroite que celle de la boutique, à CSS pourtant identique. */
.prof-grid, .shop-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; width: 100%; max-width: 640px; margin-inline: auto; }
.prof-grid { margin-top: 12px; }
.prof-card { display: flex; flex-direction: column; align-items: center; gap: 6px; background: linear-gradient(165deg, var(--panel-2), var(--panel)); border: 3px solid var(--ink); border-radius: var(--radius); padding: 16px 12px 12px; box-shadow: 0 5px 0 var(--ink); }
.prof-card.add { justify-content: center; min-height: 150px; color: var(--muted); font-weight: 800; }
.prof-card .big-plus { font-size: 48px; line-height: 1; }
/* Mobile : « Les joueurs » = EXACTEMENT 2 par ligne (minmax(0,1fr) → jamais de 3e colonne
   qui déborde / scroll horizontal). auto-fill tentait une 3e colonne sur les grands écrans. */
@media (max-width: 620px) {
  .prof-grid, .shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .prof-card, .shop-item { min-width: 0; }

  /* 4 joueurs sur téléphone : 4 cartes de 96 px + 3 gouttières = 420 px, soit plus large
     qu'un écran de 360-390 px → la 4e passait à la ligne. Les cartes se partagent donc la
     largeur disponible. La mascotte est un <canvas> dont core/mascots.js fixe la taille en
     style INLINE : seul !important peut la laisser suivre son conteneur. */
  .slots[data-n="4"] { flex-wrap: nowrap; gap: 6px; }
  .slots[data-n="4"] .slot { width: auto; flex: 1 1 0; min-width: 0; gap: 2px; padding: 8px 3px 6px; border-radius: 18px; }
  .slots[data-n="4"] .slot .mascot-view { width: 100% !important; height: auto !important; aspect-ratio: 1; }
  .slots[data-n="4"] .slot-name { font-size: 11px; max-width: 100%; }
  .slots[data-n="4"] .slot-tag { font-size: 10px; }

  /* LOBBY COMPACT : sur téléphone, l'écran de réglages doit tenir d'un seul coup d'œil,
     sans défilement — on y choisit avant de jouer, on ne le lit pas. Chaque bloc est
     resserré plutôt que supprimé : rien ne disparaît, tout rapetisse. */
  /* ⚠️ NE PAS réduire sous la hauteur de #tabbar (fixe, z-index 12) : le bas du lobby
     passerait DESSOUS. Le bouton JOUER y disparaissait, et le pouce qui voulait faire
     défiler tombait sur la barre au lieu du contenu — d'où « je ne peux plus scroller ».
     La compaction se fait sur le CONTENU (pictos, tailles, molettes), jamais sur cette
     réserve. */
  /* ⚠️ Le padding-bas d'un conteneur FLEX qui défile n'est PAS compté dans la zone
     défilable : mesuré, il n'ajoutait rien (scrollHeight = clientHeight alors que le
     bouton JOUER finissait 38 px SOUS la barre d'onglets). On réserve donc la place par
     une MARGE sur le dernier élément — une marge, elle, compte. C'était la vraie cause du
     « je ne peux plus scroller » : on atteignait le bas sans jamais dégager le bouton. */
  #lobby { padding-bottom: calc(env(safe-area-inset-bottom) + 16px); }
  #lobby .play-btn { margin-bottom: calc(env(safe-area-inset-bottom) + 88px); }
  .lobby-icon { width: 52px; height: 52px; }
  .lobby-body { gap: 2px; margin-top: 4px; }
  .lobby-body h2 { font-size: 21px; gap: 6px; }
  .lobby-desc { font-size: 12.5px; margin-top: 2px; line-height: 1.3; }
  #lobby .section-title { margin: 10px 0 6px; }
  .count-btn { width: 52px; height: 52px; font-size: 22px; }
  .count-row { gap: 9px; }
  #lobby .seg button { padding: 7px 13px; font-size: 13px; }
  /* Les deux molettes côte à côte (et non l'une sous l'autre) : ~70 px de hauteur gagnés,
     tout en restant centrées. Elles rapetissent pour tenir à deux sur 360 px de large. */
  .gopts-row { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 4px 0 0; }
  .gopt { font-size: 11.5px; gap: 4px; }
  .stepper { gap: 4px; padding: 4px; }
  .step-btn { width: 34px; height: 34px; font-size: 21px; }
  .step-val { width: 52px; font-size: 22px; }
  .play-btn { margin-top: 14px; padding: 14px 34px; font-size: 21px; min-width: 190px; }
}

/* Feuille modale (bottom sheet)
   ⚠️ z-index 45, DONC AU-DESSUS de .chat-screen (40). À 30, toute feuille ouverte depuis
   la conversation — le catalogue d'emojis du « + » des réactions, par exemple — se
   dessinait DERRIÈRE l'écran de chat : elle semblait disparaître aussitôt ouverte.
   Reste sous la révélation de cadeau (9999) et la pub (9998), qui doivent tout couvrir. */
.sheet-veil { position: absolute; inset: 0; z-index: 45; background: rgba(12, 8, 30, .72); display: flex; align-items: flex-end; justify-content: center; animation: fade .2s; }
.sheet {
  width: 100%; max-width: 520px; max-height: 88%; overflow-y: auto;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 4px solid var(--ink); border-bottom: 0;
  border-radius: 30px 30px 0 0; padding: 18px 18px calc(env(safe-area-inset-bottom) + 24px);
  box-shadow: 0 -8px 0 rgba(36, 26, 58, .4);
  animation: sheetUp .3s var(--spring);
}
.sheet h3 { margin: 4px 0 14px; text-align: center; font-size: 20px; font-weight: 900; }
.prof-editor-name { text-align: center; font-size: 22px; font-weight: 900; letter-spacing: -.3px; color: var(--text); margin: 2px 0 6px; }

/* Poignée : grande zone tactile (pour glisser-fermer), barre visible centrée via ::before */
.sheet-grip { width: 72px; height: 22px; margin: -4px auto 6px; display: grid; place-items: center; touch-action: none; cursor: grab; }
.sheet-grip::before { content: ''; width: 46px; height: 5px; border-radius: 3px; background: var(--muted); opacity: .5; }
.sheet-grip:active { cursor: grabbing; }
.mascot-picker, .profile-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 10px; }
.pick { display: flex; flex-direction: column; align-items: center; gap: 2px; background: var(--panel); border: 3px solid transparent; border-radius: 18px; padding: 6px; }
.pick.on { border-color: var(--pop-yellow); background: var(--panel-2); }
.pick-name { font-size: 11px; font-weight: 700; color: var(--muted); }
.color-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 14px 0; }
.swatch { width: 40px; height: 40px; border-radius: 50%; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); }
.swatch.on { outline: 3px solid #fff; outline-offset: 2px; }
/* Pastille blanche : l'anneau blanc s'y noierait → on le passe à l'encre. */
.swatch[data-light="1"].on { outline-color: var(--ink); }
.name-input {
  display: block; width: 100%; margin: 4px 0 14px; text-align: center;
  background: var(--bg); color: var(--text); border: 3px solid var(--ink);
  border-radius: 16px; padding: 12px; font-size: 18px; font-weight: 800; font-family: var(--font);
}
.name-input[hidden] { display: none !important; }   /* [hidden] doit battre display:block (pseudo en connexion) */
.sheet-actions { display: flex; gap: 10px; margin-top: 6px; }
.sheet-actions .btn { flex: 1; }
.link-danger { display: block; margin: 12px auto 0; color: #ff8fa3; font-weight: 800; text-align: center; }

/* ---------- Écran de jeu ---------- */
#play { z-index: 2; background: var(--bg); }
#game-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

.ov { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
.ov.center { display: flex; align-items: center; justify-content: center; }
.ov.col { flex-direction: column; gap: 18px; }
.ov.veil { background: rgba(16, 10, 40, .84); pointer-events: auto; }

.count-wrap { display: flex; flex-direction: column; align-items: center; gap: 9vh; }
.count span {
  display: block; font-size: clamp(66px, 19vmin, 156px); font-weight: 900;
  color: #fff; text-shadow: 0 5px 0 var(--ink), 0 8px 24px rgba(0, 0, 0, .5);
  animation: pop .42s var(--spring) both;
}

.pill {
  position: absolute; z-index: 4; transform: translate(-50%, -50%);
  background: #fff; color: var(--ink); border: 3px solid var(--ink);
  border-radius: 999px; min-width: 34px; text-align: center; padding: 2px 11px;
  font-size: 18px; font-weight: 900; pointer-events: none; box-shadow: 0 3px 0 var(--ink);
}
.pill.flip { transform: translate(-50%, -50%) rotate(180deg); }

.plus1 { position: absolute; z-index: 6; transform: translate(-50%, -50%); pointer-events: none; }
.plus1.flip { transform: translate(-50%, -50%) rotate(180deg); }
.plus1 span { display: block; font-size: 14vmin; font-weight: 900; text-shadow: 0 4px 0 var(--ink); animation: plus1 .85s var(--spring) both; }

/* Pack Fun — secousse d'écran, pop de combo, pièces gagnées */
@keyframes fxShakeA { 10%,90%{transform:translateX(-2px)} 20%,80%{transform:translateX(3px)} 30%,50%,70%{transform:translateX(-5px)} 40%,60%{transform:translateX(5px)} }
@keyframes fxShakeB { 15%{transform:translate(-4px,-3px)} 30%{transform:translate(6px,4px)} 45%{transform:translate(-9px,3px)} 60%{transform:translate(9px,-4px)} 80%{transform:translate(-4px,2px)} }
.fx-shake-a { animation: fxShakeA .38s cubic-bezier(.36,.07,.19,.97); }
.fx-shake-b { animation: fxShakeB .48s cubic-bezier(.36,.07,.19,.97); }
.combo-pop { position: absolute; z-index: 7; transform: translate(-50%, -50%); pointer-events: none; font-weight: 900; font-size: clamp(24px, 8vmin, 60px); color: var(--pop-yellow); -webkit-text-stroke: 3px var(--ink); paint-order: stroke; text-stroke: 3px var(--ink); animation: comboPop .92s var(--spring) forwards; }
@keyframes comboPop { 0%{opacity:0; transform:translate(-50%,-50%) scale(.3) rotate(-8deg)} 22%{opacity:1; transform:translate(-50%,-50%) scale(1.28) rotate(5deg)} 65%{opacity:1; transform:translate(-50%,-72%) scale(1) rotate(0)} 100%{opacity:0; transform:translate(-50%,-125%) scale(.9)} }
.end-coins { font-size: 27px; font-weight: 900; color: var(--pop-yellow); -webkit-text-stroke: 2px var(--ink); paint-order: stroke; margin-top: -4px; animation: coinPop .5s var(--spring) both; animation-delay: .4s; }
/* Étoile de victoire à l'écran de fin : MÊME idiome que la ligne de pièces (elle en hérite
   la classe), décalée d'un temps pour que les deux gains se lisent l'un après l'autre et non
   d'un bloc. L'icône est alignée sur la ligne de base du texte, sinon elle flotte. */
.end-stars { animation-delay: .72s; display: flex; align-items: center; justify-content: center; gap: 6px; }
.end-stars span { display: inline-flex; align-items: center; gap: 7px; }
.end-star-ico { width: 30px; height: 30px; flex: 0 0 auto; }
@keyframes coinPop { from{opacity:0; transform:scale(.4) translateY(12px)} to{opacity:1; transform:scale(1)} }
@media (prefers-reduced-motion: reduce) { .fx-shake-a, .fx-shake-b { animation: none; } }

.end-mascot { width: 44vmin; max-width: 220px; height: 44vmin; max-height: 220px; }
.end-mascot canvas { width: 100% !important; height: 100% !important; }
.end-msg { font-size: clamp(26px, 8vmin, 48px); font-weight: 900; text-align: center; text-shadow: 0 4px 0 var(--ink); }

.btn-row { display: flex; gap: 14px; margin-top: 8px; }
.btn {
  border: 3px solid var(--ink); border-radius: 16px; padding: 14px 26px;
  font-size: 17px; font-weight: 900; background: var(--panel); box-shadow: 0 5px 0 var(--ink);
  transition: transform .1s var(--spring), box-shadow .1s;
}
.btn:active { transform: translateY(5px); box-shadow: 0 0 0 var(--ink); }
.btn-primary { background: var(--pop-yellow); color: var(--ink); }

/* Dock de service EN JEU : les boutons pause et « ? » trônaient au milieu du bord droit,
   en plein dans l'aire de jeu. Ils sont repliés derrière une poignée discrète, dans le coin
   BAS — côté joueur 1, le seul dont l'interface n'est pas retournée. */
.ingame-dock {
  position: absolute; right: 6px; bottom: calc(env(safe-area-inset-bottom) + 8px); z-index: 8;
  display: flex; flex-direction: column-reverse; align-items: center; gap: 8px;
}
.dock-handle {
  width: 34px; height: 34px; display: grid; place-items: center;
  border: 2px solid var(--ink); border-radius: 50%;
  background: rgba(45, 33, 112, .5); color: #fff; font-size: 17px; font-weight: 900; line-height: 1;
  opacity: .5; cursor: pointer; transition: opacity .15s, transform .15s var(--spring);
}
.dock-handle:active { transform: scale(.9); }
.ingame-dock.open .dock-handle { opacity: 1; transform: rotate(90deg); }
/* Replié : les boutons sont invisibles ET insensibles au doigt (leur place reste
   réservée au-dessus de la poignée, mais elle est transparente et non cliquable).
   ⚠️ La règle vise TOUT enfant du dock sauf la poignée, au lieu d'énumérer les classes une
   par une. L'ancienne version listait `.pause-btn, .rules-ingame, .dock-sfx` : le jour où
   l'on a ajouté un quatrième bouton (« ↻ »), il est resté visible en permanence — la liste
   avait été oubliée à trois endroits. Un nouveau bouton est désormais replié d'office. */
.ingame-dock > :not(.dock-handle) {
  opacity: 0; pointer-events: none; transform: translateY(10px) scale(.7);
  transition: opacity .16s, transform .16s var(--spring);
}
.ingame-dock.open > :not(.dock-handle) { opacity: 1; pointer-events: auto; transform: none; }
.ingame-dock.open > :not(.dock-handle):active { transform: scale(.92); }
.dock-sfx {
  width: 40px; height: 40px; display: grid; place-items: center;
  border: 3px solid var(--ink); border-radius: 12px; background: var(--panel-2);
  box-shadow: 0 3px 0 var(--ink); font-size: 19px; line-height: 1; cursor: pointer;
}

/* Bouton de coupure du son — fixe, présent sur tous les écrans sauf la partie.
   Posé À GAUCHE : la colonne de droite est déjà prise par la roue (boutique) et la
   bulle de conversation, toutes deux à la même hauteur. */
.sfx-fab {
  position: fixed; inset-inline-start: 12px; bottom: calc(env(safe-area-inset-bottom) + 78px);
  z-index: 27; width: 46px; height: 46px; padding: 0; display: grid; place-items: center;
  background: var(--panel-2); border: 3px solid var(--ink); border-radius: 50%;
  box-shadow: 0 4px 0 var(--ink); font-size: 21px; line-height: 1; cursor: pointer; opacity: .94;
  transition: transform .1s var(--spring), box-shadow .1s;
}
.sfx-fab[hidden] { display: none !important; }   /* ⚠️ display:grid battrait [hidden] */
.sfx-fab:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.sfx-fab.is-muted { opacity: .72; }

.pause-btn {
  width: 40px; height: 44px; border: 3px solid var(--ink); border-radius: 12px;
  background: rgba(45, 33, 112, .85); color: #fff; font-size: 14px; letter-spacing: -2px; cursor: pointer;
}

/* chrono de partie : une pastille par orientation, bord gauche autour du centre */
.timer {
  position: absolute; left: 8px; z-index: 4; top: calc(50% + 8px);
  background: #fff; color: var(--ink); border: 3px solid var(--ink);
  border-radius: 999px; padding: 3px 10px; font-size: 15px; font-weight: 900;
  font-variant-numeric: tabular-nums; pointer-events: none; box-shadow: 0 3px 0 var(--ink);
}
.timer.flip { top: auto; bottom: calc(50% + 8px); }
.timer.urgent {
  background: var(--pop-pink); color: var(--ink);
  animation: urgentPulse .5s ease-in-out infinite alternate;
}
@keyframes urgentPulse { from { transform: scale(1); } to { transform: scale(1.12); } }

.confetti { position: absolute; inset: 0; z-index: 20; overflow: hidden; pointer-events: none; }
.confetti i { position: absolute; top: -12px; width: 11px; height: 15px; border-radius: 2px; animation: fall linear forwards; }

/* ---------- Bottom bar ---------- */

#tabbar {
  /* fixed + fond OPAQUE sans backdrop-filter : un backdrop-filter se recalcule à
     chaque frame de scroll (le contenu défile derrière) → barre qui vibre/bouge
     sur mobile. Fond plein = calque stable, la barre ne repeint plus au scroll. */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 12;
  display: flex; justify-content: space-around; align-items: stretch;
  background: #1b1246;
  border-top: 3px solid var(--ink);
  padding: 8px 12px calc(env(safe-area-inset-bottom) + 8px);
}
#tabbar[hidden] { display: none !important; }
#tabbar .tab {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  min-width: 92px; padding: 4px 12px; border-radius: 16px;
  color: var(--muted); font-size: 11px; font-weight: 800;
}
#tabbar .tab .ico-w { width: 30px; height: 30px; display: block; opacity: 0.55; filter: saturate(0.4); transition: transform 0.2s var(--spring); }
#tabbar .tab .ico-w svg { width: 100%; height: 100%; }
#tabbar .tab.on { color: #fff; }
#tabbar .tab.on .ico-w { opacity: 1; filter: none; animation: tabPop 0.3s var(--spring); }
#tabbar .tab:active .ico-w { transform: scale(0.85); }
@keyframes tabPop { 0% { transform: scale(0.7); } 100% { transform: scale(1); } }

/* place pour la barre sur les écrans qui la montrent */
#menu, #profiles, #account { padding-bottom: calc(env(safe-area-inset-bottom) + 104px); }

/* ---------- Écran Mon compte ---------- */

#account { z-index: 1; overflow-y: auto; padding-top: max(env(safe-area-inset-top), 26px); padding-left: 15px; padding-right: 15px; }
.acct-hero { text-align: center; }
.acct-body {
  max-width: 380px; margin: 0 auto; padding: 0 22px;
  display: flex; flex-direction: column; align-items: stretch; gap: 12px; text-align: center;
}
.acct-body h2 { margin: 2px 0 0; font-size: 28px; font-weight: 900; letter-spacing: -0.5px; }
.acct-bigemo { font-size: 64px; line-height: 1; }
.acct-mail {
  align-self: center; background: var(--panel); border: 3px solid var(--ink);
  border-radius: 999px; padding: 8px 18px; font-weight: 800; box-shadow: 0 3px 0 var(--ink);
}
.seg {
  display: flex; align-self: center; background: var(--panel);
  border: 3px solid var(--ink); border-radius: 999px; padding: 4px; gap: 4px;
  box-shadow: 0 3px 0 var(--ink);
}
.seg button { border-radius: 999px; padding: 9px 16px; font-weight: 800; font-size: 14px; color: var(--muted); }
.seg button.on { background: var(--pop-purple-lt); color: var(--ink); }
.form-err {
  background: rgba(255, 84, 112, 0.16); border: 2px solid var(--pop-pink);
  color: #ffb3c2; border-radius: 14px; padding: 10px 14px; font-weight: 700; font-size: 14px;
}
.play-btn-small { min-width: 0; margin: 4px auto 0; padding: 15px 30px; font-size: 19px; animation: none; }
.acct-privacy { color: var(--muted); font-size: 12px; font-weight: 600; line-height: 1.45; margin: 6px 0 0; }
/* Pied de page légal (Mon compte) : discret, centré, sous les cartes. */
.acct-legal { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin: 18px auto 4px; max-width: 640px; }
.acct-legal a { color: var(--muted); font-size: 12px; font-weight: 700; text-decoration: none; }
.acct-legal a:active { color: var(--text); }
.acct-legal-sep { color: var(--muted); opacity: .5; font-size: 12px; }

/* ---------- Boutique cosmétique ---------- */
#shop { z-index: 1; overflow-y: auto; padding: max(env(safe-area-inset-top), 20px) 15px calc(env(safe-area-inset-bottom) + 104px); }
.shop-head { display: flex; align-items: center; justify-content: space-between; max-width: 640px; margin: 0 auto; }
/* ⚠️ RÈGLE : tout ce qui montre la pièce 🪙 (dorée) doit avoir un fond NOIR/SOMBRE,
   jamais jaune — sinon la pièce se fond dans le fond. Fond noir par défaut ici. */
.coin-pill {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--ink); color: #fff; border: 3px solid var(--ink);
  border-radius: 999px; padding: 3px 12px; font-weight: 900; font-size: 15px;
  box-shadow: 0 3px 0 rgba(36, 26, 58, .35);
}
.coin-balance .coin-pill { font-size: 18px; padding: 5px 15px; }
.shop-earn { text-align: center; margin: 6px auto 0; }

/* Salon d'un jeu que cette version ne sait pas encore afficher. Dire honnêtement « pas
   encore » vaut mieux qu'un écran à moitié dessiné dont on ne sait pas s'il est cassé. */
.net-unsupported { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 18px; text-align: center; }
.net-uns-emo { font-size: 46px; line-height: 1; }
.net-uns-t { margin: 0; font-size: 17px; font-weight: 900; }
.net-uns-s { margin: 0; font-size: 13.5px; font-weight: 700; line-height: 1.5; color: var(--muted); }
.net-uns-out { margin-top: 6px; }

/* ---------- Changement d'adresse e-mail (page dédiée) ---------- */
#email {
  z-index: 1; overflow-y: auto;
  padding: max(env(safe-area-inset-top), 20px) 15px calc(env(safe-area-inset-bottom) + 104px);
}
.mail-wrap { max-width: 460px; margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
.mail-back { align-self: flex-start; }
.mail-cur { margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--muted); text-align: center; word-break: break-all; }
.mail-cur b { color: var(--text); }
.mail-step { display: flex; flex-direction: column; gap: 9px; }
.mail-step[hidden] { display: none; }
.mail-lab { font-size: 11.5px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 4px 0 -4px 3px; }
.mail-in { width: 100%; margin: 0; }
/* Le code : gros, espacé, chiffres alignés. On le recopie d'un autre écran, il doit se lire
   sans effort et se vérifier d'un coup d'œil. */
.mail-code { text-align: center; font-size: 28px; font-weight: 900; letter-spacing: 10px; font-variant-numeric: tabular-nums; }
.mail-hint { margin: 2px 0 4px; font-size: 12.5px; font-weight: 700; line-height: 1.45; color: var(--muted); }
.mail-sent { margin: 0 0 4px; padding: 11px 13px; font-size: 13px; font-weight: 800; line-height: 1.45;
             color: var(--ink); background: var(--pop-green); border: 3px solid var(--ink); border-radius: 14px; word-break: break-all; }
.mail-err { margin: 4px 0 0; padding: 10px 13px; font-size: 13px; font-weight: 800; line-height: 1.4;
            color: var(--ink); background: var(--pop-pink); border: 3px solid var(--ink); border-radius: 14px; }
.mail-err[hidden] { display: none; }
.mail-ask { display: flex; flex-direction: column; gap: 14px; margin-top: 6px; }
.mail-ask p { margin: 0; font-size: 15.5px; font-weight: 800; line-height: 1.45; text-align: center; }
.mail-ask-sub { font-size: 12.5px !important; font-weight: 700 !important; color: var(--muted); }
/* Étape franchie : un accusé vert, pour qu'on sache que la vérification a bien pris. */
.mail-okstep { margin: 0 0 4px; padding: 10px 13px; font-size: 13.5px; font-weight: 800; line-height: 1.4;
               color: var(--ink); background: var(--pop-green); border: 3px solid var(--ink); border-radius: 14px; }
.mail-ask-row { display: flex; gap: 10px; }
.mail-ask-row .btn { flex: 1; }
/* L'adresse devient un bouton : soulignée en pointillés, c'est le signe le plus discret qui
   dise « ceci se touche » sans transformer la ligne en gros bouton. */
.acct-mail-btn { cursor: pointer; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
.acct-mail-btn:active { color: var(--text); }

/* ---------- Fenêtre d'AVERTISSEMENT de modération ----------
   Volontairement sobre et sévère : ni confettis, ni couleur de fête. Elle annonce une
   sanction, et le ton doit le dire avant qu'on ait lu. */
.warn-box { display: flex; flex-direction: column; align-items: center; gap: 12px; margin-top: 6px; text-align: center; }
.warn-emo { font-size: 54px; line-height: 1; }
.warn-head { margin: 0; font-size: 18px; font-weight: 900; color: var(--pop-pink); }
.warn-why {
  width: 100%; padding: 11px 13px; text-align: start;
  background: rgba(255, 84, 112, .14); border: 3px solid var(--pop-pink); border-radius: 14px;
}
.warn-why span { display: block; font-size: 11px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--pop-pink); }
.warn-why b { display: block; margin-top: 3px; font-size: 15px; font-weight: 900; line-height: 1.35; word-break: break-word; }
.warn-body { margin: 0; font-size: 13.5px; font-weight: 700; line-height: 1.5; color: var(--muted); }
/* L'ÉCHÉANCE. C'est la première chose qu'un joueur suspendu cherche : « jusqu'à quand ? ».
   Elle est donc traitée comme une information de premier plan, pas comme une note de bas de
   page — une punition sans terme connu se vit comme un bannissement. */
.warn-until {
  margin: 0; padding: 8px 16px; border-radius: 999px;
  background: var(--pop-yellow); color: var(--ink);
  border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink);
  font-size: 15px; font-weight: 900; text-align: center;
}
/* Le compte à rebours avant la fermeture de session : présent mais discret. Il explique ce
   qui va se passer sans faire paniquer — l'écran ne doit pas se refermer sans prévenir. */
.warn-count { margin: 0; font-size: 12.5px; font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }
.warn-ok { width: 100%; margin-top: 4px; }

/* ---------- Fenetre de SIGNALEMENT d'un message ----------
   L'avertissement est en TETE et il est visuellement fort : signaler quelqu'un a des
   consequences pour lui, et le joueur doit le lire avant d'ecrire, pas apres. */
.rep-box { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.rep-warn {
  margin: 0; padding: 12px 13px; font-size: 12.5px; font-weight: 700; line-height: 1.5;
  color: var(--text); background: rgba(255, 84, 112, .14);
  border: 3px solid var(--pop-pink); border-radius: 16px;
}
.rep-warn b { color: var(--pop-pink); }
/* Le message signale, cite tel qu'il s'affiche : sans lui l'admin recoit un motif sans
   objet, et les messages de salon disparaissent au bout de 6 h avec leur salon. */
.rep-quote {
  padding: 10px 12px; background: var(--panel); border: 3px solid var(--ink);
  border-radius: 14px; border-inline-start-width: 7px;
}
.rep-qwho { font-size: 11.5px; font-weight: 900; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.rep-qtxt { margin: 4px 0 0; font-size: 14.5px; font-weight: 700; line-height: 1.4; word-break: break-word; }
.rep-lab { font-size: 11.5px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 5px 0 -3px 3px; }
.rep-in { width: 100%; margin: 0; }
.rep-ta {
  width: 100%; min-height: 92px; padding: 11px 13px; resize: vertical;
  font: inherit; font-size: 15px; font-weight: 700; line-height: 1.4;
  color: var(--text); background: var(--bg);
  border: 3px solid var(--ink); border-radius: 14px; outline: none;
}
.rep-ta:focus { border-color: var(--pop-purple); }
.rep-send { margin-top: 6px; }
.rep-send[disabled] { opacity: .55; }

/* ---------- Les deux BUREAUX DE CHANGE ----------
   ⚠️ Un nouvel écran DOIT déclarer son propre défilement ET sa réserve pour la barre
   d'onglets : `body` est en position fixed / overflow hidden, et `.screen` en absolute
   inset 0 — le seul conteneur qui défile est l'écran lui-même. C'est le piège qui avait
   rendu l'atelier impossible à faire défiler, et il ne se voit pas sur un écran assez haut. */
#starshop, #coinshop {
  z-index: 1; overflow-y: auto;
  padding: max(env(safe-area-inset-top), 20px) 15px calc(env(safe-area-inset-bottom) + 104px);
}
.exch-wrap { max-width: 640px; margin: 0 auto; }
.exch-back { margin-bottom: 10px; }
.exch-title { margin: 0 0 4px; }
.exch-sub { margin: 0 auto 14px; max-width: 460px; text-align: center; font-size: 13px; font-weight: 700; line-height: 1.45; color: var(--muted); }
.exch-bal { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 0 0 16px; font-weight: 800; color: var(--muted); }

.exch-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
@media (max-width: 420px) { .exch-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.exch-card {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 15px 10px 12px;
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: var(--radius); box-shadow: 0 5px 0 var(--ink);
  transition: transform .16s var(--spring), box-shadow .16s var(--spring);
}
@media (hover: hover) { .exch-card:hover { transform: translateY(-2px); box-shadow: 0 7px 0 var(--ink); } }
.exch-bonus {
  position: absolute; top: -9px; inset-inline-end: -5px;
  font-size: 11px; font-weight: 900; color: var(--ink); background: var(--pop-green);
  border: 3px solid var(--ink); border-radius: 999px; padding: 2px 9px; transform: rotate(6deg);
}
.exch-arw { font-size: 19px; font-weight: 900; color: var(--muted); line-height: 1; }
.exch-go {
  width: 100%; margin-top: 5px; padding: 9px 6px;
  font: inherit; font-size: 13.5px; font-weight: 900; line-height: 1.2;
  color: var(--ink); background: var(--pop-yellow);
  border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 3px 0 var(--ink); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis;
}
.exch-go:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.exch-won { animation: exchWon .55s var(--spring); }
@keyframes exchWon {
  0% { transform: scale(1); }
  35% { transform: scale(1.05); filter: brightness(1.3); }
  100% { transform: scale(1); }
}
.exch-note {
  max-width: 640px; margin: 18px auto 0; padding: 11px 13px;
  background: var(--panel); border: 3px dashed var(--ink); border-radius: 16px;
  font-size: 12px; font-weight: 700; line-height: 1.45; color: var(--muted); text-align: center;
}
@media (prefers-reduced-motion: reduce) { .exch-won { animation: none; } }

/* ---------- Encadré de RÈGLES du chat (replié par défaut) ----------
   Le panneau « Attention » reste visible en permanence pour qu'on sache qu'il y a quelque
   chose à lire ; le texte, lui, est replié — un pavé de règles en tête de chaque
   conversation se fait ignorer dès la deuxième fois. */
.chat-rules { flex: 0 0 auto; margin: 10px 14px 4px; }
.chat-rules summary {
  display: flex; align-items: center; gap: 8px; cursor: pointer; list-style: none;
  padding: 9px 12px; font-size: 12.5px; font-weight: 900;
  color: var(--pop-yellow); background: rgba(255, 201, 60, .12);
  border: 3px solid var(--pop-yellow); border-radius: 14px;
}
.chat-rules summary::-webkit-details-marker { display: none; }
.chat-rules .cr-chev { margin-inline-start: auto; font-size: 15px; transition: transform .18s var(--spring); }
.chat-rules[open] .cr-chev { transform: rotate(180deg); }
.chat-rules p {
  margin: 8px 0 0; padding: 11px 13px; font-size: 12.5px; font-weight: 700; line-height: 1.5;
  color: var(--muted); background: var(--panel); border: 3px solid var(--ink); border-radius: 14px;
}
.chat-rules p b { color: var(--text); }
@media (prefers-reduced-motion: reduce) { .chat-rules .cr-chev { transition: none; } }

/* ---------- Publicites RECOMPENSEES : la barre a deux moities ----------
   Deux moities STRICTEMENT egales (flex: 1 1 0 + width: 0), pour qu'aucune des deux
   recompenses n'ait l'air d'etre la principale. Meme habillage sticker que le reste :
   contour 3 px encre, ombre pleine, ecrasement a l'appui. */
.rw-bar { display: flex; gap: 10px; align-items: stretch; }
.rw-half {
  flex: 1 1 0; width: 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 12px 8px 10px; cursor: pointer; font: inherit; color: var(--text);
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 5px 0 var(--ink);
  transition: transform .16s var(--spring), box-shadow .16s var(--spring), filter .16s var(--spring);
}
.rw-half:active:not([disabled]) { transform: translateY(5px); box-shadow: 0 0 0 var(--ink); }
@media (hover: hover) {
  .rw-half:hover:not([disabled]) { transform: translateY(-2px); box-shadow: 0 7px 0 var(--ink); filter: brightness(1.08); }
}
.rw-half[disabled] { opacity: .55; cursor: default; }
.rw-ico { font-size: 27px; line-height: 1; display: inline-flex; }
.rw-ico-svg { width: 28px; height: 28px; display: block; }
.rw-gain { font-size: 21px; font-weight: 900; line-height: 1.05; color: var(--pop-yellow); -webkit-text-stroke: 2px var(--ink); paint-order: stroke; }
.rw-cur { font-size: 10.5px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.rw-go {
  margin-top: 6px; padding: 6px 13px; max-width: 100%;
  font-size: 12.5px; font-weight: 900; color: var(--ink); background: var(--pop-green);
  border: 3px solid var(--ink); border-radius: 999px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rw-half[disabled] .rw-go { background: var(--panel-2); color: var(--muted); }
/* Recompense obtenue : une pulsation courte, le temps qu'on la voie sans la subir. */
.rw-won { animation: rwWon .6s var(--spring); }
@keyframes rwWon {
  0% { transform: scale(1); }
  35% { transform: scale(1.06); filter: brightness(1.3); }
  100% { transform: scale(1); }
}

/* ---------- Le faux spot publicitaire (fournisseur « test ») ----------
   ⚠️ AUCUNE sortie autre que le bouton, et seulement une fois le decompte fini : ni voile
   cliquable, ni Echap. Sinon on recupererait la recompense sans regarder, ce qui rendrait
   la barre absurde le jour ou de vraies pubs la remplaceront. */
.ad-veil { position: fixed; inset: 0; z-index: 300; display: grid; place-items: center; padding: 20px; background: rgba(10, 6, 30, .9); }
.ad-box { width: 100%; max-width: 380px; padding: 18px; text-align: center; background: linear-gradient(165deg, var(--panel-2), var(--panel)); border: 4px solid var(--ink); border-radius: 24px; box-shadow: 0 8px 0 var(--ink); }
.ad-tag { display: inline-block; margin-bottom: 12px; padding: 4px 12px; font-size: 11px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; color: var(--ink); background: var(--pop-yellow); border: 3px solid var(--ink); border-radius: 999px; }
.ad-stage { height: 132px; display: grid; place-items: center; background: var(--bg); border: 3px solid var(--ink); border-radius: 18px; overflow: hidden; }
.ad-blob { width: 76px; height: 76px; border-radius: 42% 58% 55% 45% / 48% 42% 58% 52%; background: linear-gradient(140deg, var(--pop-pink), var(--pop-purple)); border: 3px solid var(--ink); animation: adBlob 2.4s ease-in-out infinite; }
@keyframes adBlob {
  0%, 100% { transform: rotate(0deg) scale(1); border-radius: 42% 58% 55% 45% / 48% 42% 58% 52%; }
  50% { transform: rotate(180deg) scale(1.12); border-radius: 58% 42% 45% 55% / 42% 58% 42% 58%; }
}
.ad-note { margin: 11px 0 13px; font-size: 12.5px; font-weight: 700; line-height: 1.45; color: var(--muted); }
/* ⚠️ Deux états, deux couleurs de TEXTE. En attente, le fond est violet foncé : l'encre
   sombre y tombait à 1,51:1, autrement dit le décompte « encore N s » était invisible —
   le bouton paraissait vide et cassé. --muted remonte à 5,22:1 tout en gardant l'aspect
   éteint d'un bouton qui n'est pas encore actionnable.
   Une fois PRÊT, le fond passe au vert vif et l'encre sombre reprend sa place (9,17:1). */
.ad-go { width: 100%; padding: 13px; font: inherit; font-size: 16px; font-weight: 900; color: var(--muted); background: var(--panel-2); border: 3px solid var(--ink); border-radius: 16px; box-shadow: 0 4px 0 var(--ink); cursor: default; }
.ad-go.ready { background: var(--pop-green); color: var(--ink); cursor: pointer; }
.ad-go.ready:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }
@media (prefers-reduced-motion: reduce) { .ad-blob { animation: none; } .rw-won { animation: none; } }

/* ---------- Monnaie « ÉTOILES » ⭐ ----------
   JUMEAU EXACT de .coin-pill : mêmes fond, contour, rayon, graisse, ombre et métriques.
   Deux compteurs voisins doivent se lire comme deux exemplaires du même objet — une
   première version, plus riche (libellé + bouton « + »), jurait à côté des pièces.
   Fond SOMBRE pour la même raison que la pièce : une icône dorée sur fond clair disparaît.
   L'icône est DESSINÉE (voir STAR_ICON dans core/ui.js) et non l'emoji ⭐, qui change de
   dessin d'un téléphone à l'autre — inacceptable pour l'icône d'une monnaie. */
.star-pill {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--ink); color: #fff; border: 3px solid var(--ink);
  border-radius: 999px; padding: 3px 12px; font-weight: 900; font-size: 15px;
  box-shadow: 0 3px 0 rgba(36, 26, 58, .35);
}
.star-pill-ico { width: 17px; height: 17px; flex: 0 0 auto; }
/* ---------- Les compteurs de solde sont des BOUTONS ----------
   Ils ouvrent les bureaux de change, et rien ne le disait : ni relief, ni curseur, ni
   mouvement. Ils reçoivent donc l'habillage complet d'un bouton de l'appli — contour épais,
   ombre pleine à l'encre, enfoncement à l'appui — plus une brillance qui balaie toutes les
   six secondes pour attirer l'œil sans clignoter.

   ⚠️ CANTONNÉ AUX CONTENEURS DE SOLDE. `.coin-pill` sert AUSSI aux étiquettes de prix de la
   boutique (pricePill) : les styler en bouton ferait croire que chaque prix est cliquable,
   et il y en a 165 à l'écran. Même règle que pour l'écouteur de clic. */
.coin-balance .coin-pill,
.star-balance .star-pill,
.acct-coins .coin-pill,
.acct-stars .star-pill {
  position: relative; overflow: hidden; cursor: pointer;
  /* Taille RÉDUITE (05/08) : la première version à 20 px mangeait l'en-tête. On garde tout
     ce qui dit « c'est un bouton » — relief, enfoncement, brillance — et on rend la place. */
  font-size: 16px; padding: 4px 13px;
  box-shadow: 0 3px 0 var(--ink);
  transition: transform .14s var(--spring), box-shadow .14s var(--spring);
}
.coin-balance .coin-pill:active,
.star-balance .star-pill:active,
.acct-coins .coin-pill:active,
.acct-stars .star-pill:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
@media (hover: hover) {
  .coin-balance .coin-pill:hover,
  .star-balance .star-pill:hover,
  .acct-coins .coin-pill:hover,
  .acct-stars .star-pill:hover { transform: translateY(-2px); box-shadow: 0 6px 0 var(--ink); }
}
/* Brillance : une passe rapide toutes les six secondes. Assez pour qu'on remarque, assez
   espacé pour qu'on ne s'en agace pas au bout d'une minute. */
.coin-balance .coin-pill::after,
.star-balance .star-pill::after,
.acct-coins .coin-pill::after,
.acct-stars .star-pill::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, .5) 50%, transparent 58%);
  transform: translateX(-130%);
  animation: pillShine 6s ease-in-out infinite;
}
@keyframes pillShine {
  0%, 76% { transform: translateX(-130%); }
  88%, 100% { transform: translateX(130%); }
}
.star-balance .star-pill-ico, .acct-stars .star-pill-ico { width: 18px; height: 18px; }

/* Info-bulle d'amorçage : montrée UNE SEULE FOIS, jamais rejouée après une mise à jour.
   Une astuce qui réapparaît à chaque version finit par se lire comme un bug. */
.wallet-hint {
  max-width: 640px; margin: 10px auto 0; padding: 10px 14px;
  display: flex; align-items: center; gap: 9px;
  font-size: 13px; font-weight: 800; line-height: 1.4; color: var(--ink);
  background: var(--pop-yellow); border: 3px solid var(--ink); border-radius: 16px;
  box-shadow: 0 4px 0 var(--ink);
  animation: hintIn .3s var(--spring);
}
.wallet-hint.gone { animation: hintOut .35s ease-in forwards; }
@keyframes hintIn { from { opacity: 0; transform: translateY(-8px); } }
@keyframes hintOut { to { opacity: 0; transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) {
  .coin-balance .coin-pill::after, .star-balance .star-pill::after,
  .acct-coins .coin-pill::after, .acct-stars .star-pill::after { animation: none; opacity: 0; }
  .wallet-hint, .wallet-hint.gone { animation: none; }
}

/* Scintillement de l'éclat : assez lent pour se remarquer sans clignoter. */
.star-spark { transform-origin: 16px 16px; animation: starSpark 3.2s ease-in-out infinite; }
@keyframes starSpark {
  0%, 62% { opacity: 0; transform: scale(.55) rotate(0deg); }
  72%     { opacity: .95; transform: scale(1) rotate(22deg); }
  86%     { opacity: 0; transform: scale(1.25) rotate(40deg); }
  100%    { opacity: 0; transform: scale(.55) rotate(0deg); }
}
/* Le solde SAUTE quand il change : seul retour visible du gain, le son étant muet par défaut. */
.star-pill.bump { animation: starBump .42s var(--spring); }
@keyframes starBump {
  0%   { transform: scale(1); }
  38%  { transform: scale(1.28); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .star-spark { animation: none; opacity: .9; }
  .star-pill.bump { animation: none; }
}
/* Les deux compteurs côte à côte, sans jamais déborder sur un petit écran. */
.wallets { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

/* ---------- Boutique : les DEUX ONGLETS (Boutique / Exclusif) ----------
   Encadrés, pour qu'on les lise comme des onglets et non comme deux boutons posés là :
   une gouttière à l'encre contient les deux, l'actif est jaune plein — la couleur que
   l'appli emploie déjà partout pour « sélectionné » (.opt.on, .lang-opt.on, .filter-chip.on).
   Deux moitiés strictement égales (flex: 1) : aucun des deux n'a l'air principal. */
.shop-tabs {
  display: flex; gap: 6px; max-width: 640px; margin: 14px auto 12px; padding: 5px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 18px;
  box-shadow: 0 4px 0 var(--ink);
}
.shop-tab {
  flex: 1 1 0; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-size: 15px; font-weight: 900; line-height: 1;
  color: var(--text); background: transparent;
  border: 3px solid transparent; border-radius: 13px; padding: 11px 8px; cursor: pointer;
  transition: background .16s var(--spring), color .16s var(--spring), transform .16s var(--spring);
}
.shop-tab-i { font-size: 17px; line-height: 1; }
.shop-tab.on {
  color: var(--ink); background: var(--pop-yellow); border-color: var(--ink);
  box-shadow: 0 3px 0 var(--ink);
}
.shop-tab:not(.on):active { background: var(--panel-2); transform: translateY(1px); }
@media (hover: hover) { .shop-tab:not(.on):hover { background: var(--panel-2); } }
/* Le volet caché ne doit RIEN peindre : `.shop-pane` n'est pas en display:flex, mais on pose
   la garde explicitement — c'est le piège documenté quatre fois dans ce fichier. */
.shop-pane[hidden] { display: none; }

/* ---------- Volet « Exclusif » ---------- */
.excl-note {
  max-width: 640px; margin: 0 auto 14px; padding: 11px 13px;
  background: var(--panel); border: 3px dashed var(--ink); border-radius: 16px;
  font-size: 12.5px; font-weight: 700; line-height: 1.45; color: var(--muted);
}
/* État vide : c'est l'état NORMAL de l'onglet tant qu'aucun exclusif n'est en ligne.
   Il est donc soigné — un onglet vide qui a l'air cassé fait douter de l'appli entière. */
.excl-empty {
  max-width: 640px; margin: 26px auto; padding: 26px 18px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: var(--radius); box-shadow: 0 6px 0 var(--ink);
  font-size: 14px; font-weight: 800; color: var(--muted); line-height: 1.5;
}
.excl-empty[hidden] { display: none; }
.excl-empty-i { font-size: 40px; line-height: 1; animation: starSpark 3.2s ease-in-out infinite; }
/* Compte à rebours d'un exclusif, en haut de sa vignette. */
.excl-item { position: relative; }
.excl-left {
  position: absolute; top: 6px; inset-inline-start: 6px; z-index: 2;
  font-size: 11px; font-weight: 900; color: var(--ink); background: var(--pop-yellow);
  border: 2px solid var(--ink); border-radius: 999px; padding: 2px 8px; white-space: nowrap;
}
.excl-left.excl-over { background: var(--panel-2); color: var(--muted); }
/* Prix en étoiles : même forme que la pastille de prix en pièces, autre monnaie.
   Fond sombre comme la pastille 🪙 — une icône dorée sur fond jaune disparaîtrait. */
.star-price { display: inline-flex; align-items: center; gap: 5px; }
.star-price-ico { width: 17px; height: 17px; flex: 0 0 auto; }
@media (prefers-reduced-motion: reduce) { .excl-empty-i { animation: none; } }

/* Outils admin de la boutique (tout acheter / tout revendre) — visibles des seuls admins.
   Encadré en pointillés pour qu'on voie tout de suite que ce n'est PAS l'étalage du joueur. */
.shop-admin { max-width: 640px; margin: 12px auto 0; padding: 10px; background: var(--panel); border: 2px dashed var(--ink); border-radius: 16px; }
.shop-admin-t { font-size: 12px; font-weight: 900; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 8px; }
.shop-admin-row { display: flex; gap: 8px; }
.sa-btn {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 9px 8px; font: inherit; font-size: 13px; font-weight: 900; line-height: 1.2;
  color: var(--text); background: var(--panel-2); border: 3px solid var(--ink);
  border-radius: 14px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; text-align: center;
}
.sa-btn small { font-size: 11px; font-weight: 700; color: var(--muted); }
.sa-btn:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.sa-btn[disabled] { opacity: .5; box-shadow: none; cursor: default; }
.sa-btn.broke { border-color: var(--pop-pink); }          /* solde insuffisant : signalé, pas bloqué */
.sa-btn.armed { background: var(--pop-pink); color: var(--ink); }
.sa-warn { margin: 8px 0 0; text-align: center; font-size: 12px; font-weight: 800; color: var(--pop-pink); }
.shop-flash {
  max-width: 380px; margin: 12px auto 0; text-align: center; font-weight: 800;
  background: rgba(61, 220, 132, .18); border: 3px solid var(--pop-green);
  border-radius: 16px; padding: 10px 14px; animation: pop .4s var(--spring);
}
/* Sélecteur de langue : bouton → menu avec recherche */
.lang-select { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 4px 0 var(--ink); padding: 12px 14px; font-weight: 900; font-size: 16px; cursor: pointer; }
.lang-select:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.lang-arw { color: var(--muted); }
.lang-picker { display: flex; flex-direction: column; gap: 10px; }
.lang-search { margin: 0; }
.lang-list { display: flex; flex-direction: column; gap: 6px; max-height: 56vh; overflow-y: auto; }
.lang-opt { display: flex; align-items: center; gap: 12px; background: var(--panel-2); border: 2px solid var(--ink); border-radius: 12px; padding: 11px 14px; font-weight: 800; font-size: 16px; color: var(--text); cursor: pointer; }
.lang-opt.on { background: var(--pop-yellow); color: var(--ink); }
.lang-flag { font-size: 22px; }
.lang-lbl { flex: 1; text-align: start; }
.lang-chk { font-weight: 900; }
/* Réglages de partie par jeu (inputs libres points + durée) + défauts du compte */
/* Réglages chiffrés : molettes « sticker » centrées, pensées pour le pouce. */
.gopts-row { display: flex; flex-direction: column; align-items: center; gap: 14px; margin: 10px 0 2px; }
.gopt { display: flex; flex-direction: column; align-items: center; gap: 7px; font-size: 13px; font-weight: 800; color: var(--muted); text-align: center; }
.stepper { display: flex; align-items: center; gap: 8px; padding: 5px; background: var(--panel-2); border: 3px solid var(--ink); border-radius: 999px; box-shadow: 0 4px 0 var(--ink); }
.step-btn {
  width: 42px; height: 42px; display: grid; place-items: center;
  border: 3px solid var(--ink); border-radius: 50%; background: var(--pop-yellow); color: var(--ink);
  font-size: 26px; font-weight: 900; line-height: 1; cursor: pointer;
  box-shadow: 0 3px 0 var(--ink); transition: transform .1s var(--spring), box-shadow .1s, opacity .1s;
}
.step-btn:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.step-btn:disabled { opacity: .3; cursor: default; }   /* butée atteinte : ça se voit */
.step-val {
  width: 84px; margin: 0; padding: 0; border: 0; background: none; color: var(--text);
  font-family: inherit; font-size: 27px; font-weight: 900; text-align: center;
  font-variant-numeric: tabular-nums;      /* les chiffres ne dansent pas d'une valeur à l'autre */
  appearance: textfield; -moz-appearance: textfield;
}
.step-val::-webkit-outer-spin-button, .step-val::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.step-val:focus { outline: none; }
.game-defaults { margin-top: 10px; }
/* Barre boutique : recherche (ajax) + tri + filtres */
.shop-toolbar { display: flex; gap: 8px; max-width: 640px; margin: 0 auto 10px; }
/* La recherche de la boutique réutilise le composant de la liste des jeux
   (.menu-search : loupe + champ dans une boîte sticker) — même objet, même geste. */
.shop-search { flex: 1; min-width: 0; max-width: none; }
.shop-search .menu-search-input { font-size: 15px; padding: 10px 0; }
.shop-sort { flex: 0 0 auto; display: flex; align-items: center; gap: 5px; font: inherit; font-weight: 800; font-size: 14px; color: var(--text); background: var(--panel-2); border: 3px solid var(--ink); border-radius: 14px; padding: 0 12px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; white-space: nowrap; }
.shop-sort:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.shop-sort-arw { color: var(--muted); font-size: 12px; }
.shop-filters { max-width: 640px; margin: 0 auto 14px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
/* 2e rangée = catégories : 5 puces, donc un cran plus compactes que la rangée du dessus,
   sinon elles occupent trois lignes sur un téléphone. Le libellé reste ÉCRIT. */
.shop-filters + .shop-cats { margin-top: -6px; }
.shop-cats .opt { font-size: 13px; padding: 7px 13px; }
.shop-empty { text-align: center; padding: 20px; }
/* 🎡 Roue de la fortune — bouton discret dans le coin de la boutique (légère pulsation) */
.wheel-fab { position: fixed; inset-inline-end: 12px; bottom: calc(78px + env(safe-area-inset-bottom)); z-index: 30; width: 54px; height: 54px; border-radius: 50%; border: 3px solid var(--ink); background: var(--panel-2); box-shadow: 0 4px 0 var(--ink); font-size: 26px; line-height: 1; display: grid; place-items: center; cursor: pointer; opacity: .9; animation: wheelPulse 2.6s ease-in-out infinite; }
.wheel-fab:active { transform: translateY(3px) !important; box-shadow: 0 1px 0 var(--ink); }
@keyframes wheelPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.09); } }
@media (prefers-reduced-motion: reduce) { .wheel-fab { animation: none; } }
.wheel-box { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.wheel-bal { font-weight: 900; font-size: 16px; }
.wheel-wrap { position: relative; width: 276px; height: 276px; display: grid; place-items: center; }
.wheel { position: relative; width: 256px; height: 256px; border-radius: 50%; border: 5px solid var(--ink); box-shadow: 0 5px 0 var(--ink); overflow: hidden; }
.wheel-pointer { position: absolute; top: -7px; left: 50%; transform: translateX(-50%); font-size: 28px; line-height: 1; color: var(--ink); z-index: 3; text-shadow: 0 0 2px #fff, 0 0 6px #fff, 0 2px 0 #fff; }
.wheel-hub { position: absolute; width: 44px; height: 44px; border-radius: 50%; background: var(--panel); border: 4px solid var(--ink); display: grid; place-items: center; font-size: 20px; z-index: 2; box-shadow: 0 2px 0 var(--ink); }
/* Cases posées DIRECTEMENT sur la roue (NON encadrées) ; le % en bas de la case */
.wslice { position: absolute; inset: 0; transform-origin: 50% 50%; pointer-events: none; }
.wslice-in { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 2px; }
.wslice-in .coin-pill { font-size: 17px; padding: 3px 11px; }   /* nombres de pièces plus GROS */
.wslice-pct { font-size: 11px; font-weight: 900; color: #fff; line-height: 1; font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px rgba(0, 0, 0, .9), 0 0 3px rgba(0, 0, 0, .75); }
/* Personnage « comme la fiche » : mascotte + rayons (sunburst) tournant derrière + halo */
.wslice-skin { position: relative; width: 46px; height: 46px; display: grid; place-items: center; --tint: #fff; font-size: 22px; }
.wslice-legend { --tint: #ffd24a; }   /* case 1 % légendaire : halo doré */
.wslice-skin .ms-rays { width: 50px; height: 50px; opacity: .5; }
.wslice-glow { position: absolute; width: 40px; height: 40px; border-radius: 50%; background: radial-gradient(circle, var(--tint), transparent 66%); opacity: .5; filter: blur(3px); }
.wslice-skin canvas { position: relative; z-index: 1; display: block; }

/* 🎁 Révélation d'un personnage offert (façon BrawlStars) */
.reveal-veil { position: fixed; inset: 0; z-index: 9999; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; cursor: pointer;
  background: radial-gradient(circle at 50% 42%, #2a1a5e 0%, #140b2e 60%, #0a0620 100%); animation: revealFade .28s ease-out both; overflow: hidden; padding: 20px; }
.reveal-stage { position: relative; width: 264px; height: 264px; display: grid; place-items: center; }
.reveal-stage .ms-rays { width: 460px; height: 460px; color: var(--tint); opacity: .5; animation: msSpin 12s linear infinite; }
.reveal-glow { position: absolute; width: 250px; height: 250px; border-radius: 50%; background: radial-gradient(circle, var(--tint), transparent 66%); opacity: .5; filter: blur(10px); animation: revealGlow 2.2s ease-in-out infinite; }
.reveal-flash { position: absolute; width: 220px; height: 220px; border-radius: 50%; background: radial-gradient(circle, #fff, rgba(255,255,255,.4) 40%, transparent 70%); opacity: 0; animation: revealFlash .6s ease-out .32s both; }
.reveal-mascot { position: relative; z-index: 2; animation: revealPop .6s cubic-bezier(.2,1.4,.5,1) .34s both; }
.reveal-mascot canvas { display: block; filter: drop-shadow(0 10px 18px rgba(0,0,0,.45)); }
.reveal-spark { position: absolute; z-index: 3; font-size: 22px; color: #fff; text-shadow: 0 0 8px var(--tint); opacity: 0; animation: revealTwinkle 1.6s ease-in-out infinite; }
.reveal-spark.s1 { top: 14%; left: 20%; animation-delay: .5s; }
.reveal-spark.s2 { top: 24%; right: 16%; animation-delay: .8s; font-size: 16px; }
.reveal-spark.s3 { bottom: 22%; left: 14%; animation-delay: 1.1s; font-size: 18px; }
.reveal-spark.s4 { bottom: 16%; right: 20%; animation-delay: .65s; }
.reveal-spark.s5 { top: 46%; left: 8%; animation-delay: 1.3s; font-size: 14px; }
.reveal-confetti { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; z-index: 4; }
.reveal-confetti i { position: absolute; width: 9px; height: 13px; border-radius: 2px; opacity: 0; animation: revealConfetti .95s ease-out .4s forwards; }
.reveal-tag { margin-top: 8px; font-size: 15px; font-weight: 900; letter-spacing: 2px; text-transform: uppercase; color: var(--ink); background: linear-gradient(180deg, #ffe07a, #ffc93c); border: 3px solid var(--ink); border-radius: 12px; box-shadow: 0 4px 0 var(--ink); padding: 6px 16px; animation: revealDrop .5s cubic-bezier(.2,1.5,.5,1) .7s both; }
.reveal-name { font-size: clamp(30px, 9vw, 44px); font-weight: 900; letter-spacing: -.5px; color: #fff; text-shadow: 0 3px 0 var(--ink), 0 0 22px var(--tint); animation: revealPopIn .5s cubic-bezier(.2,1.5,.5,1) .95s both; }
.reveal-from { font-size: 15px; font-weight: 700; color: var(--muted); animation: revealUp .5s ease-out 1.15s both; }
.reveal-ok { margin-top: 16px; background: var(--pop-green); color: var(--ink); border: 3px solid var(--ink); border-radius: 16px; padding: 13px 34px; font-weight: 900; font-size: 17px; box-shadow: 0 6px 0 var(--ink); cursor: pointer; animation: revealUp .5s ease-out 1.35s both; }
.reveal-ok:active { transform: translateY(6px); box-shadow: 0 0 0 var(--ink); }
@keyframes revealFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes revealGlow { 0%, 100% { opacity: .38; transform: scale(1); } 50% { opacity: .6; transform: scale(1.08); } }
@keyframes revealFlash { 0% { opacity: 0; transform: scale(.3); } 42% { opacity: .95; } 100% { opacity: 0; transform: scale(1.7); } }
@keyframes revealPop { 0% { transform: scale(0) rotate(-12deg); opacity: 0; } 55% { transform: scale(1.18) rotate(5deg); opacity: 1; } 72% { transform: scale(.93) rotate(-3deg); } 86% { transform: scale(1.05); } 100% { transform: scale(1) rotate(0); } }
@keyframes revealTwinkle { 0%, 100% { opacity: 0; transform: scale(.5); } 50% { opacity: 1; transform: scale(1.15); } }
@keyframes revealConfetti { 0% { opacity: 1; transform: translate(0, 0) rotate(0); } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--rot)); } }
@keyframes revealDrop { 0% { opacity: 0; transform: translateY(-30px) scale(.8); } 62% { opacity: 1; transform: translateY(5px) scale(1.06); } 100% { transform: translateY(0) scale(1); } }
@keyframes revealPopIn { 0% { opacity: 0; transform: scale(.6); } 72% { opacity: 1; transform: scale(1.1); } 100% { transform: scale(1); } }
@keyframes revealUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .reveal-stage .ms-rays, .reveal-glow, .reveal-spark { animation: none; } .reveal-mascot, .reveal-tag, .reveal-name, .reveal-from, .reveal-ok, .reveal-flash, .reveal-confetti i { animation-duration: .01s; } }
/* 🎁 Offrir un personnage (admin) : bouton dans la popup cadeau + grille de sélection */
.gift-skin-btn { align-self: stretch; margin-top: 8px; background: var(--pop-purple-lt); color: var(--ink); border: 3px solid var(--ink); border-radius: 14px; padding: 12px; font-weight: 900; font-size: 15px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; }
.gift-skin-btn:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }
.skin-gift-box { display: flex; flex-direction: column; gap: 10px; }
.skin-gift-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; max-height: 62vh; overflow-y: auto; padding: 2px; }
.skin-gift-card { display: flex; flex-direction: column; align-items: center; gap: 5px; background: linear-gradient(165deg, var(--panel-2), var(--panel)); border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 4px 0 var(--ink); padding: 10px 6px 8px; cursor: pointer; }
.skin-gift-card:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.sg-name { font-size: 12px; font-weight: 900; text-align: center; line-height: 1.1; }
.skin-gift-card .coin-pill { font-size: 12px; padding: 2px 8px; }
.skin-gift-card.owned { opacity: .9; cursor: default; border-color: var(--pop-green); }
.sg-has { font-size: 11px; font-weight: 900; color: var(--pop-green); }
.wheel-result { font-weight: 900; font-size: 17px; text-align: center; min-height: 24px; }
.wheel-spin { align-self: stretch; }
/* 🎬 Tour gratuit contre pub (récompensée) */
.wheel-adspin { align-self: stretch; margin-top: -4px; background: var(--pop-green); color: var(--ink); border: 3px solid var(--ink); border-radius: 14px; padding: 11px; font-weight: 900; font-size: 15px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; }
.wheel-adspin:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }
.wheel-adspin:disabled { opacity: .55; }
/* Overlay pub factice (test) — remplacé par AdMob rewarded plus tard */
.ad-veil { position: fixed; inset: 0; z-index: 9998; display: grid; place-items: center; background: rgba(8, 4, 24, .82); padding: 20px; }
.ad-box { width: 100%; max-width: 340px; background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 4px solid var(--ink); border-radius: 22px; box-shadow: 0 8px 0 var(--ink); padding: 20px; text-align: center; }
.ad-tag { font-size: 11px; font-weight: 900; letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); background: rgba(255,255,255,.08); border: 2px solid var(--ink); border-radius: 8px; padding: 3px 10px; display: inline-block; }
.ad-fake { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 52px; margin: 16px 0 6px; }
.ad-fake span { font-size: 15px; font-weight: 800; color: var(--muted); }
.ad-count { font-size: 30px; font-weight: 900; margin: 4px 0 14px; font-variant-numeric: tabular-nums; }
.ad-close { width: 100%; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); border-radius: 14px; padding: 13px; font-weight: 900; font-size: 16px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; }
.ad-close.ready { background: var(--pop-green); color: var(--ink); }
.ad-close:disabled { opacity: .6; cursor: default; }
.shop-item {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: var(--radius); padding: 16px 12px 12px;
  box-shadow: 0 5px 0 var(--ink);
}
.shop-item.owned { opacity: .92; }
.shop-swatch { width: 56px; height: 56px; border-radius: 50%; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); }
.shop-name { font-weight: 800; font-size: 15px; }
.shop-buy {
  border: 3px solid var(--ink); border-radius: 14px; padding: 7px 12px;
  background: var(--ink); color: #fff; font-weight: 800; box-shadow: 0 3px 0 var(--ink);
}
/* pastille de prix transparente sur le bouton noir → la pièce dorée reste visible */
.shop-buy .coin-pill { background: transparent; border: none; box-shadow: none; color: #fff; padding: 0; }
.shop-buy:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.shop-item.owned .shop-buy { background: var(--pop-green); color: var(--ink); }

/* verrous dans l'éditeur de profil */
.pick.locked, .swatch.locked { position: relative; opacity: .5; }
.pick .lock, .swatch .lock {
  position: absolute; right: 2px; top: 2px; font-size: 13px;
  background: rgba(0, 0, 0, .35); border-radius: 50%; line-height: 1; padding: 1px;
}
.swatch .lock { right: 50%; top: 50%; transform: translate(50%, -50%); background: none; font-size: 16px; }

/* ─────────────────────────────────────────────────────────────────────────────
   ZONES TACTILES — mesurées, pas devinées.
   Neuf boutons faisaient entre 20 et 34 px de côté, là où un pouce en demande 44
   (recommandation WCAG et Apple, reprise par Android). Sur les plus petits, on visait la
   carte du dessous aussi souvent que le bouton.
   ⚠️ On agrandit la zone de TOUCHE, jamais le dessin : un pseudo-élément invisible étend
   la surface cliquable autour du bouton. L'appli garde exactement la même allure.
   ⚠️ Et on ne le fait qu'APRÈS avoir mis une confirmation sur les deux boutons qui
   suppriment : élargir la cible d'une action irréversible non confirmée aurait multiplié
   les accidents au lieu de les éviter. L'ordre compte.
   ───────────────────────────────────────────────────────────────────────────── */
.pick-del, .prof-del, .fr-yes, .fr-no, .fr-rm, .pc-friend,
.fr-gift, .fr-msg, .react-pick, .emo-close, .rules-btn { position: relative; }
.pick-del::after, .prof-del::after, .fr-yes::after, .fr-no::after, .fr-rm::after,
.pc-friend::after, .fr-gift::after, .fr-msg::after, .react-pick::after,
.emo-close::after, .rules-btn::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
  /* Pas de fond, pas de bordure : la zone est là pour le doigt, pas pour l'œil. */
}
/* ⚠️ « Accepter » et « Refuser » sont CÔTE À CÔTE : 30 px de large, 10 px d'écart, donc
   40 px entre les deux centres. Des zones de 44 px se chevaucheraient de 4 px, et dans ce
   recouvrement c'est le dernier peint qui gagne — on refuserait un ami en croyant
   l'accepter. On borne donc la largeur à l'écart réel ; la hauteur, elle, reste à 44 px,
   la rangée ayant de la place au-dessus et en dessous.
   (.fr-gift et .fr-msg font 34 px : leurs centres sont à 44 px, les zones se touchent
   sans se recouvrir — elles gardent donc 44.) */
.fr-yes::after, .fr-no::after { width: 40px; }

/* toast */
#toast {
  position: fixed; left: 50%; bottom: 120px; transform: translate(-50%, 20px);
  z-index: 40; background: var(--ink); color: #fff; border: 3px solid #fff;
  border-radius: 16px; padding: 12px 20px; font-weight: 800; font-size: 14px;
  max-width: 84%; text-align: center; opacity: 0; pointer-events: none;
  transition: opacity .2s, transform .2s var(--spring);
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }
/* Refus : rouge franc. Le message n'accompagne pas une réussite, il explique un blocage —
   la couleur doit le dire avant même qu'on ait lu.
   ⚠️ --pop-red et non --pop-pink : sur le rose, le texte blanc tombait à 3,11:1. Un message
   d'erreur illisible est deux fois pénalisant — il arrive au pire moment. */
#toast.err { background: var(--pop-red); color: #fff; border-color: var(--ink); }

/* ---------- Jeu à distance (salons) ---------- */
.mode-seg { align-self: center; margin: 10px auto 4px; display: flex; }
.mode-seg button small { font-size: 10px; opacity: .8; }
.samescreen {
  text-align: center; margin: 10px auto 2px; color: var(--muted);
  font-size: 13px; font-weight: 700;
}
#lobby .seg { justify-content: center; }
#online-panel { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 8px 4px 20px; text-align: center; }
#online-panel[hidden] { display: none !important; } /* [hidden] doit battre display:flex (cf. .screen / #tabbar) */
.online-id { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted); font-weight: 700; flex-wrap: wrap; justify-content: center; }
.online-id b { color: var(--text); }
.chip-mini { padding: 5px 12px; font-size: 12px; box-shadow: 0 2px 0 var(--ink); }
.join-row { display: flex; gap: 10px; align-items: stretch; }
.code-input {
  width: 130px; margin: 0; text-transform: uppercase; letter-spacing: 6px;
  font-size: 22px; font-weight: 900; text-align: center;
}
.room-hint { margin: 4px 0 0; color: var(--muted); font-weight: 700; font-size: 13px; }
.room-code { display: flex; gap: 8px; }
.room-code span {
  display: block; width: 52px; padding: 10px 0; text-align: center;
  background: #fff; color: var(--ink); border: 3px solid var(--ink); border-radius: 14px;
  font-size: 30px; font-weight: 900; box-shadow: 0 4px 0 var(--ink);
}
.room-game { margin: 0; font-weight: 800; font-size: 14px; color: var(--muted); }
.room-players { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 340px; }
.room-p {
  display: flex; align-items: center; gap: 10px; text-align: start;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 18px;
  padding: 4px 14px 4px 6px; box-shadow: 0 3px 0 var(--ink);
}
.room-p.free { opacity: .4; border-style: dashed; box-shadow: none; min-height: 50px; justify-content: center; }
.room-p-name { flex: 1; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-p-name small { color: var(--muted); }
.room-p-name.muted { flex: none; color: var(--muted); }
.room-p-state { font-size: 16px; font-weight: 800; }
.room-actions { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.net-scores { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.net-sc {
  display: flex; align-items: center; gap: 6px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 999px;
  padding: 2px 12px 2px 4px; font-size: 13px;
}
.net-sc b { max-width: 74px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.net-sc-v { font-weight: 900; font-size: 16px; }
.net-round { margin: 0; color: var(--muted); font-weight: 800; font-size: 12px; letter-spacing: 1px; text-transform: uppercase; }
.net-problem {
  background: #fff; color: var(--ink); border: 4px solid var(--ink); border-radius: 22px;
  padding: 20px 30px; font-size: clamp(26px, 8vw, 40px); font-weight: 900;
  box-shadow: 0 6px 0 var(--ink); font-variant-numeric: tabular-nums;
}
.net-problem.net-role { font-size: clamp(19px, 5.6vw, 26px); }
.net-btns { display: flex; gap: 14px; justify-content: center; }
/* Même piège : les boutons sont marqués `hidden` pendant l'animation de révélation,
   et restaient pourtant à l'écran, cliquables au pire moment. */
.net-btns[hidden] { display: none; }
.net-big {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 108px; padding: 16px 20px; border: 4px solid var(--ink); border-radius: 20px;
  font-size: 21px; font-weight: 900; box-shadow: 0 6px 0 var(--ink);
  background: var(--panel-2); color: #fff;
  transition: transform .1s var(--spring), box-shadow .1s;
}
.net-big small { font-size: 12px; font-weight: 800; opacity: .85; }
.net-big.true { background: var(--pop-green); color: var(--ink); }
.net-big.false { background: var(--pop-pink); }
.net-big.dir { min-width: 86px; }
.net-big:active:not(:disabled) { transform: translateY(6px); box-shadow: 0 0 0 var(--ink); }
.net-big:disabled { opacity: .45; }
.net-big.picked { opacity: 1; outline: 3px solid #fff; }
.net-btns3 .net-big { padding: 12px 10px; }
.net-status { min-height: 22px; margin: 0; font-weight: 800; font-size: 16px; }
.net-endmascot { margin-top: 10px; }

/* ---------- Section Scores ---------- */
.scores-sec { margin-top: 14px; text-align: start; }
.scores-sec .section-title { text-align: center; }
.scores-total { text-align: center; color: var(--muted); font-weight: 700; font-size: 13px; margin: -4px 0 10px; }
.scores-empty { text-align: center; margin: 0 auto; }
.podium { display: flex; flex-direction: column; gap: 8px; }
.podium-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 18px;
  padding: 4px 14px 4px 6px; box-shadow: 0 3px 0 var(--ink);
}
.podium-row .mascot-view { flex: 0 0 auto; }
.podium-name { flex: 1; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.podium-wins { font-weight: 900; font-size: 15px; }
.match-list { display: flex; flex-direction: column; gap: 7px; }
.match-item { display: flex; flex-direction: column; }
.match-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  /* ⚠️ --border n'a JAMAIS existé. Une variable inconnue rend TOUT le raccourci `border`
     invalide, et la bordure retombe alors sur `none` : ces deux blocs n'en avaient donc
     aucune, sans que rien ne le signale. --ink est le contour sticker de la maison. */
  background: var(--panel); border: 2px solid var(--ink); border-radius: 15px;
  padding: 7px 10px; font: inherit; color: inherit; text-align: start; cursor: pointer;
}
/* Détail d'un match (déplié au tap) */
.match-detail {
  display: flex; flex-direction: column; gap: 6px;
  margin: 4px 8px 2px; padding: 10px 12px;
  background: var(--panel-2); border: 2px solid var(--ink); border-radius: 13px;
  animation: pop .25s var(--spring);
}
.match-meta { font-size: 12px; font-weight: 700; color: var(--muted); }
.match-player { display: flex; align-items: center; gap: 8px; }
.match-player .mascot-view { flex: 0 0 auto; }
.mp-name { flex: 1; font-weight: 800; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-score { font-weight: 900; font-size: 15px; font-variant-numeric: tabular-nums; }
.mp-crown { font-size: 15px; }
.match-player.winner .mp-name { color: var(--pop-yellow); }

/* Badge mode d'un match : 📱 même écran / 🌍 en ligne + tag compte par joueur */
.match-mode { font-weight: 800; }
.match-mode.m-on { color: var(--pop-blue); }
.match-mode-line { font-weight: 800; font-size: 12px; margin-top: 1px; }
.match-mode-line.m-on { color: var(--pop-blue); }
.match-mode-line.m-loc { color: var(--muted); }
.mp-acct { font-size: 9.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .3px; padding: 2px 7px; border-radius: 999px; flex: 0 0 auto; }
.mp-acct.mine { background: var(--pop-green); color: var(--ink); }
.mp-acct.other { background: var(--panel-2); color: var(--muted); }
.mp-acct.same { background: var(--panel-2); color: var(--muted); }
.mp-acct.bot { background: var(--panel); color: var(--muted); }


/* Bascule « avatar de mon compte » (éditeur de profil) */
.avatar-toggle { align-self: center; }
.avatar-toggle.on { background: var(--pop-yellow); color: var(--ink); }

/* Match en ligne (relais canvas) */
.net-hud { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; max-width: 520px; }
.net-scorepill { color: #fff; font-weight: 900; font-size: 14px; border: 3px solid var(--ink); border-radius: 999px; padding: 3px 12px; box-shadow: 0 3px 0 var(--ink); max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.net-roundlbl { font-size: 12px; font-weight: 800; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; }
.net-stage { width: 100%; max-width: 520px; height: min(62vh, 540px); border: 3px solid var(--ink); border-radius: 18px; overflow: hidden; box-shadow: 0 5px 0 var(--ink); background: var(--bg); }
.net-stage canvas { width: 100%; height: 100%; display: block; touch-action: none; }
.net-turnbar { margin: 0; font-weight: 800; font-size: 14px; color: var(--muted); }
.net-turnbar.me { color: var(--pop-yellow); animation: pop .3s var(--spring); }

/* Amis */
.fr-code { font-size: 14px; font-weight: 700; color: var(--muted); }
.fr-code b { color: var(--text); letter-spacing: 2px; font-size: 17px; background: var(--panel); border: 2px solid var(--ink); border-radius: 8px; padding: 2px 8px; margin-inline-start: 4px; }
.fr-add { display: flex; gap: 8px; }
.fr-add .name-input { flex: 1; margin: 0; }
.fr-add .btn { flex: 0 0 auto; align-self: auto; }
.fr-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.fr-av { flex: 0 0 auto; width: 38px; height: 38px; }
.fr-av.online { box-shadow: 0 0 0 3px var(--pop-green); border-radius: 50%; }
.fr-av.offline { box-shadow: 0 0 0 3px var(--pop-pink); border-radius: 50%; }
.fr-name { flex: 1; font-weight: 800; display: flex; flex-direction: column; min-width: 0; text-align: start; }
.fr-name small { font-weight: 600; color: var(--muted); font-size: 11px; }
.fr-name small.fr-on { color: var(--pop-green); }
.fr-name small.fr-off { color: var(--pop-pink); }
/* Sous-ligne du pseudo : pastille « admin » + statut, côte à côte SOUS le nom. */
.fr-sub { display: flex; align-items: center; gap: 6px; min-width: 0; flex-wrap: wrap; }
.fr-name small.fr-adm {
  flex: 0 0 auto; font-size: 9px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink); background: var(--pop-yellow); border: 2px solid var(--ink);
  border-radius: 999px; padding: 0 6px; line-height: 1.6;
}
.fr-play { font-weight: 800; font-size: 13px; padding: 6px 12px; border: 3px solid var(--ink); border-radius: 999px; background: var(--pop-yellow); color: var(--ink); box-shadow: 0 3px 0 var(--ink); cursor: pointer; }
.fr-play:disabled { opacity: .4; box-shadow: none; cursor: default; }
.fr-gift { width: 34px; height: 34px; flex: 0 0 auto; border: 2px solid var(--ink); border-radius: 50%; background: var(--pop-pink); font-size: 15px; cursor: pointer; }
/* Chat entre amis */
.fr-msg { position: relative; width: 34px; height: 34px; flex: 0 0 auto; border: 2px solid var(--ink); border-radius: 50%; background: var(--pop-blue); font-size: 15px; cursor: pointer; }
.fr-badge { position: absolute; top: -5px; inset-inline-end: -5px; min-width: 16px; height: 16px; padding: 0 3px; border-radius: 999px; background: var(--pop-pink); color: var(--ink); border: 2px solid var(--ink); font-size: 9px; font-weight: 900; line-height: 13px; text-align: center; }
/* Messagerie plein écran (façon appli de chat mobile) */
.chat-screen { position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; background: var(--bg); animation: fade .2s; }
/* ⚠️ EN-TETE EPINGLE. Trois choses le maintenaient en place mal ou pas du tout :
   1. `.chat-head` etait defini DEUX FOIS a specificite egale — ici, et 480 lignes plus bas
      pour le dock des salons. Le second gagnait, et cet en-tete perdait son fond ET sa
      reserve d'encoche `env(safe-area-inset-top)`. Les regles du dock sont desormais
      cantonnees sous `.chat-panel` ;
   2. sans `flex: 0 0 auto`, un en-tete est COMPRESSIBLE : le fil de messages pouvait
      l'ecraser (flex-shrink vaut 1 par defaut) ;
   3. `position: sticky` + `z-index` en ceinture et bretelles, pour que rien ne passe
      par-dessus meme si la structure evolue.
   Le fil (.chat-thread) est le SEUL conteneur qui defile : en-tete et barre de saisie
   restent donc visibles quelle que soit la longueur de la conversation. */
.chat-head {
  flex: 0 0 auto; position: sticky; top: 0; z-index: 3;
  display: flex; align-items: center; gap: 10px;
  padding: max(env(safe-area-inset-top), 12px) 14px 12px;
  background: #1b1246; border-bottom: 3px solid var(--ink);
}
.chat-back { font-size: 32px; font-weight: 900; line-height: 1; color: var(--text); width: 30px; flex: 0 0 auto; }
.chat-head-av { flex: 0 0 auto; }
.chat-head-id { display: flex; flex-direction: column; min-width: 0; }
.chat-head-id b { font-size: 17px; font-weight: 900; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-head-id small { font-size: 12px; font-weight: 700; }
.chat-on { color: var(--pop-green); }
.chat-off { color: var(--pop-pink); }
.chat-thread { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; gap: 3px; padding: 14px; }
.chat-empty { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 8px; color: var(--muted); font-size: 42px; }
.chat-empty span { font-size: 14px; font-weight: 700; }
.chat-msg { max-width: 80%; padding: 9px 13px; font-size: 15px; font-weight: 500; line-height: 1.35; word-break: break-word; border: 2px solid var(--ink); }
.chat-msg.mine { align-self: flex-end; background: var(--pop-green); color: var(--ink); border-radius: 18px 18px 5px 18px; }
.chat-msg.them { align-self: flex-start; background: var(--panel-2); color: var(--text); border-radius: 18px 18px 18px 5px; }
.chat-msg.mine.grp { border-radius: 18px 5px 5px 18px; margin-top: -1px; }
.chat-msg.them.grp { border-radius: 5px 18px 18px 5px; margin-top: -1px; }
/* Barre de saisie EPINGLEE en bas, pour la meme raison que l'en-tete : sans
   `flex: 0 0 auto` elle se fait comprimer par le fil. Le padding bas integre deja
   `env(safe-area-inset-bottom)` (barre gestuelle des telephones sans bouton). */
.chat-bar { flex: 0 0 auto; position: sticky; bottom: 0; z-index: 3; display: flex; align-items: center; gap: 10px; padding: 10px 12px calc(env(safe-area-inset-bottom) + 10px); background: #1b1246; border-top: 3px solid var(--ink); }
.chat-field { flex: 1; min-width: 0; margin: 0; padding: 11px 16px; border: 3px solid var(--ink); border-radius: 999px; background: var(--panel); color: var(--text); font: inherit; font-size: 15px; }
.chat-field:focus { outline: none; border-color: var(--pop-blue); }
.chat-send { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 50%; background: var(--pop-blue); border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); display: grid; place-items: center; }
.chat-send:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.chat-send svg { width: 22px; height: 22px; }
/* Feuille « offrir des pièces » */
.gift-box { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 8px; }
.gift-to { font-weight: 800; font-size: 16px; margin: 0; }
.gift-bal { color: var(--muted); font-weight: 700; margin: 0; display: flex; align-items: center; gap: 6px; }
/* Le popup cadeau porte DEUX sections, pieces puis etoiles. Un intertitre discret et un
   trait a l'encre : sans separation, les deux champs de saisie se lisaient comme un seul
   formulaire et on ne savait plus lequel donnait quoi. */
.gift-sec { margin: 15px 0 5px; font-size: 12px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.gift-sec:first-of-type { margin-top: 9px; }
.gift-sep { height: 3px; margin: 17px 0 3px; background: var(--ink); border-radius: 2px; }
.gift-amounts { display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); gap: 10px; width: 100%; }
.gift-amt { font-weight: 900; font-size: 16px; padding: 12px; border: 3px solid var(--ink); border-radius: 14px; background: var(--ink); color: #fff; box-shadow: 0 4px 0 rgba(36, 26, 58, .35); cursor: pointer; }
.gift-amt:disabled { opacity: .35; box-shadow: none; cursor: default; }
.gift-amt:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.gift-custom { display: flex; gap: 8px; width: 100%; margin-top: 2px; }
.gift-all { width: 100%; margin-top: 8px; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); font-weight: 800; }
.gift-all:disabled { opacity: .45; }
.gift-inf { width: 100%; margin-top: 8px; background: linear-gradient(135deg, var(--pop-purple), var(--pop-pink)); color: #fff; border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); font-weight: 900; }
.gift-inf:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.gift-admin-sep { margin-top: 14px; font-size: 11px; font-weight: 900; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); text-align: center; border-top: 2px dashed var(--ink); padding-top: 11px; }
.gift-rem { width: 100%; margin-top: 8px; background: var(--panel); color: var(--pop-pink-lt); border: 3px solid var(--pop-pink); box-shadow: 0 4px 0 var(--ink); font-weight: 900; }
.gift-rem:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
/* Bascule Donner ⇄ Retirer (admins) + habillage du mode retrait */
.gift-toggle { width: 100%; margin: 0 0 2px; font-weight: 900; border: 3px solid var(--pop-pink); box-shadow: 0 3px 0 var(--ink); background: var(--panel); color: var(--pop-pink-lt); }
.gift-toggle.is-take { border-color: var(--ink); background: var(--pop-green); color: var(--ink); }
.gift-toggle:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.gift-box.take-mode .gift-to { color: var(--pop-pink); }
.gift-amt.is-take { border-color: var(--pop-pink); color: var(--pop-pink); }

.gift-custom .name-input { flex: 1; margin: 0; text-align: center; }
.gift-custom .btn { flex: 0 0 auto; align-self: auto; }
/* 🪄 baguette magique admin */
.magic-btn { background: linear-gradient(135deg, var(--pop-purple), var(--pop-pink)); color: #fff; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); }
/* Un module = un titre (« Pieces » / « Etoiles ») + sa rangee. C'est le titre qui distingue
   les deux, et non un pictogramme dans la rangee : celui-la volait la place du champ. */
.magic-block { margin-bottom: 10px; }
.magic-lbl { margin: 0 0 5px 4px; font-size: 11px; font-weight: 900; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.magic-row { display: flex; align-items: center; gap: 8px; padding: 8px; background: var(--panel); border: 3px solid var(--ink); border-radius: 16px; }
/* Le champ garde un PLANCHER : avec `min-width: 0`, flex l'autorise a se reduire jusqu'a
   zero et la barre de saisie disparait des que la rangee se serre. 44 px suffisent a voir
   le nombre, et laissent la rangee tenir sur UNE ligne jusqu'a 320 px de large (voir la
   regle compacte plus bas). Le champ est l'element le plus important des cinq : il ne doit
   ceder qu'en dernier. */
.magic-input { flex: 1 1 auto; margin: 0; min-width: 44px; text-align: center; }
.magic-add, .magic-sub { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 14px; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); font-size: 26px; font-weight: 900; line-height: 1; color: #fff; }
.magic-add { background: var(--pop-green); }
.magic-inf { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 14px; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); font-size: 24px; font-weight: 900; line-height: 1; color: var(--ink); background: var(--pop-yellow); }

/* ---- Rangee admin sur PETIT telephone -------------------------------------------------
   CALCUL, pas une intuition. La rangee reclame 4 boutons + 4 gouttieres + le champ, et la
   largeur utile vaut (viewport - 90) : 15 px de padding d'ecran de chaque cote, 3 px de
   bordure de carte, 16 px de padding de carte, plus 3 + 8 px de bordure et de padding de la
   rangee. A 46 px et 8 px de gouttiere il faut 216 px avant le champ : ca passe a 360 px,
   ca ne passe plus a 320 px. On retrecit donc legerement plutot que de passer a deux
   lignes : 40 px et 6 px de gouttiere ramenent le besoin a 184 px, et la rangee tient sur
   UNE seule ligne jusqu'a 320 px. 40 px reste une cible confortable au pouce. */
@media (max-width: 380px) {
  .magic-row { gap: 6px; padding: 7px; }
  .magic-trash, .magic-sub, .magic-add, .magic-inf { width: 40px; height: 40px; }
  .magic-add, .magic-sub { font-size: 23px; }
  .magic-inf { font-size: 21px; }
}


.magic-inf:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
/* Poubelle admin (à gauche) : vide toutes les pièces — même gabarit que ∞, fond rouge, icône blanche */
.magic-trash { flex: 0 0 auto; width: 46px; height: 46px; display: grid; place-items: center; border-radius: 14px; border: 3px solid var(--ink); box-shadow: 0 3px 0 var(--ink); background: var(--pop-pink); }
.magic-trash svg { width: 24px; height: 24px; display: block; }
.magic-trash:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.gift-friend-bal { color: var(--muted); margin-top: -4px; }
.gift-friend-bal .coin-pill { vertical-align: middle; }

/* Bouton vers le tableau de bord admin, en haut de Mon compte (admins) */
.acct-admin-link { display: flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 900; font-size: 15px; color: var(--ink); background: linear-gradient(135deg, var(--pop-yellow), #ff9e2c); border: 3px solid var(--ink); box-shadow: 0 5px 0 var(--ink); border-radius: 16px; padding: 13px 16px; }
.acct-admin-link > span:first-of-type { flex: 1; }
.acct-admin-link .aal-arw { font-size: 22px; line-height: 1; }
.acct-admin-link:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--ink); }

/* Fiche d'un joueur (clic depuis le Hall of Fame, admins) */
.pcard { display: flex; flex-direction: column; gap: 12px; }
.pcard .stx-grid { grid-template-columns: repeat(2, 1fr); }   /* 4 cellules → 2×2 propre (pas 3+1) */
.pcard .stx-lines { display: flex; flex-direction: column; gap: 8px; }
.pcard-id { display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--panel); border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 4px 0 var(--ink); }
.pcard-id > .mascot-view { flex: 0 0 auto; }
.pcard-idtxt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pcard-name { font-size: 20px; font-weight: 900; letter-spacing: -.5px; display: flex; align-items: center; gap: 8px; min-width: 0; }
.pcard-nametxt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Picto « ajouter en ami » (fiche du joueur) — états ✓ amis / ⏳ en attente / ✗ refusé / + ajouter. */
.pc-friend { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; border: 2px solid var(--ink); display: grid; place-items: center; font-size: 15px; font-weight: 900; line-height: 1; cursor: pointer; background: var(--panel-2); color: var(--text); box-shadow: 0 2px 0 var(--ink); }
.pc-friend svg { width: 17px; height: 17px; }
.pc-friend.add { background: var(--pop-green); color: var(--ink); }
.pc-friend.ok { background: var(--pop-green); color: var(--ink); }
.pc-friend.pending { background: var(--pop-yellow); color: var(--ink); }
.pc-friend.refused { background: #e0245e; color: #fff; }
.pc-friend[disabled] { cursor: default; box-shadow: none; }
.pc-friend:not([disabled]):active { transform: translateY(2px); box-shadow: none; }
.pcard-mail { font-size: 12px; color: var(--muted); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard-coins { flex: 0 0 auto; font-weight: 900; font-size: 15px; background: var(--ink); color: var(--pop-yellow); padding: 6px 11px; border-radius: 999px; white-space: nowrap; }
.pcard-sec { font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-top: 4px; }
.pcard-msg { display: flex; gap: 8px; }
.pcard-msg .name-input { flex: 1; margin: 0; min-width: 0; }
.pcard-msg .pc-msgsend { flex: 0 0 auto; }
.pcard-admin { display: flex; gap: 8px; }
.pc-block, .pc-del { flex: 1; font-weight: 900; border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); }
.pc-block { background: var(--panel-2); color: var(--text); }
.pc-del { background: var(--panel); color: var(--pop-pink-lt); border: 3px solid var(--pop-pink); }
.pc-del.armed { background: var(--pop-pink); color: var(--ink); border-color: var(--ink); }
.pc-block:active, .pc-del:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.magic-sub { background: var(--pop-pink); }
.magic-add:active, .magic-sub:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }

/* Fiche personnage (boutique) */
.mascot-sheet { display: flex; flex-direction: column; align-items: center; gap: 12px; margin-top: 2px; --tint: #a05cff; }
/* Scène : sunburst tournant + halo teinté + étincelles, mascotte qui flotte */
.ms-stage { position: relative; display: grid; place-items: center; width: 100%; height: 188px; overflow: hidden; border: 3px solid var(--ink); border-radius: 24px; background: radial-gradient(circle at 50% 44%, var(--panel-2), var(--panel) 70%); box-shadow: inset 0 3px 0 rgba(255, 255, 255, .05); }
.ms-rays { position: absolute; width: 340px; height: 340px; color: var(--tint); opacity: .24; animation: msSpin 24s linear infinite; }
.ms-glow { position: absolute; width: 190px; height: 190px; border-radius: 50%; background: radial-gradient(circle, var(--tint), transparent 66%); opacity: .42; filter: blur(5px); }
.ms-hero { position: relative; width: 128px; height: 128px; filter: drop-shadow(0 9px 0 rgba(36, 26, 58, .3)); animation: msFloat 3.6s ease-in-out infinite; }
.ms-cat { position: absolute; top: 12px; inset-inline-end: 12px; transform: rotate(6deg); background: var(--pop-yellow); color: var(--ink); border: 3px solid var(--ink); border-radius: 999px; padding: 4px 11px; font-weight: 900; font-size: 12px; box-shadow: 0 3px 0 var(--ink); }
.ms-spark { position: absolute; color: #fff; font-size: 18px; opacity: .8; animation: msTwinkle 2.4s ease-in-out infinite; pointer-events: none; }
.ms-spark.s1 { top: 20px; left: 26px; }
.ms-spark.s2 { bottom: 26px; left: 42px; font-size: 14px; animation-delay: .8s; }
.ms-spark.s3 { top: 44px; right: 52px; font-size: 15px; animation-delay: 1.4s; }
@keyframes msSpin { to { transform: rotate(360deg); } }
@keyframes msFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
@keyframes msTwinkle { 0%, 100% { transform: scale(.55); opacity: .3; } 50% { transform: scale(1.1); opacity: .95; } }
@media (prefers-reduced-motion: reduce) { .ms-rays, .ms-hero, .ms-spark { animation: none; } }
.ms-price { font-size: 22px; font-weight: 900; }
.ms-storycard { position: relative; align-self: stretch; background: var(--panel-2); border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 4px 0 var(--ink); padding: 16px 16px 14px; }
.ms-quote { position: absolute; top: -12px; left: 12px; font-family: Georgia, 'Times New Roman', serif; font-size: 52px; line-height: 1; font-weight: 900; color: var(--tint); text-shadow: 0 2px 0 var(--ink); }
.ms-story { font-size: 15px; font-weight: 600; line-height: 1.55; text-align: center; color: var(--text); margin: 0; }
/* Bouton « Adopter » : fond NOIR (pièce dorée visible), ombre teintée, ressort */
.ms-buy { align-self: stretch; display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: var(--ink); color: #fff; border: 3px solid var(--ink); border-radius: 16px; padding: 14px; font-weight: 900; font-size: 16px; box-shadow: 0 5px 0 var(--bg2); transition: transform .12s var(--spring), box-shadow .12s; }
.ms-buy:active { transform: translateY(5px); box-shadow: 0 0 0 var(--bg2); }
.ms-buy .coin-pill { background: transparent; border: none; box-shadow: none; color: #fff; padding: 0; }
.ms-cart { font-size: 18px; }
/* Personnage possédé : bouton Rembourser (rend 85 %) + prix remboursé / prix du perso dessous.
   1er tap = armé (rouge « Confirmer ? »), 2e tap = rembourse. Anti-remboursement accidentel. */
.ms-refund { align-self: stretch; display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); border-radius: 16px; padding: 13px; font-weight: 900; font-size: 16px; box-shadow: 0 5px 0 var(--bg2); transition: transform .12s var(--spring), box-shadow .12s, background .15s, color .15s; cursor: pointer; }
.ms-refund:active { transform: translateY(5px); box-shadow: 0 0 0 var(--bg2); }
.ms-refund.armed { background: #ff5470; color: var(--ink); border-color: #ff5470; }
.ms-back { font-size: 18px; }
.ms-refund-info { align-self: stretch; display: flex; flex-direction: column; gap: 6px; }
.ms-rline { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 800; font-size: 14px; background: var(--panel-2); border: 2px solid var(--ink); border-radius: 12px; padding: 8px 12px; }
.ms-rlab { color: var(--muted); }
.ms-rline .coin-pill { font-size: 14px; padding: 2px 10px; }
.fr-yes, .fr-no, .fr-rm { width: 30px; height: 30px; flex: 0 0 auto; border: 2px solid var(--ink); border-radius: 50%; font-weight: 900; cursor: pointer; }
.fr-yes { background: var(--pop-green); color: var(--ink); }
.fr-no, .fr-rm { background: var(--panel-2); color: var(--muted); }
.fr-empty { color: var(--muted); font-weight: 600; font-size: 13px; text-align: center; margin: 4px 0; }
.fr-loader { display: flex; align-items: center; justify-content: center; gap: 9px; color: var(--muted); font-weight: 700; font-size: 13px; padding: 14px 0; }
.spinner { width: 16px; height: 16px; border-radius: 50%; border: 3px solid var(--panel-2); border-top-color: var(--pop-yellow); animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Hall of Fame (Mon compte) */
.hall-list { display: flex; flex-direction: column; gap: 7px; }
.hall-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; background: var(--panel); border: 2px solid var(--ink); border-radius: 12px; }
.hall-row.me { border-color: var(--pop-yellow); box-shadow: inset 0 0 0 2px var(--pop-yellow); }
.hall-rank { flex: 0 0 auto; width: 32px; text-align: center; font-weight: 900; font-size: 16px; font-variant-numeric: tabular-nums; }
.hall-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 800; }
.hall-coins { flex: 0 0 auto; }
.hall-list .fr-more { margin-top: 0; }   /* la liste est déjà en flex avec gap */

/* Bannière Hall of Fame (bas de la home) + popup */
.hall-banner { display: flex; align-items: center; gap: 12px; width: 100%; max-width: 640px; margin: 22px auto 4px; padding: 14px 16px; background: linear-gradient(100deg, var(--pop-purple), var(--pop-pink)); border: 3px solid var(--ink); border-radius: 20px; box-shadow: 0 5px 0 var(--ink); text-align: start; transition: transform .12s var(--spring), box-shadow .12s; }
.hall-banner:active { transform: translateY(5px); box-shadow: 0 0 0 var(--ink); }
.hall-banner-ico { font-size: 34px; line-height: 1; flex: 0 0 auto; filter: drop-shadow(0 2px 0 var(--ink)); animation: hallWobble 3s ease-in-out infinite; }
.hall-banner-txt { display: flex; flex-direction: column; flex: 1; min-width: 0; color: #fff; }
.hall-banner-txt b { font-size: 18px; font-weight: 900; letter-spacing: -.3px; }
.hall-banner-txt small { font-size: 12.5px; font-weight: 700; opacity: .92; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hall-banner-arw { font-size: 30px; font-weight: 900; color: #fff; flex: 0 0 auto; }
@keyframes hallWobble { 0%,100% { transform: rotate(-8deg); } 50% { transform: rotate(8deg); } }
@media (prefers-reduced-motion: reduce) { .hall-banner-ico { animation: none; } }
.hall-sheet { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.hall-hero { font-size: 56px; line-height: 1; filter: drop-shadow(0 3px 0 var(--ink)); }
.hall-intro { text-align: center; color: var(--muted); font-weight: 600; line-height: 1.5; margin: 0 0 4px; max-width: 40ch; }
.hall-sheet .hall-list { align-self: stretch; width: 100%; }


@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 1.6s; } }
.fr-gamepick { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 10px; margin-top: 8px; }
.fr-game { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 6px; border: 3px solid var(--ink); border-radius: 16px; background: var(--panel-2); color: var(--text); font-weight: 800; font-size: 12px; box-shadow: 0 4px 0 var(--ink); cursor: pointer; }
.fr-game-ico { width: 40px; height: 40px; }
.fr-game-ico svg { width: 100%; height: 100%; }
/* Bannière d'invitation à jouer */
#invite-banner {
  position: fixed; top: calc(env(safe-area-inset-top) + 10px); left: 50%; transform: translateX(-50%);
  z-index: 50; display: flex; align-items: center; gap: 10px; max-width: 92vw;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 16px;
  padding: 8px 10px; box-shadow: 0 6px 0 var(--ink); animation: pop .3s var(--spring);
}
.inv-ico { width: 34px; height: 34px; flex: 0 0 auto; }
.inv-ico svg { width: 100%; height: 100%; }
.inv-txt { display: flex; flex-direction: column; min-width: 0; text-align: start; }
.inv-txt small { color: var(--muted); font-size: 12px; font-weight: 600; }
.inv-join { font-weight: 900; font-size: 13px; padding: 6px 12px; border: 3px solid var(--ink); border-radius: 999px; background: var(--pop-green); color: var(--ink); cursor: pointer; }
.inv-x { background: none; border: none; color: var(--muted); font-size: 16px; font-weight: 900; cursor: pointer; }
.match-ico { width: 30px; height: 30px; flex: 0 0 auto; }
.match-ico svg { width: 100%; height: 100%; }
.match-info { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.match-info b { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.match-info small { color: var(--muted); font-size: 11px; font-weight: 600; }
.match-score { font-weight: 900; font-size: 15px; font-variant-numeric: tabular-nums; }
.match-win {
  color: #fff; font-weight: 800; font-size: 12px;
  border: 2px solid var(--ink); border-radius: 999px; padding: 2px 10px;
  max-width: 86px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#account .chip-btn, #account .btn { align-self: center; }
#account .link-danger { margin-top: 4px; }

/* Mon compte — refonte en cartes sectionnées (mobile first) */
.acct-wrap { display: flex; flex-direction: column; gap: 14px; max-width: 640px; margin: 0 auto; }
.acct-card { background: linear-gradient(165deg, var(--panel-2), var(--panel)); border: 3px solid var(--ink); border-radius: var(--radius); box-shadow: 0 6px 0 var(--ink); }
.acct-card-h { font-size: 12px; font-weight: 900; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); padding: 13px 16px 0; }
.acct-card-b { display: flex; flex-direction: column; gap: 11px; padding: 14px 16px 16px; }
.acct-header .acct-card-b { flex-direction: row; align-items: center; gap: 14px; }
.acct-avatar { flex: 0 0 auto; }
.acct-idblock { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-align: start; }
/* ⚠️ `overflow-wrap: anywhere` OBLIGATOIRE. La colonne du pseudo ne fait que 112 px de large
   à 320 px de viewport (l'avatar en prend 76, la colonne de pictos 66). Or le champ autorise
   16 caractères SANS contrainte d'espace (app.js, maxlength, et mb_strlen côté serveur) :
   « SuperMegaJoueur » mesure ~200 px d'un seul tenant. Sans point de coupure, le mot
   traversait la colonne de pictos et sortait de la carte, en provoquant un défilement
   horizontal parasite sur tout l'écran.
   On COUPE plutôt qu'on ne TRONQUE : un joueur doit pouvoir lire son propre nom en entier. */
.acct-hi { font-size: 23px; font-weight: 900; letter-spacing: -.5px; overflow-wrap: anywhere; }
.pseudo-edit { font-size: 13px; padding: 3px 8px; border-radius: 10px; background: var(--panel-2); border: 2px solid var(--ink); margin-inline-start: 7px; vertical-align: middle; line-height: 1; }
.pseudo-edit:active { transform: translateY(1px); }
/* « Mot de passe oublié ? » : lien discret sous le bouton de connexion */
.acct-forgot { background: none; border: 0; color: var(--muted); font-weight: 700; font-size: 14px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; padding: 4px; margin: -2px auto 0; }
.acct-forgot:active { transform: translateY(1px); }
.pseudo-edit-box { display: flex; flex-direction: column; gap: 12px; }
.pseudo-edit-box .name-input { margin: 0; text-align: center; }
/* ❗ Signaler un problème : à côté du pseudo (joueurs non-admin) — encadré COMME le stylo ✏️
   (même cadre neutre : fond panneau + bordure encre), PAS de pavé rouge. */
.report-box { display: flex; flex-direction: column; gap: 8px; }
.report-intro { font-size: 14px; color: var(--muted); margin: 0 0 4px; line-height: 1.5; }
.report-lab { font-size: 13px; font-weight: 800; color: var(--muted); margin-top: 4px; }
.report-box .name-input { margin: 0; }
.report-msg { resize: vertical; min-height: 90px; font: inherit; line-height: 1.4; }
.report-send { margin-top: 8px; }

/* L'e-mail sous le pseudo. Il héritait du gros badge arrondi (centré, 18 px de marge
   interne, sans troncature) : une adresse un peu longue passait SOUS la cloche et le
   drapeau de signalement. Ici : plus petit, aligné à gauche sous le pseudo, et coupé
   par des points de suspension — il ne peut plus mordre sur la colonne de pictos. */
.acct-header .acct-mail {
  margin: 0; align-self: start; max-width: 100%;
  /* Agrandie (05/08) : à 12,5 px elle se lisait mal, et c'est elle qu'on touche pour
     changer d'adresse — un bouton doit se lire. */
  font-size: 14px; font-weight: 700;
  padding: 4px 11px; border-width: 2px; box-shadow: 0 2px 0 var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Les DEUX soldes sur la MEME ligne, sous l'adresse : ils se lisent comme un seul porte-
   monnaie a deux poches. `flex-wrap` pour qu'ils passent l'un sous l'autre plutot que de
   deborder sur un tres petit ecran, et `align-items: center` parce que les deux pastilles
   n'ont pas exactement la meme hauteur de contenu (emoji contre SVG). */
.acct-wallets { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.acct-coins, .acct-stars { margin: 0; }
.acct-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
/* Pack Fun v2 — fête du bonus quotidien */
.stat-tile { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 13px 6px; background: var(--panel); border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 4px 0 var(--ink); }
.stat-ico { font-size: 22px; line-height: 1; }
.stat-n { font-size: 22px; font-weight: 900; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-n.stat-name { font-size: 15px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat-l { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }

/* 🔔 Cloche de notifications dans le header « Mon compte » (déplacée de la bottom bar) */
.acct-header { position: relative; }
/* Réserve la place de la colonne de pictos en haut de la carte de compte. */
.acct-header .acct-card-b { padding-inline-end: 66px; min-height: 92px; }
/* Colonne : cloche en haut, drapeau en dessous (l'ordre du DOM fait l'ordre visuel).
   Un conteneur flex plutôt que deux décalages calculés à la main. */
.hdr-actions { position: absolute; top: 12px; inset-inline-end: 12px; display: flex; flex-direction: column; gap: 8px; }
.hdr-bell, .hdr-report { position: relative; width: 42px; height: 42px; display: grid; place-items: center; background: var(--panel-2); border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 3px 0 var(--ink); cursor: pointer; }
.hdr-bell:active, .hdr-report:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.hdr-bell svg, .hdr-report svg { width: 24px; height: 24px; display: block; }
.hdr-bell .tab-badge { top: -7px; inset-inline-end: -7px; }

/* 📊 Carte Statistiques du compte (remplace l'ancienne section Scores) */
.stx-id { display: flex; align-items: center; gap: 13px; padding: 12px; background: var(--panel); border: 3px solid var(--ink); border-radius: 20px; box-shadow: 0 4px 0 var(--ink); }
.stx-id > .mascot-view { flex: 0 0 auto; }
.stx-idtxt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.stx-name { font-size: 21px; font-weight: 900; letter-spacing: -.5px; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stx-sub { font-size: 13px; font-weight: 700; color: var(--muted); display: flex; align-items: center; gap: 6px; min-width: 0; }
.stx-si { flex: 0 0 auto; display: inline-flex; }
.stx-si svg { width: 16px; height: 16px; display: block; }
.acct-stats-card .acct-card-h { display: flex; align-items: center; gap: 7px; }
.stx-titico { display: inline-flex; }
.stx-titico svg { width: 18px; height: 18px; display: block; }
.stx-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.stx-cell { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 12px 4px; background: var(--panel); border: 3px solid var(--ink); border-radius: 16px; box-shadow: 0 4px 0 var(--ink); text-align: center; }
.stx-ico { line-height: 1; display: inline-flex; }
.stx-ico svg { width: 25px; height: 25px; display: block; }
.stx-cell b { font-size: 20px; font-weight: 900; font-variant-numeric: tabular-nums; line-height: 1.05; letter-spacing: -.5px; }
.stx-cell.win b { color: var(--pop-green); }
.stx-cell.loss b { color: var(--pop-pink); }
.stx-cell.rate b { color: var(--pop-yellow); }
.stx-cell small { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .3px; color: var(--muted); }
.stx-lines { display: flex; flex-direction: column; gap: 8px; }
.stx-line { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px; background: var(--panel); border: 3px solid var(--ink); border-radius: 14px; }
.stx-line > span { font-weight: 800; font-size: 13.5px; color: var(--muted); display: flex; align-items: center; gap: 7px; }
.stx-line > span svg { width: 20px; height: 20px; display: block; flex: 0 0 auto; }
.stx-line > b { font-weight: 900; font-size: 15px; text-align: end; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; align-items: center; gap: 6px; min-width: 0; }
.stx-gi { display: inline-flex; flex: 0 0 auto; }
.stx-gi svg { width: 20px; height: 20px; display: block; }
.set-label { font-size: 12px; font-weight: 800; color: var(--muted); }
.acct-pitch { color: var(--muted); font-weight: 700; font-size: 14px; line-height: 1.4; margin: 0; text-align: center; }
.acct-auth .acct-card-b, .acct-pending .acct-card-b { align-items: center; text-align: center; }
.acct-card .scores-sec, .acct-card .section-title:first-child { margin-top: 0; }

/* ⭐ Avatar du compte sur les cartes Personnage */
.prof-card { position: relative; }
.prof-star { position: absolute; top: 4px; inset-inline-end: 6px; font-size: 20px; line-height: 1; cursor: pointer; opacity: .75; transition: transform .12s var(--spring); }
.prof-star:active { transform: scale(1.25); }
.prof-star.on { opacity: 1; }

/* Accordéon « Derniers matchs » + « voir tous les matchs » */
/* Bouton « ? » règles (lobby) + contenu de la feuille */
.rules-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  font: inherit; font-size: 16px; font-weight: 900; color: var(--ink);
  background: var(--pop-yellow); border: 3px solid var(--ink); border-radius: 50%;
  box-shadow: 0 3px 0 var(--ink); cursor: pointer; transition: transform .12s var(--spring);
}
.rules-btn:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.rules-box { display: flex; flex-direction: column; gap: 14px; margin-top: 2px; text-align: start; }
/* Scène : icône du jeu qui flotte + étincelles */
.rules-hero { position: relative; display: grid; place-items: center; height: 100px; overflow: hidden; border: 3px solid var(--ink); border-radius: 20px; background: radial-gradient(circle at 50% 42%, var(--panel-2), var(--panel) 72%); box-shadow: inset 0 3px 0 rgba(255, 255, 255, .05); }
.rules-hero-ico { width: 66px; height: 66px; filter: drop-shadow(0 4px 0 var(--ink)); animation: rulesFloat 3.4s ease-in-out infinite; }
.rules-hero-ico svg { width: 100%; height: 100%; overflow: visible; }
.rules-spark { position: absolute; color: #fff; opacity: .7; font-size: 15px; animation: msTwinkle 2.4s ease-in-out infinite; pointer-events: none; }
.rules-spark.s1 { top: 16px; left: 28px; }
.rules-spark.s2 { bottom: 16px; right: 32px; font-size: 12px; animation-delay: .9s; }
@keyframes rulesFloat { 0%, 100% { transform: translateY(0) rotate(-3deg); } 50% { transform: translateY(-6px) rotate(3deg); } }
@media (prefers-reduced-motion: reduce) { .rules-hero-ico, .rules-spark { animation: none; } }
/* 4 sections en cartes colorées avec picto SVG sticker */
.rules-list { display: flex; flex-direction: column; gap: 10px; }
.rules-row { display: flex; gap: 12px; align-items: flex-start; background: var(--panel); border: 3px solid var(--ink); border-radius: 16px; padding: 12px 14px; box-shadow: 0 4px 0 var(--ink); }
.rules-ico { flex: 0 0 auto; width: 34px; height: 34px; }
.rules-ico svg { width: 100%; height: 100%; overflow: visible; }
.rules-txt { margin: 0; font-size: 14.5px; font-weight: 600; line-height: 1.45; color: var(--text); }
.rules-row.r-goal { border-color: var(--pop-pink); }
.rules-row.r-controls { border-color: var(--pop-blue); }
.rules-row.r-scoring { border-color: var(--pop-yellow); }
.rules-row.r-tip { border-color: var(--pop-green); }
/* Bouton « ? » EN JEU (mode d'emploi pendant la partie) — vit dans .ingame-dock,
   qui porte son positionnement et ses états replié/déplié. */
.rules-ingame {
  width: 40px; height: 40px; border: 3px solid var(--ink); border-radius: 12px;
  background: rgba(45, 33, 112, .85); color: #fff; font-size: 18px; font-weight: 900; cursor: pointer;
}
/* « ↻ » — repartir de zéro sans quitter, mêmes réglages. Même boîte que ses voisins du
   dock : c'est une rangée, elle doit se lire comme une rangée.
   ⚠️ 40 px de côté, comme les autres : la règle des 44 px ne s'applique pas ici, le dock
   est REPLIÉ par défaut et ne s'ouvre que sur un geste délibéré — on ne l'effleure pas en
   jouant. C'était justement la raison d'être de cette poignée. */
.restart-ingame {
  width: 40px; height: 40px; border: 3px solid var(--ink); border-radius: 12px;
  background: rgba(45, 33, 112, .85); color: #fff; font-size: 21px; font-weight: 900;
  line-height: 1; cursor: pointer;
}
/* ⚠️ Pas de `:active` propre ici : le dock en impose déjà un à tous ses boutons
   (`scale(.92)`), et il l'emporte en spécificité. Un second, plus faible, n'aurait servi
   qu'à faire croire que ce bouton réagit autrement que ses voisins. */

.match-acc { margin-top: 15px; }
.match-acc-h { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 8px 2px; background: none; border: none; color: var(--text); font-weight: 900; font-size: 13px; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; }
.acc-chevron { transition: transform .2s var(--spring); color: var(--muted); }
.match-acc:not(.open) .acc-chevron { transform: rotate(-90deg); }
.match-acc:not(.open) .match-acc-b { display: none; }
.match-acc-b { display: flex; flex-direction: column; gap: 7px; }
.match-all { align-self: center; margin-top: 4px; }

/* Sélecteur de personnages : filtres (catégorie) + tri */
.pick-bar { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 14px; margin: 4px auto 10px; }
.pick-filters { display: inline-flex; gap: 3px; padding: 3px; background: var(--panel); border: 2px solid var(--ink); border-radius: 999px; }
.pick-chip { font: inherit; font-size: 12px; font-weight: 800; color: var(--text); background: transparent; border: none; border-radius: 999px; padding: 5px 11px; cursor: pointer; white-space: nowrap; }
.pick-chip.on { background: var(--pop-purple-lt); color: var(--ink); }
.pick { position: relative; }
/* ✕ retirer un personnage depuis « Qui joue ici ? » (un seul clic) */
.pick-del {
  position: absolute; top: 2px; inset-inline-end: 4px; width: 20px; height: 20px;
  display: grid; place-items: center; border-radius: 50%;
  font-size: 12px; font-weight: 900; line-height: 1;
  color: var(--muted); background: var(--panel-2); border: 2px solid var(--ink);
  opacity: .75; cursor: pointer; transition: opacity .12s, transform .12s var(--spring);
}
.pick-del:active { opacity: 1; transform: scale(.86); background: var(--pop-pink); color: var(--ink); }
/* Filtre sans résultat dans le sélecteur de mascotte */
.pick-none { grid-column: 1 / -1; margin: 10px 0; text-align: center; color: var(--muted); font-weight: 700; font-size: 13px; }
/* Prix EXACT (donc parfois long : « 24 032 014 ») sur une vignette de 60 px : chiffres
   tabulaires et un poil plus petits, sinon la pastille déborde sur ses voisines. */
/* Prix d'un EXCLUSIF : même pastille sombre que les pièces (règle : tout prix sur fond
   noir, jamais sur fond jaune), plus un liseré doré. Deux monnaies qui se ressemblent
   feraient épargner la mauvaise : le ⭐ le dit, l'anneau le confirme du coin de l'œil. */
.pick-price.pick-stars { box-shadow: 0 0 0 2px var(--pop-yellow); }
.pick-price { position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); font-size: 9px; font-weight: 900; color: #fff; background: var(--ink); border-radius: 999px; padding: 1px 5px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pick-owned { position: absolute; top: 2px; inset-inline-end: 2px; font-size: 11px; font-weight: 900; color: var(--ink); background: var(--pop-green); border: 2px solid var(--ink); border-radius: 999px; min-width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; }

.noscript { padding: 40vh 24px 0; text-align: center; color: var(--muted); }

@keyframes pop { 0% { transform: scale(1.7); opacity: 0; } 32% { opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes plus1 { 0% { transform: scale(.6); opacity: 0; } 25% { transform: scale(1.35); opacity: 1; } 72% { transform: scale(1); opacity: 1; } 100% { transform: scale(1); opacity: 0; } }
@keyframes fade { from { opacity: 0; } }
@keyframes sheetUp { from { transform: translateY(100%); } }
@keyframes fall { to { transform: translateY(115vh) rotate(720deg); } }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
  .decor { display: none; }
}

/* Popup suppression de compte */
.del-box { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.del-ico { font-size: 46px; line-height: 1; }
.del-warn { color: var(--text); font-weight: 700; line-height: 1.5; margin: 0; max-width: 42ch; }
.del-confirm { background: var(--pop-pink); color: var(--ink); border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); font-weight: 900; }
.del-confirm:disabled { opacity: .6; }

/* Inviter un ami depuis le salon en ligne */
.room-invite { width: 100%; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); font-weight: 800; margin-top: 6px; }
.inv-pick { display: flex; flex-direction: column; gap: 8px; }
.inv-friend { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; background: var(--panel); border: 3px solid var(--ink); border-radius: 14px; text-align: start; cursor: pointer; }
.inv-friend:active { transform: translateY(2px); }
.inv-friend .fr-name { flex: 1; }
/* « Jouer avec des amis » (lobby en ligne) : sélection multiple avant création du salon. */
.online-invite { display: block; width: 100%; max-width: 320px; margin: 8px auto 0; background: var(--panel-2); color: var(--text); border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink); font-weight: 800; }
.inv-friend .inv-check { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; border: 3px solid var(--ink); display: grid; place-items: center; font-weight: 900; font-size: 15px; color: transparent; background: var(--panel-2); }
.inv-friend.sel { border-color: var(--pop-green); background: rgba(61, 220, 132, .12); }
.inv-friend.sel .inv-check { background: var(--pop-green); color: var(--ink); }
/* Ami hors ligne : présent mais non invitable (un match en ligne se joue en direct). */
.inv-friend.off { opacity: .5; cursor: default; }
.inv-friend.off .inv-check { display: none; }
.inv-none { margin: 0 0 2px; }
.inv-go { width: 100%; margin-top: 6px; }
.inv-go[disabled] { opacity: .55; box-shadow: none; animation: none; }

/* Cloche + centre de notifications */
.tab-bell .ico-w { position: relative; overflow: visible; }
.tab-badge { position: absolute; top: -4px; inset-inline-end: -9px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px; background: var(--pop-pink); color: var(--ink); border: 2px solid var(--ink); font-size: 10px; font-weight: 900; line-height: 13px; text-align: center; }
.notif-list { display: flex; flex-direction: column; gap: 8px; }
.notif-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; color: var(--muted); font-size: 42px; padding: 18px 0; }
.notif-empty span { font-size: 14px; font-weight: 700; }
.notif-row { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 11px 13px; background: var(--panel); border: 3px solid var(--ink); border-radius: 16px; box-shadow: 0 3px 0 var(--ink); }
/* Invitation à jouer : boutons Accepter / Refuser sous le texte, pleine largeur */
.notif-act { flex-basis: 100%; display: flex; gap: 8px; margin-top: 2px; }
.notif-yes, .notif-no { flex: 1; font: inherit; font-weight: 900; font-size: 13px; padding: 9px 10px; border: 3px solid var(--ink); border-radius: 12px; box-shadow: 0 3px 0 var(--ink); cursor: pointer; }
.notif-yes { background: var(--pop-green); color: var(--ink); }
.notif-no { background: var(--panel-2); color: var(--text); }
.notif-yes:active, .notif-no:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
.notif-emo { flex: 0 0 auto; width: 38px; height: 38px; display: grid; place-items: center; font-size: 19px; border-radius: 50%; border: 2px solid var(--ink); background: var(--panel-2); }
.notif-row.n-req .notif-emo { background: var(--pop-blue); }
.notif-row.n-inv .notif-emo { background: var(--pop-purple); }
.notif-row.n-gift .notif-emo { background: var(--pop-pink); }
.notif-row.n-msg .notif-emo { background: var(--pop-green); }
.notif-txt { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; line-height: 1.35; }
.notif-txt b { font-weight: 900; }
.notif-txt small { display: block; color: var(--muted); font-size: 11px; font-weight: 700; margin-top: 2px; }
.name-input.locked { opacity: .65; cursor: default; }
.prof-lock-hint { font-size: 12px; color: var(--muted); font-weight: 600; text-align: center; line-height: 1.4; margin: 4px 0 0; }

/* ---------- Chat des parties en ligne ----------
   Dock fixe en bas à droite : #online-panel est réécrit à chaque instantané, le chat
   doit lui survivre (et surtout ne pas perdre le texte en cours de frappe). */
/* ⚠️ Le panneau de discussion en partie était une VIGNETTE flottante de 78 vw ancrée dans le
   coin : trois messages visibles, un champ de saisie écrasé, et un bloc posé de travers sur
   le jeu. C'est maintenant une BARRE pleine largeur en bas de l'écran, avec sa poignée, comme
   toutes les feuilles de l'appli. Le bouton, lui, reste dans le coin : c'est un appel, pas un
   panneau. */
.chat-dock { position: fixed; inset-inline-end: 12px; inset-inline-start: 12px; bottom: calc(env(safe-area-inset-bottom) + 12px); z-index: 28; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; pointer-events: none; }
.chat-dock > * { pointer-events: auto; }
.chat-dock[hidden] { display: none; }
.chat-fab {
  position: relative; width: 50px; height: 50px; display: grid; place-items: center;
  background: var(--panel-2); border: 3px solid var(--ink); border-radius: 50%;
  box-shadow: 0 4px 0 var(--ink); cursor: pointer;
  transition: transform .12s var(--spring), box-shadow .12s;
}
.chat-fab:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.chat-fab svg { width: 27px; height: 27px; display: block; }
.chat-fab .tab-badge { top: -5px; inset-inline-end: -5px; }
.chat-panel {
  width: 100%; max-width: 560px; margin-inline: auto;
  max-height: min(56vh, 420px); display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: 22px; box-shadow: 0 6px 0 var(--ink);
  overflow: hidden; animation: chatPop .16s var(--spring);
}
/* La poignée : quatre traits ne diraient rien, un seul trait large dit « glisse-moi ».
   Même dessin que .sheet-grip, pour que le geste s'apprenne une fois pour toutes. */
.chat-grip { flex: 0 0 auto; width: 46px; height: 5px; border-radius: 999px; background: var(--muted); opacity: .55; margin: 9px auto 3px; }
@keyframes chatPop { from { opacity: 0; transform: translateY(10px) scale(.94); } }
.chat-panel .chat-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 14px 9px; border-bottom: 3px solid var(--ink); font-size: 15px; }
.chat-close { background: none; border: 0; color: var(--text); font-size: 17px; line-height: 1; cursor: pointer; padding: 2px 4px; }
.chat-list { flex: 1; min-height: 130px; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 12px 14px; display: flex; flex-direction: column; gap: 9px; }
.chat-panel .chat-empty { margin: 0; color: var(--muted); font-size: 13px; text-align: center; }
.chat-panel .chat-msg { display: flex; align-items: baseline; gap: 6px; font-size: 13.5px; line-height: 1.35; }
/* Message expurgé par le filtre de grossièretés (rooms.php, rm_clean_msg). Volontairement
   DISCRET : pas de rouge accusateur ni d'icône d'alerte — on signale, on ne fait pas honte.
   Les astérisques disent déjà ce qu'il s'est passé, et le bip l'a fait entendre. */
.chat-panel .chat-msg.cens .chat-txt { opacity: .78; letter-spacing: .04em; }
.chat-who { font-weight: 900; color: var(--pop-yellow); flex: 0 0 auto; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-panel .chat-msg.mine .chat-who { color: var(--pop-green); }
.chat-txt { flex: 1; min-width: 0; overflow-wrap: anywhere; }   /* un mot très long ne casse pas la boîte */
/* Bouton de signalement REVELE PAR L'APPUI LONG (il n'est plus permanent : un drapeau sur
   chaque message encombrait le fil et invitait au clic accidentel). Il se pose SOUS le
   message visé, aligné a sa fin, et il est franc — on doit voir qu'on l'a fait apparaitre. */
.chat-flag {
  display: block; margin: 5px 0 0 auto; padding: 3px 10px;
  font-size: 14px; line-height: 1.2; cursor: pointer;
  background: var(--pop-pink); border: 2px solid var(--ink); border-radius: 999px;
  box-shadow: 0 2px 0 var(--ink);
  animation: flagIn .18s var(--spring);
}
.chat-flag:active { transform: translateY(2px); box-shadow: 0 0 0 var(--ink); }
@keyframes flagIn { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .chat-flag { animation: none; } }
.chat-form { display: flex; gap: 7px; align-items: center; padding: 10px 12px calc(env(safe-area-inset-bottom) * 0.4 + 10px); border-top: 3px solid var(--ink); }
.chat-input { flex: 1; min-width: 0; margin: 0; min-height: 44px; padding: 10px 13px; font: inherit; font-size: 15px; color: var(--text); background: var(--bg); border: 3px solid var(--ink); border-radius: 14px; }
.chat-input:focus { outline: none; border-color: var(--pop-purple); }
.chat-panel .chat-send { flex: 0 0 auto; min-width: 52px; min-height: 44px; padding: 0 16px; font: inherit; font-size: 14px; font-weight: 900; color: var(--ink); background: var(--pop-yellow); border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 3px 0 var(--ink); cursor: pointer; }
.chat-panel .chat-send:active { transform: translateY(2px); }

/* Recherche d'ami par pseudo + demandes envoyées */
.fr-search { display: flex; flex-direction: column; gap: 10px; }
.fr-row.fr-sent { opacity: .85; }
.fr-rel { color: var(--muted); font-weight: 700; font-size: 12px; margin-inline-start: auto; }
.fr-cancel, .fr-ask { flex: 0 0 auto; }
.fr-cancel {
  padding: 6px 11px; font: inherit; font-size: 12px; font-weight: 800; color: var(--text);
  background: var(--panel-2); border: 2px solid var(--ink); border-radius: 10px; cursor: pointer;
}
.fr-cancel:active { transform: translateY(2px); }
.fr-ask { padding: 9px 14px; font-size: 13px; margin-inline-start: auto; }

/* Profil déjà affecté à un autre joueur : visible mais inerte (on comprend pourquoi
   on ne peut pas le prendre, au lieu de le voir disparaître de la liste). */
.pick.taken { opacity: .42; cursor: default; }
.pick-taken {
  position: absolute; inset-inline-start: 50%; bottom: 2px; transform: translateX(-50%);
  font-size: 9px; font-weight: 900; letter-spacing: .3px; white-space: nowrap;
  color: #fff; background: var(--ink); border-radius: 999px; padding: 1px 6px;
}

/* Suppression d'un personnage depuis la grille — à l'opposé de l'⭐ pour ne pas se toucher. */
.prof-del {
  position: absolute; top: 4px; inset-inline-start: 6px; width: 22px; height: 22px;
  display: grid; place-items: center; color: var(--muted); opacity: .6; cursor: pointer;
  transition: opacity .12s, transform .12s var(--spring);
}
.prof-del svg { width: 17px; height: 17px; display: block; }
.prof-del:active { opacity: 1; transform: scale(.88); color: var(--pop-pink); }
.confirm-box { display: flex; flex-direction: column; gap: 14px; }
.confirm-txt { margin: 0; text-align: center; font-weight: 800; font-size: 15px; line-height: 1.4; }
.btn-danger { background: var(--pop-pink); color: var(--ink); }

/* ---------- Sélecteur d'emojis (chat) ----------
   Glissé au-dessus de la barre de saisie, pas en feuille modale : le champ reste
   visible et le pouce ne se déplace pas. Onglets en PICTOS → rien à traduire. */
.emo-btn {
  flex: 0 0 auto; width: 40px; height: 40px; display: grid; place-items: center;
  font-size: 21px; line-height: 1; cursor: pointer;
  background: var(--panel-2); border: 2px solid var(--ink); border-radius: 12px;
  transition: transform .1s var(--spring), background .12s;
}
.emo-btn:active { transform: translateY(2px); }
.emo-btn.on { background: var(--pop-yellow); }
.emo-panel {
  flex: 0 0 auto; display: flex; flex-direction: column;
  border-top: 3px solid var(--ink); background: var(--panel);
  animation: emoPop .14s var(--spring);
}
@keyframes emoPop { from { opacity: 0; transform: translateY(8px); } }
.emo-tabs {
  display: flex; gap: 2px; padding: 6px 8px 0; overflow-x: auto;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.emo-tabs::-webkit-scrollbar { display: none; }
.emo-tab {
  flex: 1 0 auto; min-width: 40px; padding: 6px 0 8px; font-size: 19px; line-height: 1;
  background: none; border: 0; border-bottom: 3px solid transparent; cursor: pointer;
  opacity: .55; transition: opacity .12s, border-color .12s;
}
.emo-tab.on { opacity: 1; border-bottom-color: var(--pop-yellow); }
/* Hauteur PLAFONNÉE : le fil de discussion doit rester visible au-dessus. */
.emo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: 2px; padding: 6px 8px calc(env(safe-area-inset-bottom) + 6px);
  max-height: min(38vh, 260px); overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.emo {
  aspect-ratio: 1; display: grid; place-items: center; font-size: 23px; line-height: 1;
  background: none; border: 0; border-radius: 10px; cursor: pointer;
  transition: transform .08s var(--spring), background .12s;
}
.emo:active { transform: scale(1.35); background: var(--panel-2); }
.emo-empty { grid-column: 1 / -1; margin: 18px 0; text-align: center; font-size: 26px; opacity: .35; }

/* Horodatage des messages : séparation par jour + heure sous chaque bulle. */
.chat-day { display: flex; align-items: center; gap: 10px; margin: 12px 4px 6px; }
.chat-day::before, .chat-day::after { content: ''; flex: 1; height: 2px; background: rgba(255, 255, 255, .1); border-radius: 2px; }
.chat-day span { flex: 0 0 auto; font-size: 11px; font-weight: 900; letter-spacing: .4px; text-transform: uppercase; color: var(--muted); }
.chat-time { display: block; margin-top: 3px; font-size: 10px; font-weight: 700; opacity: .55; font-variant-numeric: tabular-nums; }
.chat-msg.mine .chat-time { text-align: end; }

/* Chat de salon : heure discrète en bout de ligne, et grille d'emojis resserrée —
   le panneau du dock est bien plus petit que l'écran de chat des amis. */
.chat-hm { flex: 0 0 auto; font-size: 9.5px; font-weight: 700; opacity: .45; font-variant-numeric: tabular-nums; align-self: flex-end; }
.chat-dock .emo-grid { max-height: 148px; grid-template-columns: repeat(auto-fill, minmax(36px, 1fr)); }
.chat-dock .emo { font-size: 20px; }
.chat-dock .emo-tab { min-width: 34px; font-size: 17px; }
.chat-form .emo-btn { width: 44px; height: 44px; font-size: 20px; flex: 0 0 auto; }

/* ---------- Réactions aux messages ---------- */
.chat-wrap { position: relative; display: flex; flex-direction: column; }
.chat-wrap.mine { align-items: flex-end; }
.chat-wrap.them { align-items: flex-start; }
/* Les pastilles chevauchent le bas de la bulle, comme sur les messageries : elles
   appartiennent visiblement AU message et ne poussent pas le fil vers le bas. */
.chat-reacts { display: flex; flex-wrap: wrap; gap: 3px; margin: -8px 6px 4px; z-index: 1; }
/* Fond NOIR pour toutes les pastilles : un fond jaune écrasait l'emoji lui-même, qui est
   le seul contenu utile. Celle que J'AI posée se distingue par son CONTOUR, pas par son
   fond — le fond reste noir dans les deux cas. */
.reactp {
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 7px;
  font-size: 13px; line-height: 1.3; cursor: pointer; color: #fff;
  background: var(--ink); border: 2px solid var(--ink); border-radius: 999px;
  box-shadow: 0 2px 0 rgba(0, 0, 0, .45); transition: transform .1s var(--spring);
}
.reactp b { font-size: 10px; font-weight: 900; opacity: .85; }
.reactp.mine { border-color: var(--pop-yellow); }
.reactp:active { transform: scale(.9); }
/* Barre de choix rapide, posée au-dessus de la bulle sur appui long. */
/* ⚠️ flex-wrap OBLIGATOIRE : avec 6 réactions + ➕ + ✏️ + 🗑️, la barre atteint ~366 px
   et débordait d'un fil large de ~330 px, qui masque le débordement — les deux derniers
   pictos étaient purement et simplement invisibles. Elle passe sur deux rangs. */
.react-bar {
  position: absolute; bottom: 100%; z-index: 5; display: flex; flex-wrap: wrap;
  justify-content: center; max-width: min(288px, 88vw); gap: 2px; padding: 5px;
  background: var(--panel-2); border: 3px solid var(--ink); border-radius: 22px;
  box-shadow: 0 4px 0 var(--ink); animation: emoPop .13s var(--spring);
}
.chat-wrap.mine .react-bar { inset-inline-end: 0; }
.chat-wrap.them .react-bar { inset-inline-start: 0; }
.react-pick {
  width: 34px; height: 34px; display: grid; place-items: center; font-size: 19px;
  background: none; border: 0; border-radius: 50%; cursor: pointer;
  transition: transform .09s var(--spring), background .12s;
}
.react-pick:active { transform: scale(1.3); background: var(--panel); }
.react-more { font-size: 15px; opacity: .7; }
.react-sheet { display: flex; flex-direction: column; }
.react-sheet .emo-grid { max-height: 46vh; }

/* Emojis des messages : agrandis. Dans une phrase ils restent alignés sur la ligne de
   base ; seuls, le message entier passe en très grand (usage des messageries). */
.emo-in { font-size: 1.6em; line-height: 1; vertical-align: -0.22em; }
.chat-msg.emo-solo, .chat-msg.emo-solo .chat-txt { font-size: 15px; }
.chat-msg.emo-solo .emo-in { font-size: 3em; vertical-align: -0.1em; }
.chat-dock .chat-msg.emo-solo .emo-in { font-size: 2.4em; }

/* Barre de titre du sélecteur d'emojis : la croix rend la fermeture évidente. */
.emo-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 0; }
.emo-grab { width: 44px; height: 4px; border-radius: 999px; background: rgba(255, 255, 255, .18); }
.emo-close {
  width: 30px; height: 30px; display: grid; place-items: center; font-size: 15px; font-weight: 900;
  color: var(--text); background: var(--panel-2); border: 2px solid var(--ink); border-radius: 50%; cursor: pointer;
}
.emo-close:active { transform: scale(.9); }

/* ⚠️ PIÈGE RÉCURRENT DU PROJET : un élément en display:flex/grid IGNORE l'attribut
   [hidden] du navigateur — la règle de classe l'emporte. Sans ces deux gardes, poser
   `.hidden = true` en JS ne masquait RIEN : le sélecteur d'emojis et le panneau de chat
   des salons restaient affichés, leur croix semblait morte. Voir aussi .screen[hidden]. */
.emo-panel[hidden], .chat-panel[hidden] { display: none !important; }

/* ---------- Bulle de conversation réduite ----------
   La conversation survit au changement d'écran : elle se réduit ici plutôt que de se
   fermer. Placée AU-DESSUS de la barre du bas pour ne pas masquer un onglet, et sous
   les feuilles modales (z-index 30) pour ne jamais passer devant une popup ouverte. */
.chat-bubble {
  position: fixed; inset-inline-end: 12px; bottom: calc(env(safe-area-inset-bottom) + 78px);
  z-index: 27; width: 56px; height: 56px; padding: 0; display: grid; place-items: center;
  background: var(--panel-2); border: 3px solid var(--ink); border-radius: 50%;
  box-shadow: 0 5px 0 var(--ink); cursor: pointer;
  animation: bubblePop .18s var(--spring);
  transition: transform .12s var(--spring), box-shadow .12s;
}
.chat-bubble[hidden] { display: none !important; }   /* display:grid battrait [hidden] */
.chat-bubble:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--ink); }
.chat-bubble-av { display: block; width: 40px; height: 40px; pointer-events: none; }
.chat-bubble .tab-badge { top: -4px; inset-inline-end: -4px; }
@keyframes bubblePop { from { opacity: 0; transform: scale(.6) translateY(10px); } }
.chat-screen[hidden] { display: none !important; }   /* même piège : .chat-screen est en flex */

/* Message modifié / supprimé + bandeau de modification */
.chat-edited { margin-inline-start: 6px; font-size: 10px; font-style: italic; opacity: .55; }
.chat-gone { opacity: .6; font-style: italic; }
.chat-wrap.gone .chat-msg { background: transparent; border-style: dashed; color: var(--muted); }
/* Coupe la ligne : les actions du message (modifier / supprimer) forment un rang à part,
   nettement séparé des réactions — deux intentions différentes. */
.react-sep { flex-basis: 100%; height: 2px; margin: 3px 8px 1px; background: rgba(255, 255, 255, .18); border-radius: 2px; }
.chat-editbar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 14px; background: var(--panel-2); border-top: 3px solid var(--ink);
  font-size: 13px; font-weight: 800;
}
.chat-editx { background: none; border: 0; color: var(--text); font-size: 15px; font-weight: 900; cursor: pointer; padding: 2px 6px; }

/* Bascule « voir plus » de la liste d'amis : discrète, pleine largeur, sous la liste. */
.fr-more {
  display: block; width: 100%; margin: 6px 0 0; padding: 9px 12px;
  font: inherit; font-size: 13px; font-weight: 800; color: var(--muted);
  background: var(--panel); border: 2px dashed var(--ink); border-radius: 12px; cursor: pointer;
}
.fr-more:active { transform: translateY(2px); }

/* ============================================================================
   ATELIER DES JOUEURS — « Créer un personnage »
   Même largeur bornée (640) et même respiration que les autres écrans hors jeu.
   ============================================================================ */

/* ⚠️ OBLIGATOIRE : `.screen` est en position:absolute + inset:0 SANS défilement — chaque
   écran déclare le sien (#account, #shop, #lobby…). Sans cette ligne, l'atelier déborde
   de la fenêtre sans jamais pouvoir défiler : tout ce qui suit l'aperçu devient
   inatteignable, et le défaut ne se voit pas sur un écran de bureau assez haut.
   Le bas de page réserve la place de la barre d'onglets (104 px), comme #shop. */
#atelier {
  z-index: 1; overflow-y: auto;
  padding: max(env(safe-area-inset-top), 20px) 15px calc(env(safe-area-inset-bottom) + 104px);
}
.atl-wrap { display: flex; flex-direction: column; gap: 14px; max-width: 640px; margin: 0 auto; }

/* Porte d'entrée (boutique + Mon compte) : une seule ligne, tout entière cliquable. */
.atl-entry {
  display: flex; align-items: center; gap: 12px; width: 100%; margin: 10px 0 0; padding: 12px 14px;
  font: inherit; text-align: start; color: var(--text); cursor: pointer;
  background: linear-gradient(165deg, var(--panel-2), var(--panel));
  border: 3px solid var(--ink); border-radius: 18px; box-shadow: 0 4px 0 var(--ink);
}
.atl-entry:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
.atl-entry-ico { font-size: 24px; line-height: 1; }
.atl-entry-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.atl-entry-txt b { font-size: 15px; font-weight: 900; }
.atl-entry-txt small { font-size: 12px; font-weight: 700; color: var(--muted); }
.atl-entry-arw { font-size: 22px; font-weight: 900; color: var(--muted); }
.atl-entry-badge {
  padding: 3px 9px; font-size: 11px; font-weight: 900; color: var(--ink);
  background: var(--pop-yellow); border: 2px solid var(--ink); border-radius: 999px; white-space: nowrap;
}
.atl-entry-badge[hidden] { display: none; }

/* ---- Entrée de l'atelier sur PETIT écran : la pastille passe SOUS le libellé ----
   CALCUL. À 320 px, la largeur utile de .atl-entry vaut 218 px (320 moins 30 de padding
   d'écran, 6 de bordure de carte, 32 de padding de carte, 6 de bordure et 28 de padding de
   l'entrée). Quand la pastille « En attente » est visible, l'incompressible vaut 154 px :
   l'emoji 29, la pastille 81 (elle est en white-space:nowrap, donc sa largeur minimale est
   son texte entier), la flèche 8, et 36 de gouttières. Il ne reste que 64 px au libellé,
   dont le mot le plus long en fait 90 : il déborde de 26 px et mord sur la pastille.
   En russe c'est pire — la pastille y fait 121 px et il manque 63 px.

   ⚠️ `flex-wrap: wrap` ne suffirait PAS : avec `flex: 1` (base 0) sur le libellé, c'est la
   FLÈCHE qui partirait seule à la ligne, pas la pastille. Il faut une grille explicite.
   Seuil à 400 px : la pastille ne repasse au-dessus du plus long mot qu'à 346 px en
   français, 361 en néerlandais et 383 en russe — à 390 px il ne resterait que 7 px de marge. */
@media (max-width: 400px) {
  .atl-entry { display: grid; grid-template-columns: auto 1fr auto; align-items: center; }
  .atl-entry-ico { grid-area: 1 / 1 / 2 / 2; }
  .atl-entry-txt { grid-area: 1 / 2 / 2 / 3; }
  .atl-entry-arw { grid-area: 1 / 3 / 2 / 4; }
  .atl-entry-badge { grid-area: 2 / 2 / 3 / 4; justify-self: start; margin-top: 5px; }
}

/* Le mode d'emploi : la promesse faite au joueur, avant qu'il ne compose. */
.atl-steps { margin: 0; padding-inline-start: 0; list-style: none; display: flex; flex-direction: column; gap: 9px; }
.atl-steps li { display: flex; gap: 9px; font-size: 14px; font-weight: 700; line-height: 1.42; }
.atl-steps b { color: var(--pop-yellow); font-weight: 900; flex: none; }
.atl-note { margin: 4px 0 0; padding: 10px 12px; font-size: 13px; font-weight: 800; line-height: 1.4;
  background: rgba(255, 201, 60, .13); border: 2px dashed var(--pop-yellow); border-radius: 12px; }
.atl-note-soft { color: var(--muted); font-weight: 700; background: none; border-color: rgba(255, 255, 255, .18); }

/* Scène d'aperçu : la créature en grand, le dé juste à côté. */
.atl-stage { display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; }
.atl-preview {
  display: grid; place-items: center; padding: 6px;
  background: radial-gradient(circle at 50% 42%, rgba(255, 255, 255, .1), transparent 68%);
  border-radius: 50%;
}
.atl-dice { padding: 11px 18px; font-size: 15px; }

/* Rangées de pièces */
.atl-row { margin-top: 14px; }
.atl-row-t { margin-bottom: 7px; font-size: 12px; font-weight: 900; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); text-align: center; }
.atl-chips .opt { font-size: 13px; padding: 7px 13px; }

/* Champs de saisie */
.atl-field { display: flex; flex-direction: column; gap: 6px; margin-top: 16px; }
.atl-field > span { font-size: 12px; font-weight: 900; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); }
.atl-field input, .atl-field textarea {
  width: 100%; padding: 12px 14px; font: inherit; font-size: 15px; font-weight: 700; color: var(--ink);
  background: #fff; border: 3px solid var(--ink); border-radius: 14px; resize: vertical;
  /* Le corps de page porte `user-select: none` (pour que rien ne se sélectionne pendant
     une partie) : on le rend à ces deux champs, sinon poser le curseur au milieu de
     l'histoire devient pénible au doigt. */
  -webkit-user-select: text; user-select: text;
}
.atl-send { width: 100%; margin-top: 18px; }

/* Cartes d'état : en attente / publiée / refusée. La couleur porte le verdict. */
.atl-st .acct-card-b { align-items: center; text-align: center; }
.atl-st-name { margin: 0; font-size: 17px; font-weight: 900; }
.atl-st .acct-card-b p { margin: 0; font-size: 14px; font-weight: 700; line-height: 1.42; }
.atl-st-wait { border-color: var(--pop-yellow); }
.atl-st-ok { border-color: var(--pop-green); }
.atl-st-no { border-color: var(--pop-pink); }
.atl-reason {
  padding: 9px 12px; font-size: 13px !important; font-weight: 700;
  background: rgba(255, 255, 255, .08); border-radius: 12px;
}
.atl-login { align-items: center; text-align: center; }
.atl-login p { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.45; }

/* ---- Atelier : menus déroulants, encoches, composition par IA, verdict ---- */

/* Les six familles en « champs sticker » : libellé au-dessus, champ pleine largeur,
   chevron dessiné. Deux colonnes dès qu'il y a la place — six champs empilés faisaient
   une colonne interminable. */
.atl-selects { display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 14px; }
@media (min-width: 520px) { .atl-selects { grid-template-columns: 1fr 1fr; } }

.atl-fld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.atl-fld-t {
  font-size: 11px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); padding-inline-start: 3px;
}
.atl-fld-w { position: relative; display: block; }
.atl-sel {
  width: 100%; padding: 12px 38px 12px 14px;
  font: inherit; font-size: 15px; font-weight: 900; color: var(--ink);
  background: #fff; border: 3px solid var(--ink); border-radius: 15px;
  box-shadow: 0 4px 0 var(--ink);
  -webkit-appearance: none; appearance: none;
  cursor: pointer; text-overflow: ellipsis;
}
.atl-sel:focus { outline: none; border-color: var(--pop-purple); }
.atl-fld-w:active .atl-sel { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.atl-chev {
  position: absolute; inset-inline-end: 14px; top: 50%; transform: translateY(-50%);
  width: 13px; height: 9px; color: var(--ink); pointer-events: none;
}
.atl-fld-w:active .atl-chev { transform: translateY(calc(-50% + 2px)); }

.atl-tick-row { margin-top: 12px; }
.atl-tick {
  display: flex; align-items: flex-start; gap: 11px; padding: 11px 13px;
  background: rgba(255, 255, 255, .06); border: 2px solid var(--ink); border-radius: 14px; cursor: pointer;
}
.atl-tick input { flex: none; width: 22px; height: 22px; accent-color: var(--pop-green); margin: 1px 0 0; }
.atl-tick span { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.atl-tick b { font-size: 14px; font-weight: 900; }
.atl-tick small { font-size: 12px; font-weight: 700; color: var(--muted); line-height: 1.35; }

.atl-ai {
  margin-top: 16px; padding: 12px 13px;
  background: linear-gradient(150deg, rgba(160, 92, 255, .2), rgba(45, 156, 255, .14));
  border: 3px solid var(--ink); border-radius: 16px;
}
.atl-ai-t { font-size: 13px; font-weight: 900; }
.atl-ai-sub { margin: 4px 0 9px; font-size: 12px; font-weight: 700; color: var(--muted); line-height: 1.35; }
/* Zone de texte, pas un champ d'une ligne : à 180 signes on ne voyait plus le début de
   sa propre description en la tapant. Le bouton passe dessous, pleine largeur. */
#atl-ai-in {
  width: 100%; min-height: 76px; padding: 11px 13px; font: inherit; font-size: 14px; font-weight: 700;
  line-height: 1.4; color: var(--ink); background: #fff; border: 3px solid var(--ink);
  border-radius: 13px; resize: vertical;
  -webkit-user-select: text; user-select: text;
}
.atl-ai-go {
  width: 100%; margin-top: 9px; padding: 11px 15px; font: inherit; font-size: 15px; font-weight: 900;
  color: var(--ink); background: var(--pop-yellow); border: 3px solid var(--ink);
  border-radius: 13px; box-shadow: 0 3px 0 var(--ink);
}
.atl-ai-go:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.atl-ai-go[disabled] { opacity: .5; }

/* Libellé de champ + son petit dé, discret, à droite */
.atl-lbl { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.atl-rnd {
  flex: none; width: 30px; height: 30px; font-size: 14px; line-height: 1;
  background: rgba(255, 255, 255, .1); border: 2px solid var(--ink); border-radius: 10px;
  display: grid; place-items: center; opacity: .75;
}
.atl-rnd:active { transform: translateY(2px); opacity: 1; }

/* Verdict plein écran : la croix barrée du refus */
.atl-verdict .atl-cross { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.atl-verdict .atl-cross svg { width: 62%; height: 62%; overflow: visible; }
.atl-cross-o, .atl-cross-l {
  fill: none; stroke: var(--pop-pink); stroke-width: 9; stroke-linecap: round;
  filter: drop-shadow(0 2px 0 var(--ink));
}
.atl-cross-o { stroke-dasharray: 239; stroke-dashoffset: 239; animation: atlCrossO .5s .28s ease-out forwards; }
.atl-cross-l { stroke-dasharray: 77; stroke-dashoffset: 77; animation: atlCrossL .26s .74s ease-out forwards; }
@keyframes atlCrossO { to { stroke-dashoffset: 0; } }
@keyframes atlCrossL { to { stroke-dashoffset: 0; } }
/* Le personnage refusé se vide de ses couleurs pendant que la croix se trace. */
.atl-verdict.vno .reveal-mascot { animation: atlFade .5s .5s ease-out forwards; }
@keyframes atlFade { to { filter: grayscale(.85) brightness(.78); } }
.atl-vreason, .atl-vbonus {
  max-width: 320px; margin: 8px 18px 0; padding: 9px 13px; text-align: center;
  font-size: 13.5px; font-weight: 800; line-height: 1.4;
  background: rgba(0, 0, 0, .3); border-radius: 13px;
}
.atl-vbonus { color: var(--pop-yellow); }

@media (prefers-reduced-motion: reduce) {
  .atl-cross-o, .atl-cross-l { animation: none; stroke-dashoffset: 0; }
  .atl-verdict.vno .reveal-mascot { animation: none; filter: grayscale(.85) brightness(.78); }
}

/* ---- Atelier : onglets Composer / Dessiner, et la planche à dessin ---- */
.atl-modes { display: flex; gap: 8px; }
.atl-mode {
  flex: 1; padding: 11px 8px; font: inherit; font-size: 14px; font-weight: 900; color: var(--muted);
  background: var(--panel); border: 3px solid var(--ink); border-radius: 15px;
  box-shadow: 0 4px 0 var(--ink); cursor: pointer;
}
.atl-mode.on { background: var(--pop-yellow); color: var(--ink); }
.atl-mode:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }

.atl-board-wrap { display: grid; place-items: center; margin: 6px 0 2px; }
.atl-board {
  /* Fond BLANC : on dessine sur une feuille, pas sur un écran de nuit. L'encre sombre —
     la plus utile pour les contours — était presque invisible sur le fond de l'appli. */
  border: 3px solid var(--ink); border-radius: 24px; background: #fff;
  box-shadow: 0 5px 0 var(--ink);
  /* Le doigt DESSINE : il ne doit ni faire défiler la page, ni sélectionner, ni zoomer. */
  touch-action: none; -webkit-user-select: none; user-select: none; cursor: crosshair;
}
/* La palette d'encres est plus fournie que celle du corps : pastilles resserrées. */
.atl-inks .swatch { width: 34px; height: 34px; }
.atl-w { display: grid; place-items: center; min-width: 46px; }
.atl-wdot { display: block; background: currentColor; border-radius: 50%; }
.atl-erase.on { background: var(--pop-pink); color: var(--ink); }
/* Mot de l'équipe accompagnant une publication : chaleureux, pas un motif de refus. */
.atl-word { background: rgba(61, 220, 132, .16) !important; }
.atl-vword { color: var(--pop-green); }
/* Confirmation avant envoi d'une proposition */
.atl-confirm { display: flex; flex-direction: column; gap: 10px; text-align: center; }
.atl-confirm p { margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.45; }
.atl-confirm-name { font-size: 19px !important; font-weight: 900 !important; }
.atl-confirm-acts { display: flex; gap: 10px; margin-top: 6px; }
.atl-confirm-acts .btn { flex: 1; padding: 13px 10px; font-size: 15px; }

/* Multiplicateur — la vignette ne porte plus qu'un éclair si le personnage est CHOISI
   (169 encadrés dans la grille la rendaient illisible). Le chiffre vit dans la fiche. */
.shop-item { position: relative; }
.shop-mult {
  position: absolute; top: 6px; inset-inline-end: 6px; z-index: 2;
  display: grid; place-items: center; width: 24px; height: 24px; font-size: 13px; line-height: 1;
  background: var(--pop-green); border: 2px solid var(--ink); border-radius: 8px; pointer-events: none;
}

/* Fiche du personnage : l'encadré TOUT EN HAUT À DROITE DE LA FEUILLE. Il était posé
   sur la scène, où il chevauchait la mascotte et le badge de catégorie. La feuille défile :
   `position: sticky` le garde visible en haut pendant qu'on lit l'histoire. */
.sheet { position: relative; }
.ms-mult {
  position: sticky; top: 0; float: inline-end; margin: -4px -4px 0 0; z-index: 5;
  display: flex; flex-direction: column; align-items: center; line-height: 1;
  padding: 5px 9px; background: rgba(36, 26, 58, .78); border: 2px solid var(--ink); border-radius: 11px;
}
.ms-mult small { font-size: 8px; font-weight: 900; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.ms-mult b { font-size: 14px; font-weight: 900; color: var(--pop-yellow); font-variant-numeric: tabular-nums; }

/* « Choisir comme multiplicateur », sous le prix. */
.ms-mult-pick {
  width: 100%; margin-top: 10px; padding: 11px 14px;
  font: inherit; font-size: 14.5px; font-weight: 900; color: var(--ink);
  background: var(--pop-yellow); border: 3px solid var(--ink); border-radius: 14px;
  box-shadow: 0 4px 0 var(--ink); cursor: pointer;
}
.ms-mult-pick:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.ms-mult-pick.on { background: var(--pop-green); }
.ms-mult-pick[disabled] { opacity: .55; cursor: default; box-shadow: 0 4px 0 var(--ink); }
.ms-mult-pick.on[disabled] { opacity: 1; }

/* ════════════════════════ CLANS ════════════════════════
   ⚠️ `#clan` DOIT déclarer son propre défilement. `body` est en position:fixed +
   overflow:hidden et `.screen` en position:absolute; inset:0 : le seul conteneur qui défile
   est l'écran lui-même. Livré sans cette règle, l'atelier était impossible à faire défiler,
   et rien de ce qui suivait le premier écran n'était atteignable. */
#clan {
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 14px 15px calc(env(safe-area-inset-bottom) + 104px);
  max-width: 640px; margin: 0 auto;
}
#clan input, #clan textarea { user-select: text; }

/* ── TOUT L'ÉCRAN CLAN EST NOIR ──────────────────────────────────────────────
   Demandé le 07/08. Ce n'est pas qu'une question de goût : le violet des panneaux
   (--panel) est très proche du fond violet de l'appli (--bg), si bien qu'une carte de clan
   se distinguait à peine de la page, et qu'on ne repérait plus le sien dans la liste. Sur
   noir, chaque carte se détache franchement et le contour sticker reprend son rôle.

   ⚠️ Une seule variable à changer pour toute la page, plutôt que trente règles retouchées
   une à une : le jour où l'on veut revenir au violet, ou passer à autre chose, il n'y a
   qu'un endroit à toucher, et rien ne peut rester en arrière.
   ⚠️ `--panel-2` sert de « noir un ton au-dessus » : sur du noir pur, deux surfaces
   collées l'une à l'autre deviennent une seule tache, et les cartes de combat amical
   disparaîtraient dans le fil. */
#clan, .sheet.clan-sheet {
  --bg: #08060f;        /* fond des champs de saisie */
  --panel: #0d0a18;     /* cartes, boutons, fil de discussion */
  --panel-2: #17121f;   /* un ton au-dessus : deux surfaces collées restent distinctes */
}
#clan { background: #08060f; }

.clan-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.clan-titre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ⚠️ Les trois gestes du clan vivent EN HAUT À DROITE. « Quitter » était sous le champ de
   saisie et le chevauchait : on croyait écrire à son clan et on le quittait. Un geste
   irréversible ne se met jamais sous le pouce d'un geste courant. */
.clan-tools { display: flex; gap: 7px; flex: 0 0 auto; }
.clan-ic {
  width: 44px; height: 44px;            /* cible tactile pleine, comme partout ailleurs */
  display: grid; place-items: center; font-size: 19px;
  background: var(--panel); color: var(--text);
  border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 3px 0 var(--ink);
  cursor: pointer; flex: 0 0 auto;
}
.clan-ic:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.clan-ic.danger { background: var(--pop-pink); color: var(--ink); }
.clan-loupe {
  width: 44px; height: 44px; display: grid; place-items: center; font-size: 19px;
  background: var(--pop-yellow); color: var(--ink);
  border: 3px solid var(--ink); border-radius: 14px; box-shadow: 0 3px 0 var(--ink);
  cursor: pointer; flex: 0 0 auto;
}
.clan-loupe:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.clan-searchbar { display: flex; gap: 8px; margin: 10px 0; }
.clan-searchbar[hidden] { display: none !important; }   /* display:flex bat l'attribut hidden */
.clan-searchbar input { flex: 1; min-width: 0; }

.clan-load, .clan-dim { color: var(--muted); font-weight: 700; font-size: 13px; text-align: center; margin: 10px 0; }
.clan-err { color: var(--pop-pink); font-weight: 800; text-align: center; margin: 12px 0; }
.clan-sub { font-weight: 900; font-size: 15px; margin: 16px 0 8px; }
.clan-block { background: var(--panel); border: 3px solid var(--ink); border-radius: 18px; padding: 12px; margin: 12px 0; }
.clan-meta { color: var(--muted); font-weight: 800; font-size: 13px; margin-bottom: 6px; line-height: 1.5; }
.clan-descr { display: block; font-size: 13px; font-weight: 700; margin: 2px 0; }
.clan-descr-big { font-size: 14px; font-weight: 700; margin: 6px 0 4px; line-height: 1.45; }
.clan-mine-note {
  background: var(--panel2); border: 3px dashed var(--ink); border-radius: 14px;
  padding: 9px 12px; font-size: 13px; font-weight: 800; margin: 10px 0;
}

.clan-banned {
  background: var(--pop-pink); color: var(--ink); border: 3px solid var(--ink);
  border-radius: 14px; box-shadow: 0 3px 0 var(--ink);
  font-weight: 900; text-align: center; padding: 10px 12px; margin: 10px 0;
}

.clan-row { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 2px solid rgba(255,255,255,.07); }
.clan-row-txt { flex: 1; min-width: 0; }
.clan-row-txt b { display: block; font-size: 15px; }
.clan-row-acts { display: flex; gap: 6px; flex: 0 0 auto; }
.clan-lock { font-size: 18px; opacity: .7; }

.clan-memlist { display: flex; flex-direction: column; gap: 4px; }
.clan-mem { display: flex; align-items: center; gap: 9px; padding: 6px 2px; }
.clan-mem-b { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.clan-mem-n { font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clan-mem-c { font-size: 11.5px; font-weight: 800; color: var(--muted); }
.clan-crown { font-size: 13px; }
.clan-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); border: 2px solid var(--ink); flex: 0 0 auto; }
.clan-dot.on { background: #3ddc84; }
.cl-kick { flex: 0 0 auto; padding: 4px 9px; }

/* La discussion : plus haute qu'au premier jet, qui donnait une bande étroite entre deux
   titres. Un fil de discussion doit pouvoir montrer plusieurs échanges d'un coup, sinon on
   passe son temps à faire défiler pour suivre une conversation de trois lignes. */
.clan-msgs {
  min-height: 200px; max-height: 58vh;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 16px;
  padding: 12px; display: flex; flex-direction: column; gap: 8px;
}
.clan-msg { font-size: 14px; line-height: 1.35; word-break: break-word; }
.clan-msg b { color: var(--pop-yellow); }
.clan-msg.cens span { opacity: .8; font-style: italic; }
.clan-gone, .clan-edited { color: var(--muted); font-style: italic; font-size: 12px; }
.clan-msg.del { opacity: .65; }
.clan-reacts { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 5px; }
.clan-react {
  font: inherit; font-size: 12px; font-weight: 800; line-height: 1;
  padding: 4px 8px; background: var(--panel-2); color: var(--text);
  border: 2px solid var(--ink); border-radius: 999px; cursor: pointer;
}
.clan-react.on { background: var(--pop-yellow); color: var(--ink); }
/* Citation du message dans la feuille d'actions : sans elle, on ne sait plus lequel on
   s'apprête à supprimer, et une suppression sans certitude est une suppression regrettée. */
.clan-quote {
  background: var(--panel); border: 3px solid var(--ink); border-radius: 14px;
  padding: 10px 12px; font-size: 13.5px; line-height: 1.4; margin: 0 0 10px; word-break: break-word;
}
.clan-quote b { color: var(--pop-yellow); }
.clan-emorow { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.clan-emopick {
  flex: 1 1 auto; min-width: 44px; min-height: 44px; font-size: 21px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 13px;
  box-shadow: 0 3px 0 var(--ink); cursor: pointer;
}
.clan-emopick:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }
.clan-say { align-items: center; }
.clan-say .emo-btn { width: 44px; height: 44px; font-size: 20px; flex: 0 0 auto; }

/* Une annonce de combat est une CARTE avec un bouton, pas une ligne de texte : on doit
   pouvoir la rejoindre d'un geste, sans chercher où taper. */
.clan-duelcard {
  background: var(--panel2); border: 3px solid var(--ink); border-radius: 14px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 6px;
}
.clan-duel-t { font-weight: 900; font-size: 14px; }
.clan-duel-s { font-size: 12.5px; font-weight: 800; color: var(--muted); }
.clan-duelcard .btn2 { align-self: flex-start; }

.clan-say { margin-top: 10px; }
/* Les deux gestes du bas : proposer un combat, et aller voir ailleurs. Côte à côte au-delà
   de 380 px, empilés en dessous — deux boutons écrasés sur un petit téléphone donnent deux
   libellés coupés et personne ne sait plus lequel fait quoi. */
.clan-bottom { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.clan-bottom .chip-btn { flex: 1 1 150px; }
.chip-btn.clan-duel { margin-top: 0; }
.chip-btn.danger { background: var(--pop-pink); color: var(--ink); }

/* Formulaire partagé par la fondation et les réglages : mêmes champs, un seul écran. */
.clan-form { display: flex; flex-direction: column; gap: 6px; }
.clan-lbl { font-weight: 900; font-size: 13px; margin-top: 8px; }
.clan-ta { resize: vertical; min-height: 62px; font-family: inherit; }
.clan-modes { display: flex; gap: 7px; flex-wrap: wrap; }
.clan-mbtn {
  flex: 1 1 auto; min-height: 44px; padding: 8px 12px;
  background: var(--panel); color: var(--text);
  border: 3px solid var(--ink); border-radius: 13px; box-shadow: 0 3px 0 var(--ink);
  font: inherit; font-weight: 900; font-size: 13px; cursor: pointer;
}
.clan-mbtn.on { background: var(--pop-yellow); color: var(--ink); }
.clan-mbtn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink); }

/* Les feuilles ouvertes DEPUIS le clan suivent la même règle : membres, réglages et combat
   amical font partie de l'écran, et une feuille violette surgissant d'une page noire se
   lirait comme un morceau d'une autre appli.
   ⚠️ On ne repeint PAS leur fond : `.sheet` est un dégradé de --panel-2 vers --panel, et
   ces deux variables sont déjà redéfinies plus haut. Poser une couleur plate ici aurait
   effacé le dégradé, donc le relief qui distingue une feuille de la page. */

.fr-tools { display: flex; gap: 8px; flex-wrap: wrap; }

/* Partage d'invitation : les moyens sont EMPILÉS et pleine largeur. Côte à côte, quatre
   boutons à libellé variable (« WhatsApp », « Par e-mail »…) se coupent dès qu'une langue
   est plus bavarde que le français, et on ne sait plus lequel fait quoi. */
.fs-code {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--panel); border: 3px solid var(--ink); border-radius: 14px;
  padding: 10px 14px; margin-bottom: 4px;
}
.fs-code b { font-size: 22px; letter-spacing: .12em; font-variant-numeric: tabular-nums; }
.fs-acts { display: flex; flex-direction: column; gap: 8px; }
.fs-acts .btn { width: 100%; text-align: center; text-decoration: none; }
.fs-fallback { margin-top: 10px; font-size: 13px; text-align: start; }

/* Réglages d'une partie EN LIGNE : même habillage que le bloc local, pour qu'un joueur
   n'ait rien à réapprendre en passant d'un mode à l'autre. */
#net-opts { margin: 6px 0 10px; }
#net-opts .section-title { margin-top: 10px; }
.net-maxrow { gap: 6px; }
.net-maxrow .opt { min-width: 46px; min-height: 44px; }
.fr-tools .chip-btn { flex: 1 1 auto; }
