/* === Reset === */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg:      #111110;
  --surface: #1a1917;
  --border:  #2a2a28;
  --accent:  #5DCAA5;
  --text:    #e8e5df;
  --dim:     #888;
  --danger:  #c0392b;
  --radius:  12px;
  --font:    'Courier New', Courier, monospace;
}

html, body {
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  overflow: hidden;
  touch-action: none;
  /* No pull-to-refresh, no overscroll glow, and no chaining a scroll from an inner
     list out to the viewport. In the installed app there is no address bar to absorb
     a downward drag, so the browser is quicker to read one as "reload the page" —
     and the moment it does, it takes the gesture away from us (pointercancel), which
     is exactly what dropped a hero mid-drag. Nothing here ever wants to overscroll. */
  overscroll-behavior: none;
}

/* Subtle grid background (matches main site) */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.018) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.018) 1px, transparent 1px);
  background-size: 44px 44px;
  pointer-events: none;
  z-index: 0;
}
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background: radial-gradient(ellipse 80% 60% at 50% 50%, transparent, #111110 80%);
  pointer-events: none;
  z-index: 0;
}

/* === Lang Toggle === */
#lang-toggle {
  position: fixed;
  top: max(14px, calc(env(safe-area-inset-top, 0px) + 6px));
  right: max(16px, calc(env(safe-area-inset-right, 0px) + 8px));
  z-index: 100;
  display: flex;
  gap: 4px;
}
.global-user-bar #lang-toggle {
  position: static;
  margin-left: auto;
}
.lang-btn {
  background: none;
  border: 0.5px solid var(--border);
  color: var(--dim);
  font-family: var(--font);
  font-size: 10px;
  letter-spacing: 0.14em;
  padding: 5px 11px;
  border-radius: 5px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.lang-btn:hover:not(.active) { color: var(--text); border-color: var(--dim); }
.lang-btn.active { color: var(--accent); border-color: var(--accent); }

/* === Global currency bar === */
.global-user-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface);
  border-bottom: 0.5px solid var(--border);
  padding-top: max(8px, env(safe-area-inset-top, 0px));
  padding-bottom: 8px;
  padding-left: max(14px, calc(env(safe-area-inset-left, 0px) + 4px));
  padding-right: max(14px, calc(env(safe-area-inset-right, 0px) + 4px));
  font-size: 12px;
  letter-spacing: 0.06em;
}

/* Back arrow — hidden by default, shown via JS when not on the root screen */
#btnNavBack {
  display: none;
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  padding: 4px 6px;
  margin-right: -4px; /* compensate so gap stays visually even */
  border-radius: 6px;
  cursor: pointer;
  transition: color 0.15s, background 0.1s;
}
#btnNavBack:hover { color: var(--text); background: rgba(255,255,255,0.06); }

/* Username shrinks first when the bar is tight; fixed elements stay their size */
#menuUsername {
  color: var(--accent);
  font-weight: 700;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.global-user-bar .currency  { flex-shrink: 0; }
.global-user-bar .btn-small { flex-shrink: 0; }
.global-user-bar #lang-toggle { flex-shrink: 0; }

/* On narrow screens hide the logout button — it lives in Settings on these devices */
@media (max-width: 460px) {
  #btnLogout { display: none; }
}

/* On very narrow screens hide the username entirely so the other controls still fit */
@media (max-width: 400px) {
  #menuUsername { display: none; }
  .global-user-bar { gap: 8px; }
}

/* === Screens === */
.screen {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 1;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding-top: max(58px, calc(env(safe-area-inset-top, 0px) + 46px));
  padding-bottom: max(24px, calc(env(safe-area-inset-bottom, 0px) + 12px));
  padding-left: 20px;
  padding-right: 20px;
  overflow-y: auto;
}
.screen.active { display: flex; }

/* === Logo === */
.logo {
  font-size: 1.6rem;
  font-weight: 900;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 24px rgba(93,202,165,0.35);
  margin-bottom: 28px;
}

/* === Screen headings === */
.screen > h2,
.heroes-header > h2 {          /* heroes title lives inside the sticky header wrapper */
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--dim);
  margin-bottom: 22px;
}
.heroes-header > h2 { margin-bottom: 10px; }   /* tighter inside the compact sticky header */

/* === Buttons === */
.btn-primary, .btn-secondary, .btn-small, .btn-back {
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background 0.15s, box-shadow 0.2s, transform 0.1s, color 0.15s, border-color 0.15s;
}

.btn-primary {
  background: transparent;
  border: 0.5px solid var(--accent);
  color: var(--accent);
  font-size: 13px;
  padding: 12px 28px;
}
.btn-primary:hover  { background: rgba(93,202,165,0.09); box-shadow: 0 0 20px rgba(93,202,165,0.12); }
.btn-primary:active { background: rgba(93,202,165,0.18); transform: scale(0.96); }

/* Destructive action button (e.g. confirm "remove friend"). */
.btn-danger {
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background 0.15s, box-shadow 0.2s, transform 0.1s, color 0.15s, border-color 0.15s;
  background: transparent;
  border: 0.5px solid #e05555;
  color: #e05555;
  font-size: 13px;
  padding: 12px 28px;
}
.btn-danger:hover  { background: rgba(224,85,85,0.10); box-shadow: 0 0 20px rgba(224,85,85,0.12); }
.btn-danger:active { background: rgba(224,85,85,0.20); transform: scale(0.96); }
.btn-danger:disabled { opacity: 0.35; cursor: not-allowed; box-shadow: none; }

/* === Danger zone (account deletion, last card in the settings) === */
/* Folded shut and quiet: the one action here destroys everything the player built. It
   must be findable — Google Play requires it — without ever inviting a stray tap. */
.danger-zone > summary {
  cursor: pointer;
  list-style: none;              /* no disclosure marker — it rendered as a stray dot */
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #e05555;
  padding: 2px 0;
}
.danger-zone > summary::-webkit-details-marker { display: none; }
.danger-zone > summary::marker { content: ""; }
.danger-zone > summary:hover { color: #ff6b6b; }
.danger-zone[open] { border-color: rgba(224,85,85,0.35); }
.danger-warn {
  margin: 16px 0 10px;
  font-size: 12px;
  line-height: 1.7;
  color: #e0857f;
}
/* The two buttons in here are smaller than the ones elsewhere on purpose: this is not an
   action anyone should be drawn towards. Centred in the card rather than stretched across it. */
.danger-zone .btn-danger {
  display: block;
  width: auto;
  margin: 0 auto;
  padding: 6px 18px;
  line-height: 1.35;             /* the label brought its own leading on top of the padding */
  font-size: 11px;
  letter-spacing: 0.12em;
  text-indent: 0.12em;           /* letter-spacing adds a gap AFTER the last letter, which
                                    shifts the label left of centre — this pays it back */
}
.del-code-input {
  width: 100%;
  text-align: center;
  font-family: var(--font);
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 0.5em;
  text-indent: 0.5em;          /* centres the text despite the trailing letter-space */
  padding: 12px 8px;
  border-radius: var(--radius);
  border: 0.5px solid var(--border);
  background: rgba(0,0,0,0.25);
  color: var(--text);
}
.del-code-input:focus { outline: none; border-color: #e05555; }

.btn-secondary {
  background: transparent;
  border: 0.5px solid var(--border);
  color: var(--dim);
  font-size: 13px;
  padding: 12px 28px;
}
.btn-secondary:hover  { border-color: var(--dim); color: var(--text); }
.btn-secondary:active { transform: scale(0.96); }

.btn-small {
  background: transparent;
  border: 0.5px solid var(--border);
  color: var(--dim);
  font-size: 10px;
  padding: 5px 11px;
  border-radius: 5px;
}
.btn-small:hover { border-color: var(--dim); color: var(--text); }

.btn-back {
  background: transparent;
  border: none;
  color: var(--dim);
  font-size: 12px;
  padding: 8px 0;
  margin-top: 32px;
  letter-spacing: 0.12em;
}
.btn-back:hover { color: var(--text); }

/* === Main Nav === */
.main-nav {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 280px;
}
.main-nav .btn-primary { text-align: center; }

/* Menu notifier — a glowing pulse on a button that needs attention
   (e.g. the Friends button when there are new friend requests). */
@keyframes notifyPulse {
  0%, 100% { box-shadow: 0 0 4px rgba(93, 202, 165, 0.30); border-color: var(--accent); }
  50%      { box-shadow: 0 0 18px 3px rgba(93, 202, 165, 0.80); border-color: #8ff0cf; }
}
.notify-pulse { animation: notifyPulse 1.6s ease-in-out infinite; }

.currency { font-size: 12px; }

/* === Mode Cards === */
.mode-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin: 8px 0;
}
.mode-card {
  position: relative;   /* anchor for the corner lock ribbon */
  overflow: hidden;     /* clips the diagonal ribbon to the rounded corner */
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 22px;
  padding: 24px 20px;
  width: 230px;
  text-align: center;
  transition: border-color 0.25s, box-shadow 0.25s;
  display: flex;
  flex-direction: column;
}
.mode-card:hover {
  border-color: rgba(93,202,165,0.35);
  box-shadow: 0 0 24px rgba(93,202,165,0.07);
}

/* Locked mode (Endless/PVP before campaign level 10 is cleared) ─────────────── */
.mode-card.locked {
  opacity: 0.82;
  border-color: rgba(224,83,59,0.35);
}
.mode-card.locked:hover {
  border-color: rgba(224,83,59,0.5);
  box-shadow: 0 0 24px rgba(224,83,59,0.08);
}
/* Diagonal "🔒 Ab Level 10" band pinned to the top-right corner — hard to miss. */
.mode-lock-ribbon {
  position: absolute;
  top: 16px;
  right: -42px;
  transform: rotate(45deg);
  background: linear-gradient(90deg, #e0533b 0%, #f0803a 100%);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 5px 44px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.45);
  text-shadow: 0 1px 1px rgba(0,0,0,0.35);
  z-index: 3;
  pointer-events: none;
}
/* Higher specificity than `.mode-card p` so its sizing/colour actually win. */
.mode-card p.mode-lock-note {
  color: #f0803a;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.45;
  min-height: 0;
  margin-bottom: 14px;
}
/* Ribbon + note only show while the card carries .locked. */
.mode-card:not(.locked) .mode-lock-ribbon,
.mode-card:not(.locked) .mode-lock-note { display: none; }
.mode-card h3 {
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
  font-weight: 700;
}
.mode-card p {
  color: var(--dim);
  margin-bottom: 18px;
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.55;
  /* Reserve three lines so every card's body starts at the same y — that is what
     lets the Starten buttons line up with the middle PVP variant below. */
  min-height: calc(3 * 1.55em);
}
/* Fills the space the PVP card gives to its three variant buttons, so a centred
   button here sits exactly on the middle (v3) variant. */
.mode-action {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── PVP matchmaking queue ─────────────────────────────────────────── */
.pvp-queue-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  margin: 48px 0 40px;
}
.pvp-spinner {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 4px solid rgba(93,202,165,0.18);
  border-top-color: var(--accent);
  animation: pvpSpin 0.9s linear infinite;
}
@keyframes pvpSpin { to { transform: rotate(360deg); } }

/* === Level Grid === */
.level-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin: 8px 0;
}
.level-btn {
  width: 54px; height: 54px;
  border-radius: 50%;
  cursor: pointer;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  background: var(--surface);
  border: 0.5px solid var(--border);
  color: var(--dim);
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.level-btn.unlocked  { border-color: var(--accent); color: var(--accent); }
.level-btn.unlocked:hover { background: rgba(93,202,165,0.08); }
.level-btn.completed { border-color: rgba(93,202,165,0.4); color: var(--accent); background: rgba(93,202,165,0.06); }
.level-btn.locked    { opacity: 0.25; cursor: not-allowed; }

/* === Campaign world map === */
/* One zone (10 levels) per page as a winding trail of nodes, grouped into acts.
   Node positions are computed in campaign.js (sine serpentine); the SVG links and the
   per-zone theme tint are set inline from there. Built to scale to 1000+ levels: only
   ~10 nodes render at a time. */
/* Fills the remaining screen height (a flex child of .screen) so a whole zone fits the
   viewport with no scrolling; the path box below grows to take the leftover space. */
.cmap { width: 100%; max-width: 460px; margin: 2px auto 0; flex: 1 1 auto; min-height: 0;
        display: flex; flex-direction: column; }
.cmap-header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 14px; margin-bottom: 2px; flex: 0 0 auto;
  border-radius: 16px;
  background: var(--surface);           /* overridden inline with the zone's theme tint */
  border: 1px solid var(--border);
}
.cmap-titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmap-act   { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.cmap-realm { font-size: 18px; font-weight: 800; color: #fff; text-shadow: 0 1px 6px rgba(0,0,0,.7); }
.cmap-diff  { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
.cmap-flames { font-size: 14px; letter-spacing: 1px; filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.cmap-tough  { font-size: 9px; font-weight: 700; letter-spacing: .05em; color: #ffce7a;
               background: rgba(0,0,0,.4); padding: 2px 7px; border-radius: 7px; white-space: nowrap; }

/* flex:1 → the path box takes whatever height is left; node top/left are % of it. */
.cmap-path { position: relative; flex: 1 1 auto; min-height: 0; width: 100%; margin: 2px 0; }
.cmap-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }

.cmap-node {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  /* Size comes from --cmap-node, computed per render from the measured path height so a
     node is always smaller than the vertical gap → circles never overlap (see _sizeNodes).
     The fallbacks apply only for the first paint before JS sizes them. */
  width: var(--cmap-node, 46px); height: var(--cmap-node, 46px); border-radius: 50%;
  font-family: var(--font); font-weight: 800; font-size: calc(var(--cmap-node, 46px) * .34);
  /* Opaque background so the connector line stays hidden behind the disc and only shows in
     the gaps between circles — the level number is never struck through. */
  border: 2px solid var(--border); background: var(--surface); color: var(--dim);
  cursor: pointer; z-index: 2;
  transition: transform .1s, border-color .15s, box-shadow .15s, background .15s;
}
.cmap-node:active { transform: translate(-50%, -50%) scale(.9); }
.cmap-node.boss      { width: var(--cmap-boss, 54px); height: var(--cmap-boss, 54px); font-size: calc(var(--cmap-boss, 54px) * .30); }
.cmap-node.unlocked  { border-color: var(--accent); color: var(--accent); }
.cmap-node.unlocked:hover { background: #17231e; }
.cmap-node.completed { border-color: var(--accent); color: var(--accent); background: #1a2722; }
.cmap-node.locked    { opacity: .4; cursor: not-allowed; border-style: dashed; }
.cmap-node.current   { animation: cmapPulse 1.7s ease-in-out infinite; }
@keyframes cmapPulse {
  0%,100% { box-shadow: 0 0 0 3px rgba(93,202,165,.30), 0 0 12px rgba(93,202,165,.35); }
  50%     { box-shadow: 0 0 0 4px rgba(93,202,165,.55), 0 0 22px rgba(93,202,165,.6); }
}
.cmap-node .cmap-stars { position: absolute; bottom: -13px; font-size: 10px; letter-spacing: 1px; color: #f7c94f; white-space: nowrap; }
.cmap-node .cmap-crown { position: absolute; top: -13px; font-size: 13px; white-space: nowrap; }

.cmap-nav { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 8px; flex: 0 0 auto; }
.cmap-navbtn { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border);
               background: var(--surface); color: var(--text); font-size: 15px; cursor: pointer; }
.cmap-navbtn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.cmap-navbtn:disabled { opacity: .3; cursor: default; }
.cmap-zonelabel { font-size: 12px; color: var(--muted); min-width: 104px; text-align: center; }
.cmap-jump { display: block; margin: 8px auto 0; padding: 7px 16px; border-radius: 20px; flex: 0 0 auto;
             border: 1px solid var(--accent); background: transparent; color: var(--accent);
             font-size: 12px; font-weight: 700; cursor: pointer; }
.cmap-jump:hover { background: rgba(93,202,165,.1); }
/* Keep the button's space reserved (not display:none) so showing/hiding it never
   shifts the nav row above it. */
.cmap-jump.hidden { visibility: hidden; }

/* === Hero Grid === */
/* The whole header (title + formation + hint) stays visible while the collection
   scrolls, so there's always a drop target within reach — essential for placing a
   hero from far down the list on mobile. Pinned just below the fixed global user
   bar; align-self + negative margins make the opaque backdrop span full width so
   hero cards passing under stay hidden. */
.heroes-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: sticky;
  top: 0;                        /* pinned to the very top; the opaque backdrop below
                                    fills behind the fixed user bar (bar is z-index 50) */
  z-index: 30;
  align-self: stretch;
  background: var(--bg);
  margin: 0 -20px 14px;
  /* Top padding clears the fixed user bar (moved here from .screen's padding-top, so
     the header's opaque box spans the full top region and pins seamlessly at 0 —
     otherwise a gap = paddingTop − barHeight would show above it once stuck). */
  padding: max(58px, calc(env(safe-area-inset-top, 0px) + 46px)) 20px 12px;
  box-shadow: 0 6px 14px -8px rgba(0,0,0,0.7);
}
/* The header now provides the top clearance, so the screen itself must not add it. */
#screenHeroes { padding-top: 0; }

.team-slots {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 12px;
}
.team-slot {
  width: 58px; height: 58px;
  border: 0.5px dashed rgba(93,202,165,0.4);
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  color: rgba(93,202,165,0.4);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.team-slot:hover { border-color: var(--accent); color: var(--accent); }
.team-slot.filled   { border-style: solid; border-color: rgba(93,202,165,0.5); }
.team-slot.active   { border-style: solid; border-color: var(--accent) !important;
                      box-shadow: 0 0 14px rgba(93,202,165,0.35); }
.team-slot.slot-lead  { border-color: rgba(93,202,165,0.6); }
.team-slot.slot-locked { opacity: 0.2; pointer-events: none; cursor: default; }

/* Formation visual order: far-left | left | CENTER | right | far-right */
.team-slot[data-slot="3"] { order: 1; }
.team-slot[data-slot="1"] { order: 2; }
.team-slot[data-slot="0"] { order: 3; width: 66px; height: 66px; } /* lead slot slightly larger */
.team-slot[data-slot="2"] { order: 4; }
.team-slot[data-slot="4"] { order: 5; }

/* Hint the arc the team actually flies in: the lead sits a little ahead, the outer pair
   a little behind. Mirrors the dy offsets of FORMATION in player.js (-55 / -25 / +5) but
   scaled right down — enough to read as a formation, not so much that the row stops
   reading as a row. Purely visual: the slots keep their normal hit areas. */
.team-slots { align-items: center; }
.team-slot[data-slot="0"] { transform: translateY(-7px); }
.team-slot[data-slot="3"],
.team-slot[data-slot="4"] { transform: translateY(7px); }

.team-slot-inner  { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.team-slot-swatch { width: 30px; height: 30px; border-radius: 6px; }
.team-slot-label  { font-size: 8px; font-weight: 700; color: #c8c5bf;
                    letter-spacing: 0.02em; text-align: center; max-width: 62px;
                    overflow: hidden; white-space: nowrap; }

.hero-team-badge {
  position: absolute; bottom: -3px; right: -3px;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--accent); color: #111;
  font-size: 9px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 2px #111;
}

.team-hint { font-size: 11px; color: #555; text-align: center;
             letter-spacing: 0.06em; margin: -6px 0 6px; }

.team-save-indicator {
  font-size: 11px; letter-spacing: 0.1em; color: var(--accent);
  text-align: center; transition: opacity 0.4s;
  min-height: 18px;
}
.team-save-indicator.hidden { opacity: 0; pointer-events: none; }

/* === Drag & drop formation editing === */
/* Floating element that follows the pointer while dragging a hero. */
.drag-ghost {
  position: fixed; left: 0; top: 0;
  width: 54px; height: 54px;
  border-radius: 10px;
  overflow: hidden;
  pointer-events: none;               /* so elementFromPoint sees the slot underneath */
  z-index: 9999;
  opacity: 0.92;
  box-shadow: 0 8px 22px rgba(0,0,0,0.55);
  transform: translate(-50%, -60%);
  will-change: transform;
}
.drag-ghost img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Slot currently under the pointer and eligible to receive the drop. */
.team-slot.drop-target {
  border-style: solid !important;
  border-color: var(--accent) !important;
  box-shadow: 0 0 16px rgba(93,202,165,0.5);
  transform: scale(1.06);
}
/* Dragging a hero away from every slot will remove it — dim the formation to hint that. */
.team-slots.dnd-removing .team-slot.filled { opacity: 0.45; }

/* Portrait <img>s must not swallow the drag gesture: without this the browser's
   native image-drag starts when you grab a hero by its picture, hijacking our
   pointer sequence (grabbing the text worked, the image did not). pointer-events:
   none routes the gesture to the parent card/slot (hit-testing uses .closest). */
.hero-card img,
.team-slot img { pointer-events: none; -webkit-user-drag: none; user-select: none; }

.dnd-origin { opacity: 0.35; }        /* the card/slot the hero is being dragged from */
.team-slot.filled { cursor: grab; }
body.dnd-active { cursor: grabbing; user-select: none; -webkit-user-select: none; }
body.dnd-active .team-slot,
body.dnd-active .hero-card { cursor: grabbing; }
/* Freeze the collection while a hero is "in hand" so the drag can't scroll the
   list out from under the pointer (belt-and-suspenders alongside preventDefault). */
body.dnd-active #screenHeroes { overflow: hidden; touch-action: none; }

.hero-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
.hero-card {
  position: relative;                 /* anchor for the in-team corner marker */
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 14px;
  width: 100px;
  padding: 12px 8px;
  text-align: center;
  cursor: pointer;
  font-size: 11px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.hero-card.rarity-common    { background: linear-gradient(150deg, #1f2d33 0%, #141e22 100%); border-color: rgba(84,110,122,0.45); }
.hero-card.rarity-rare      { background: linear-gradient(150deg, #141e6b 0%, #0d1345 100%); border-color: rgba(79,195,247,0.35); }
.hero-card.rarity-epic      { background: linear-gradient(150deg, #2e0850 0%, #1c0535 100%); border-color: rgba(206,147,216,0.35); }
.hero-card.rarity-legendary { background: linear-gradient(150deg, #3d1e00 0%, #261200 100%); border-color: rgba(247,201,79,0.45); }
.hero-card:hover { border-color: rgba(93,202,165,0.4); box-shadow: 0 0 14px rgba(93,202,165,0.09); }

/* Heroes already in the formation. Placed AFTER the rarity rules on purpose: each
   .rarity-* sets its own border-color at equal specificity, so an earlier in-team
   rule would be overridden and the yellow border would never show. */
.hero-card.in-team { border: 1px solid rgba(255,213,79,0.65) !important;
                     box-shadow: 0 0 6px 1px rgba(255,213,79,0.16); }
/* Bold gold check badge in the top-right card corner — the primary at-a-glance
   marker (ℹ sits top-left, slot badge bottom-right of the avatar, so this corner
   is free). */
.hero-team-corner {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; border-radius: 50%;
  background: #ffd54f; color: #3a2c00;
  font-size: 12px; font-weight: 900; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 2px #111, 0 0 8px rgba(255,213,79,0.55);
  pointer-events: none; z-index: 3;
}
.hero-card .hero-rarity-common    { color: var(--dim); }
.hero-card .hero-rarity-rare      { color: #4fc3f7; }
.hero-card .hero-rarity-epic      { color: #ce93d8; }
.hero-card .hero-rarity-legendary { color: var(--accent); }
.hero-card .hero-level { font-size: 10px; color: var(--dim); margin-top: 2px; }

/* EXP bar on hero card */
.hero-exp-wrap { width: 100%; margin-top: 4px; }
.hero-exp-bar-outer {
  width: 100%; height: 3px;
  background: rgba(255,255,255,0.08);
  border-radius: 2px; overflow: hidden;
}
.hero-exp-bar-inner {
  height: 100%; background: #c084fc;
  border-radius: 2px; transition: width 0.4s ease;
}
.hero-exp-label { display: block; font-size: 9px; color: rgba(192,132,252,0.6); margin-top: 2px; }

/* Stat-point notification button on hero card */
.btn-stat-up {
  display: block; width: 100%; margin-top: 5px;
  padding: 4px 0; font-family: var(--font); font-size: 9px;
  font-weight: 700; letter-spacing: 0.06em;
  color: #c084fc; background: rgba(192,132,252,0.10);
  border: 1px solid rgba(192,132,252,0.35); border-radius: 6px;
  cursor: pointer; transition: background 0.15s;
}
.btn-stat-up:hover { background: rgba(192,132,252,0.22); }
@keyframes statPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(192,132,252,0.45); }
  50%       { box-shadow: 0 0 0 5px rgba(192,132,252,0); }
}
.btn-stat-up.pulse { animation: statPulse 1.6s ease-in-out infinite; }

.hero-stars { font-size: 12px; margin-top: 4px; letter-spacing: 0.02em; line-height: 1; }
.hero-star-filled { color: #f7c94f; }
.hero-star-empty  { color: #333; }

.btn-star-up {
  display: block;
  width: 100%;
  margin-top: 7px;
  padding: 4px 0;
  background: none;
  border: 1px solid #f7c94f44;
  border-radius: 6px;
  color: #f7c94f;
  font-family: var(--font);
  font-size: 9px;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-star-up:hover:not(:disabled) {
  background: rgba(247,201,79,0.12);
  border-color: #f7c94f88;
}
.btn-star-up:disabled {
  color: var(--dim);
  border-color: var(--border);
  cursor: default;
}

/* === Star-Up Celebration Modal === */
@keyframes starup-slide-in {
  from { transform: translateY(32px) scale(0.94); opacity: 0; }
  to   { transform: translateY(0)    scale(1);    opacity: 1; }
}
@keyframes starup-glow {
  0%, 100% { box-shadow: 0 0 0   0px rgba(247,201,79,0.0); }
  50%       { box-shadow: 0 0 32px 10px rgba(247,201,79,0.5); }
}
@keyframes star-pop {
  0%   { transform: scale(0) rotate(-20deg); opacity: 0; }
  60%  { transform: scale(1.35) rotate(6deg); opacity: 1; }
  100% { transform: scale(1)    rotate(0deg); opacity: 1; }
}
@keyframes starup-fade-up {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0);   opacity: 1; }
}

.starup-box {
  background: var(--card);
  border: 1px solid rgba(247,201,79,0.3);
  border-radius: 18px;
  padding: 32px 28px 24px;
  max-width: 320px;
  width: 90%;
  text-align: center;
  animation: starup-slide-in 0.32s cubic-bezier(0.22,1,0.36,1) forwards;
}
.starup-title {
  font-size: 10px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: #f7c94f;
  margin-bottom: 18px;
}
.starup-avatar-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: 14px;
}
.starup-avatar {
  width: 72px;
  height: 72px;
  border-radius: 14px;
  overflow: hidden;
  animation: starup-glow 1.4s ease-in-out infinite;
}
.starup-hero-name {
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
  letter-spacing: 0.04em;
}
.starup-stars-row {
  font-size: 22px;
  letter-spacing: 0.14em;
  color: #f7c94f;
  margin-bottom: 20px;
}
.starup-star {
  display: inline-block;
  opacity: 0;
  animation: star-pop 0.35s ease forwards;
}
.starup-star:nth-child(1) { animation-delay: 0.10s; }
.starup-star:nth-child(2) { animation-delay: 0.22s; }
.starup-star:nth-child(3) { animation-delay: 0.34s; }
.starup-star:nth-child(4) { animation-delay: 0.46s; }
.starup-star:nth-child(5) { animation-delay: 0.58s; }
.starup-star-empty { color: #444; }

.starup-stats {
  width: 100%;
  margin-bottom: 22px;
  border-collapse: collapse;
}
.starup-stat-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 0;
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  opacity: 0;
  animation: starup-fade-up 0.3s ease forwards;
}
.starup-stat-row:last-child { border-bottom: none; }
.starup-stat-row:nth-child(1) { animation-delay: 0.7s; }
.starup-stat-row:nth-child(2) { animation-delay: 0.82s; }
.starup-stat-row:nth-child(3) { animation-delay: 0.94s; }
.starup-stat-label { color: var(--dim); letter-spacing: 0.08em; }
.starup-stat-value {
  display: flex;
  align-items: center;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}
.starup-stat-old { color: var(--dim); text-decoration: line-through; }
.starup-stat-arrow { color: #f7c94f; font-size: 10px; }
.starup-stat-new { color: #5DCAA5; font-weight: 700; }

.starup-ok-btn { min-width: 140px; }

/* === Hero HP bar (hero menu cards) === */
.hero-hp-wrap {
  margin-top: 6px;
  width: 100%;
}
.hero-hp-wrap.hero-hp-full .hero-hp-bar-outer { display: none; }
.hero-hp-label {
  display: block;
  font-size: 9px;
  color: var(--dim);
  margin-bottom: 2px;
  letter-spacing: 0.06em;
}
.hero-hp-full .hero-hp-label { color: #4caf50; }
.hero-hp-bar-outer {
  width: 100%;
  height: 5px;
  background: #2a2a28;
  border-radius: 3px;
  overflow: hidden;
}
.hero-hp-bar-inner {
  height: 100%;
  border-radius: 3px;
  transition: width 0.3s, background 0.3s;
}

/* === Hero Heal button === */
.btn-heal {
  display: block;
  width: 100%;
  margin-top: 5px;
  padding: 4px 0;
  background: none;
  border: 1px solid #e53935aa;
  border-radius: 6px;
  color: #ef9a9a;
  font-family: var(--font);
  font-size: 9px;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-heal:hover:not(:disabled) {
  background: rgba(229,57,53,0.14);
  border-color: #ef9a9a;
}
.btn-heal:disabled {
  color: var(--dim);
  border-color: var(--border);
  cursor: default;
}

/* === Shop === */
.shop-section { width: 100%; max-width: 440px; margin: 0 auto 28px; }
.shop-section h3 {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--dim);
  margin-bottom: 12px;
}
.pack-list { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
.pack-card {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 16px;
  padding: 20px 14px;
  flex: 1;
  min-width: 130px;
  text-align: center;
  transition: border-color 0.2s, box-shadow 0.2s;
  /* Column layout so the price + button anchor to the bottom regardless of how
     many lines the title/hint take — keeps all "Öffnen" buttons on one line. */
  display: flex;
  flex-direction: column;
}
/* Push the price (and the button that follows it) to the bottom of the card. */
.pack-price { margin-top: auto; }
/* Keep the button its natural width (flex column would otherwise stretch it). */
.pack-card .btn-open-pack { align-self: center; }
.pack-card:hover { border-color: rgba(93,202,165,0.3); box-shadow: 0 0 18px rgba(93,202,165,0.06); }
.pack-card h4 {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  margin-bottom: 6px;
}
.pack-card p  { color: var(--dim); margin-bottom: 14px; font-size: 13px; letter-spacing: 0.06em; }
.pack-hint    { font-size: 10px !important; letter-spacing: 0.08em !important; margin-bottom: 6px !important; color: rgba(93,202,165,0.7) !important; }
.gem-bundles  { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.coming-soon  { color: var(--dim); font-size: 11px; letter-spacing: 0.1em; }

/* Daily gift widget */
.daily-gift-card {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 16px;
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.daily-gift-icon { font-size: 28px; line-height: 1; flex-shrink: 0; }
.daily-gift-info { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.daily-gift-amount { font-size: 16px; font-weight: 700; color: var(--coin, #f7c94f); }
.daily-gift-countdown { font-size: 11px; color: var(--dim); letter-spacing: 0.08em; min-height: 16px; }

/* Exchange widget */
.exchange-card {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 16px;
  padding: 20px 20px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 360px;
  margin: 0 auto;
}
.exchange-rate {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--dim);
  text-transform: uppercase;
}
.exchange-inputs {
  display: flex;
  align-items: center;
  gap: 14px;
}
.exchange-field {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #111110;
  border: 0.5px solid var(--border);
  border-radius: 10px;
  padding: 8px 12px;
}
.exchange-field input[type="number"] {
  width: 80px;
  background: none;
  border: none;
  color: var(--text);
  font-family: 'Courier New', Courier, monospace;
  font-size: 18px;
  font-weight: 700;
  outline: none;
  text-align: right;
  -moz-appearance: textfield;
}
.exchange-field input[type="number"]::-webkit-outer-spin-button,
.exchange-field input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.exchange-cur    { font-size: 20px; }
.exchange-arrow  { color: var(--dim); font-size: 18px; }
.exchange-result {
  font-size: 18px;
  font-weight: 700;
  color: #f7c94f;
  min-width: 90px;
  text-align: left;
  letter-spacing: 0.04em;
}
.exchange-msg { min-height: 1.2em; font-size: 11px; letter-spacing: 0.06em; text-align: center; }
.exchange-msg.ok  { color: var(--accent); }
.exchange-msg.err { color: #e05555; }

/* Gem bundle cards */
.gem-card {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 16px;
  padding: 18px 10px 14px;
  flex: 1;
  min-width: 172px;
  max-width: 200px;
  text-align: center;
  transition: border-color 0.2s, box-shadow 0.2s;
  position: relative;
  overflow: hidden;
}
.gem-card:hover { border-color: rgba(93,202,165,0.3); box-shadow: 0 0 18px rgba(93,202,165,0.06); }

/* Highlighted / popular card */
.gem-card-highlight {
  border-color: rgba(247,201,79,0.45);
  box-shadow: 0 0 22px rgba(247,201,79,0.08);
}
.gem-card-highlight:hover {
  border-color: rgba(247,201,79,0.7);
  box-shadow: 0 0 28px rgba(247,201,79,0.14);
}

.gem-card-inner { padding-bottom: 12px; }
.gem-badge {
  position: absolute;
  top: -1px;
  right: -1px;
  background: var(--accent);
  color: #111110;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.08em;
  padding: 3px 7px;
  border-radius: 0 14px 0 10px;
}
/* The "most popular" flag sits in the OPPOSITE corner from the rate badge, so the two are
   shown side by side rather than one replacing the other. They used to be an either/or,
   which meant the recommended pack was the only one not saying how good its rate was —
   the card recommended itself without ever giving a reason. */
.gem-badge-popular {
  right: auto;
  left: -1px;
  border-radius: 14px 0 10px 0;   /* mirror image of the right-hand badge */
  background: #f7c94f;
  color: #111110;
  font-size: 8px;
  white-space: nowrap;
}
.gem-icon   { font-size: 28px; margin-bottom: 6px; }
.gem-amount { font-size: 22px; font-weight: 900; color: var(--accent); letter-spacing: 0.04em; }
/* Under the total: what it is made of. The total stays the loud number — this line only
   has to make the arithmetic impossible to get wrong (it used to read "+ 3.200 Bonus-Gems
   gratis", which read like an amount to ADD to the total rather than part of it). */
.gem-total-label {
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 2px;
}
.gem-breakdown {
  font-size: 10px;
  font-weight: 700;
  color: #9a9a96;
  letter-spacing: 0.02em;
  margin: 6px 0 6px;
  min-height: 15px;
  white-space: nowrap;
}
.gem-breakdown .gem-plus { color: var(--accent); margin: 0 2px; }
.gem-breakdown-empty { color: transparent; min-height: 15px; margin: 6px 0; }
.gem-name   { font-size: 9px; text-transform: uppercase; letter-spacing: 0.18em; color: var(--dim); margin-bottom: 8px; }
.gem-price  { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 0; }
.gem-paypal-wrap {
  min-height: 70px;
  margin: 8px 0 0;
}
.gem-msg    { min-height: 14px; font-size: 10px; letter-spacing: 0.06em; margin-top: 6px; }
.gem-msg.ok  { color: var(--accent); }
.gem-msg.err { color: #e05555; }

/* === Pack Reveal === */
.pack-reveal { flex: 1; display: flex; align-items: center; justify-content: center; }
.reveal-card {
  width: 200px; height: 300px;
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border-radius: 22px;
  border: 0.5px solid var(--accent);
  box-shadow: 0 0 30px rgba(93,202,165,0.15);
}

/* === Auth Page === */
/* The only page that may scroll. Everywhere else the body is locked (html, body have
   overflow:hidden + touch-action:none, so a stray drag can never pan the game away) —
   but the register card is taller than a phone screen, and a centred card that does not
   fit spills out of BOTH ends: its top slid under the fixed DE/EN toggle, taking the
   card's "i" button out of reach. Hence: scrollable, and never centred so tightly that
   content lands under the toggle.
     min-height (not height) — the card may be taller than the viewport
     safe center            — centres while it fits, falls back to top-aligned when it
                              does not, instead of pushing the top off-screen
     padding-top            — keeps the card (and its "i") clear of the fixed toggle */
.auth-page {
  display: flex;
  flex-direction: column;           /* card, then footer — they stack, never overlap */
  align-items: safe center;
  justify-content: safe center;
  min-height: 100%;
  padding: calc(env(safe-area-inset-top, 0px) + 56px) 16px 32px;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;              /* the one place a finger may scroll */
  background: var(--bg);
  position: relative;
}
.auth-card {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 22px;
  padding: 36px 28px;
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  position: relative;
  z-index: 1;
}
.tab-bar { display: flex; gap: 6px; }
.tab {
  background: transparent;
  border: 0.5px solid var(--border);
  border-radius: 6px;
  color: var(--dim);
  font-family: var(--font);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 7px 18px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.tab:hover:not(.active) { color: var(--text); border-color: var(--dim); }
.tab.active { color: var(--accent); border-color: var(--accent); }

.auth-form { width: 100%; display: none; flex-direction: column; gap: 12px; }
.auth-form.active { display: flex; }
.auth-form label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dim);
}
.auth-form input {
  background: var(--bg);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  padding: 10px 12px;
  font-family: var(--font);
  font-size: 14px;
  width: 100%;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.auth-form input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(93,202,165,0.18);
}
.error-msg { color: var(--danger); font-size: 11px; min-height: 1.2em; letter-spacing: 0.06em; }
.auth-form .btn-primary { width: 100%; text-align: center; margin-top: 4px; }

/* === Overlay === */
.overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.82);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  z-index: 10;
}
.overlay.hidden { display: none; }
.overlay h2 {
  font-size: 13px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 18px rgba(93,202,165,0.4);
  margin-bottom: 6px;
}
.overlay p {
  color: var(--dim);
  font-size: 12px;
  letter-spacing: 0.06em;
  margin-bottom: 4px;
}

/* === Pack Info screen === */
.shop-section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.shop-section-header h3 {
  margin-bottom: 0;
}
.btn-pack-info {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--accent);
  background: none;
  color: var(--accent);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
.btn-pack-info:hover { background: var(--accent); color: var(--bg); }

#screenPackInfo, #screenPackLog {
  overflow-y: auto;
  padding-bottom: 24px;
}
.packlog-pagination {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: center;
  margin-bottom: 14px;
}
.packlog-wrap {
  width: 100%;
  max-width: 560px;
  overflow-x: auto;
}
.packlog-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  white-space: nowrap;
}
.packlog-table th {
  text-align: left;
  color: var(--dim);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0 10px 6px 0;
  border-bottom: 1px solid var(--border);
}
.packlog-table td {
  padding: 8px 10px 8px 0;
  border-bottom: 1px solid rgba(255,255,255,0.05);
  color: var(--text);
}
.packlog-table tr:last-child td { border-bottom: none; }
.packlog-table .packlog-num   { color: var(--muted); width: 32px; }
.packlog-table .packlog-date  { color: var(--muted); font-size: 11px; }
.packlog-table .packlog-coins { text-align: right; font-variant-numeric: tabular-nums; }
.packinfo-sub {
  color: var(--dim);
  font-size: 12px;
  text-align: center;
  margin-bottom: 20px;
  max-width: 300px;
  line-height: 1.5;
}
.packinfo-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 16px;
  width: 100%;
  max-width: 320px;
}
.packinfo-block h3 {
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 2px;
}
.packinfo-cost {
  font-size: 11px;
  color: var(--dim);
  margin-bottom: 12px;
}
.packinfo-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.packinfo-table th {
  text-align: left;
  color: var(--dim);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0 0 6px;
  border-bottom: 1px solid var(--border);
}
.packinfo-table th:last-child { text-align: right; }
.packinfo-table td {
  padding: 7px 0;
  border-bottom: 1px solid rgba(255,255,255,0.05);
}
.packinfo-table td:last-child {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.packinfo-table tr:last-child td { border-bottom: none; }

.rarity-common    td:first-child { color: #c8c8c8; }
.rarity-rare      td:first-child { color: #5b9cf6; }
.rarity-epic      td:first-child { color: #b06cf7; }
.rarity-legendary td:first-child { color: #f7c94f; }

.packinfo-note {
  color: var(--dim);
  font-size: 11px;
  text-align: center;
  max-width: 300px;
  line-height: 1.5;
  margin-top: 4px;
  margin-bottom: 20px;
}

/* === Hero info button (ℹ on avatar) === */
.btn-hero-info {
  position: absolute;
  top: -5px;
  left: -5px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid rgba(93,202,165,0.5);
  background: rgba(17,17,16,0.85);
  color: var(--accent);
  font-family: var(--font);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  z-index: 2;
  transition: background 0.15s, border-color 0.15s;
}
.btn-hero-info:hover { background: var(--accent); color: var(--bg); }

/* === Hero in-compare highlight === */
.hero-card.in-compare {
  border-color: rgba(247,201,79,0.45);
  box-shadow: 0 0 10px rgba(247,201,79,0.1);
}

/* === Compare bar === */
.compare-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid #f7c94f44;
  border-radius: 20px;
  padding: 7px 12px;
  margin: 10px auto 2px;
  width: fit-content;
  max-width: 340px;
  font-size: 12px;
  color: #f7c94f;
}
.compare-bar.hidden { display: none; }
.compare-bar .btn-small { font-size: 11px; padding: 4px 10px; }
.btn-accent {
  background: var(--accent);
  border: none;
  color: var(--bg);
  border-radius: 8px;
  font-family: var(--font);
  font-weight: 700;
  cursor: pointer;
  transition: opacity 0.15s;
}
.btn-accent:disabled { opacity: 0.35; cursor: default; }
.btn-accent-outline {
  border-color: var(--accent) !important;
  color: var(--accent) !important;
}

/* === Modals === */
.modal-backdrop {
  position: fixed;
  inset: 0;
  bottom: auto;
  /* Bind to the *visible* viewport (dvh) so a centered modal isn't pushed under
     the mobile browser's address/nav bar — which forced scrolling to reach the
     buttons. vh is the fallback for browsers without dvh support. */
  height: 100vh;
  height: 100dvh;
  background: rgba(0,0,0,0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.modal-backdrop.hidden { display: none; }

.modal-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 20px 18px 16px;
  width: 100%;
  max-width: 340px;
  max-height: 85vh;
  max-height: 85dvh;   /* visible-viewport height on mobile (fallback: 85vh) */
  overflow-y: auto;
  position: relative;
}
.modal-box-wide { max-width: 420px; }

.modal-title {
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
  text-align: center;
}

/* Countdown on the "your match is still running" offer: the seconds are the whole
   point of the dialog, so they are the loudest thing in it. */
.pvp-rejoin-clock {
  margin-top: 10px;
  text-align: center;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--accent, #5DCAA5);
  font-variant-numeric: tabular-nums;   /* the number must not wobble as it counts down */
}

.modal-actions {
  display: flex;
  gap: 8px;
  margin-top: 16px;
}
.modal-actions .btn-primary,
.modal-actions .btn-secondary {
  flex: 1;
  min-width: 0;               /* let flex items shrink so a long label (e.g.
                                 "Zum Heldenscreen") can't force horizontal
                                 overflow of the modal */
  padding-left: 14px;
  padding-right: 14px;
  text-align: center;
  overflow-wrap: break-word;  /* break an over-long single word instead of clipping */
}
/* Stacked variant: buttons below one another (used where labels are long, e.g.
   the heal-&-retry modal) instead of squeezing them into one wrapping row. */
.modal-actions.modal-actions-column {
  flex-direction: column;
}
.modal-actions.modal-actions-column .btn-primary,
.modal-actions.modal-actions-column .btn-secondary {
  flex: 0 0 auto;
  width: 100%;
}
/* Hidden "play on without healing" button (the whole team is defeated). */
#btnHealRetryNoHeal.hidden { display: none; }

/* === First-time in-game coach (non-blocking contextual tips) === */
/* Sits above HUD and overlays (both z-index 10) so summary tips show over the
   level-complete screen too; pointer-events:none so taps reach the canvas/buttons. */
.coach-tip {
  position: absolute;
  top: max(56px, calc(env(safe-area-inset-top, 0px) + 52px));
  left: 50%;
  transform: translateX(-50%);
  width: min(90%, 460px);
  z-index: 20;
  pointer-events: none;
  background: linear-gradient(150deg, rgba(30,34,40,0.96) 0%, rgba(18,20,24,0.96) 100%);
  border: 1px solid rgba(93,202,165,0.45);
  border-radius: 14px;
  box-shadow: 0 8px 28px rgba(0,0,0,0.5);
  overflow: hidden;
}
.coach-tip.hidden { display: none; }
.coach-tip.coach-in { animation: coach-in 0.32s cubic-bezier(0.2,0.8,0.3,1); }
@keyframes coach-in {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
.coach-tip-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
}
.coach-tip-icon {
  flex: 0 0 auto;
  font-size: 26px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
}
/* Purple gem badge mirroring the in-game EXP drop, for the "what are the crystals" tip. */
.coach-gem {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-block;
  background: radial-gradient(circle at 35% 30%, #e9d5ff 0%, #c084fc 60%, #a855f7 100%);
  border: 2px solid #7e22ce;
  box-shadow: 0 0 12px rgba(192,132,252,0.6);
}
.coach-tip-text { display: flex; flex-direction: column; gap: 2px; text-align: left; }
.coach-tip-eyebrow {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
}
.coach-tip-body {
  color: #ececec;
  font-size: 12.5px;
  line-height: 1.5;
  letter-spacing: 0.01em;
}
/* Thin auto-advance progress bar along the bottom edge. */
.coach-tip-bar { height: 3px; background: rgba(255,255,255,0.08); }
.coach-tip-bar-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width 0.12s linear;
}

/* === Hero info modal content === */
.hinfo-header {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-bottom: 12px;
}
.hinfo-avatar {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  flex-shrink: 0;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.hinfo-meta { flex: 1; }
.hinfo-name {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-bottom: 3px;
}
.hinfo-rarity { font-size: 11px; letter-spacing: 0.1em; margin-bottom: 5px; }
.hinfo-stars-row { font-size: 14px; }
.hinfo-level-tag {
  font-size: 10px;
  color: var(--dim);
  letter-spacing: 0.08em;
  vertical-align: middle;
}

.hinfo-desc {
  font-size: 12px;
  color: var(--dim);
  line-height: 1.5;
  margin-bottom: 14px;
  border-left: 2px solid var(--border);
  padding-left: 10px;
}

.hinfo-shottype {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 12px;
}
.hinfo-shottype-label { color: var(--dim); }
.hinfo-shottype-val   { font-weight: 700; letter-spacing: 0.06em; }
.hinfo-shottype-bolt  { color: #4fc3f7; }
.hinfo-shottype-orb   { color: #f7c94f; }
.hinfo-shottype-wave  { color: #ce93d8; }
.hinfo-shottype-dart  { color: #4fc3f7; }
.hinfo-shottype-tri   { color: #ffd54f; }

.hinfo-stat-section-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 8px;
}
.hinfo-next-label { color: #4caf50; text-transform: none; letter-spacing: 0; }

.hinfo-stat-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 7px;
}
.hinfo-stat-name {
  font-size: 11px;
  color: var(--dim);
  width: 54px;
  flex-shrink: 0;
  letter-spacing: 0.05em;
}
.hinfo-bar-track {
  flex: 1;
  height: 5px;
  background: rgba(255,255,255,0.06);
  border-radius: 3px;
  overflow: hidden;
}
.hinfo-bar-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.3s ease;
}
.hinfo-stat-val {
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 52px;
  text-align: right;
}
.hinfo-stat-next {
  color: #4caf50;
  font-size: 10px;
  font-weight: 400;
}

/* EXP progress in info modal header */
.hinfo-exp-section { margin-top: 6px; }
.hinfo-exp-bar-outer {
  width: 100%; height: 4px;
  background: rgba(255,255,255,0.08);
  border-radius: 2px; overflow: hidden;
}
.hinfo-exp-bar-inner {
  height: 100%; background: #c084fc;
  border-radius: 2px; transition: width 0.4s ease;
}
.hinfo-exp-nums { font-size: 9px; color: rgba(192,132,252,0.6); margin-top: 2px; }
.hinfo-exp-max  { font-size: 9px; color: rgba(192,132,252,0.8); margin-top: 2px; }

/* Stat-point invest section */
.hinfo-stat-points-section {
  margin: 14px 0 0;
  padding: 10px 12px;
  background: rgba(192,132,252,0.07);
  border: 1px solid rgba(192,132,252,0.22);
  border-radius: 10px;
}
.hinfo-statpoints-title {
  font-size: 11px; font-weight: 700;
  color: #c084fc; margin-bottom: 8px;
  letter-spacing: 0.06em;
}
.hinfo-stat-invest-row {
  display: flex; gap: 6px; flex-wrap: wrap;
}
.btn-invest-stat {
  flex: 1; min-width: 70px;
  padding: 6px 4px; font-family: var(--font);
  font-size: 10px; font-weight: 700;
  color: #c084fc; background: rgba(192,132,252,0.10);
  border: 1px solid rgba(192,132,252,0.30); border-radius: 8px;
  cursor: pointer; transition: background 0.15s, transform 0.1s;
}
.btn-invest-stat:hover:not(:disabled) { background: rgba(192,132,252,0.22); }
.btn-invest-stat:active:not(:disabled) { transform: scale(0.96); }
.btn-invest-stat:disabled { opacity: 0.4; cursor: default; }
.hinfo-stat-invested {
  font-size: 9px; color: rgba(192,132,252,0.55);
  margin-top: 10px; text-align: center; letter-spacing: 0.04em;
}

.hinfo-dupes-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 12px;
  font-size: 11px;
  color: var(--dim);
  border-top: 1px solid var(--border);
  padding-top: 10px;
}
.hinfo-cost-hint { color: #f7c94f; }
.hinfo-max       { color: var(--accent); }

/* === Reusable hero upgrade block (star / level / future equipment) ===
   Every upgrade source gets its own labelled card built from this same pattern,
   so a third "equipment" block slots in later with no new structure. */
.hinfo-block {
  margin-top: 14px;
  padding: 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: rgba(255,255,255,0.03);
}
.hinfo-block-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
}
.hinfo-block-icon { font-size: 20px; line-height: 1; flex-shrink: 0; }
.hinfo-block-titles { flex: 1; }
.hinfo-block-title { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; }
.hinfo-block-sub {
  font-size: 9px; color: var(--dim); letter-spacing: 0.04em; margin-top: 1px;
}
.hinfo-block-meta { font-size: 10px; color: var(--dim); letter-spacing: 0.03em; }
.hinfo-block-max  {
  font-size: 12px; font-weight: 700; color: var(--accent); margin-bottom: 4px;
}
.hinfo-block-exp  { margin-bottom: 10px; }

/* Star block accent (gold) */
.hinfo-block-star { background: rgba(247,201,79,0.06); border-color: rgba(247,201,79,0.22); }
.hinfo-block-star .hinfo-block-title { color: #f7c94f; }

/* Level block accent (purple) */
.hinfo-block-level { background: rgba(192,132,252,0.07); border-color: rgba(192,132,252,0.22); }
.hinfo-block-level .hinfo-block-title { color: #c084fc; }

/* Star-up preview rows (current → next, gold delta) */
.hinfo-preview-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-variant-numeric: tabular-nums; margin-bottom: 5px;
}
.hinfo-preview-name  { width: 54px; flex-shrink: 0; color: var(--dim); letter-spacing: 0.05em; }
.hinfo-preview-from  { color: var(--dim); }
.hinfo-preview-arrow { color: rgba(247,201,79,0.6); }
.hinfo-preview-to    { font-weight: 700; }
.hinfo-preview-delta { margin-left: auto; color: #f7c94f; font-weight: 700; }

/* Block action row (star-up button + meta) */
.hinfo-block-action {
  display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap;
}
.hinfo-block-btn {
  font-family: var(--font); font-size: 11px; font-weight: 700;
  padding: 7px 14px; border-radius: 8px; cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}
.hinfo-block-btn:active:not(:disabled) { transform: scale(0.96); }
.hinfo-block-btn:disabled { opacity: 0.4; cursor: default; }
.hinfo-star-btn {
  color: #f7c94f; background: rgba(247,201,79,0.12); border: 1px solid rgba(247,201,79,0.35);
}
.hinfo-star-btn:hover:not(:disabled) { background: rgba(247,201,79,0.24); }

/* Per-point clarifier under the invest buttons */
.hinfo-statpoints-perpoint {
  font-size: 9px; color: rgba(192,132,252,0.6);
  margin-top: 7px; letter-spacing: 0.03em;
}

/* === Hero compare modal === */
.cmp-table { width: 100%; }

.cmp-row {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 5px 0;
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
.cmp-row:last-child { border-bottom: none; }
.cmp-header-row { padding-bottom: 12px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }

.cmp-label-cell {
  width: 60px;
  flex-shrink: 0;
  font-size: 10px;
  color: var(--dim);
  letter-spacing: 0.08em;
}
.cmp-cell { flex: 1; text-align: center; }

.cmp-hero-cell { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.cmp-avatar {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  margin-bottom: 2px;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.cmp-hero-name  { font-size: 11px; font-weight: 700; }
.cmp-hero-stars { font-size: 11px; }
.cmp-hero-rarity { font-size: 9px; letter-spacing: 0.08em; }
.cmp-hero-level  { font-size: 9px; color: var(--dim); }

.cmp-val-cell {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--dim);
}
.cmp-best { color: #4caf50; }

/* === Toast notification === */
#gameToast {
  position: fixed;
  bottom: 88px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(24, 22, 20, 0.96);
  border: 1px solid rgba(239,154,154,0.35);
  border-radius: 10px;
  padding: 11px 22px;
  color: #ef9a9a;
  font-family: 'Courier New', Courier, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}
#gameToast.visible { opacity: 1; }

/* ========================================================
   PACK OPENING — EPIC REVEAL ANIMATION
======================================================== */

#screenPackOpen {
  padding: 0;
  justify-content: center;
  overflow: hidden;
}

/* Dark base background */
.pack-anim-bg {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 42%, #0c1520 0%, #050810 100%);
  z-index: 0;
  pointer-events: none;
}

/* Rarity color overlay — fades in on reveal */
.pack-anim-bg-overlay {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.1s ease;
  z-index: 0;
  pointer-events: none;
}
.pack-anim-bg-overlay.visible { opacity: 1; }

/* ── Legendary Shine Rays ────────────────────────── */
.pack-shine {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}
.pack-shine.hidden { display: none; }
.pack-shine::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 900px;
  height: 900px;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,    rgba(255,213,79,0.18) 18deg,
    transparent 36deg,   rgba(255,213,79,0.10) 54deg,
    transparent 72deg,   rgba(255,213,79,0.18) 90deg,
    transparent 108deg,  rgba(255,213,79,0.10) 126deg,
    transparent 144deg,  rgba(255,213,79,0.18) 162deg,
    transparent 180deg,  rgba(255,213,79,0.10) 198deg,
    transparent 216deg,  rgba(255,213,79,0.18) 234deg,
    transparent 252deg,  rgba(255,213,79,0.10) 270deg,
    transparent 288deg,  rgba(255,213,79,0.18) 306deg,
    transparent 324deg,  rgba(255,213,79,0.10) 342deg,
    transparent 360deg
  );
  animation: pack-rays-spin 2.7s ease-out forwards;
}

@keyframes pack-rays-spin {
  0%   { transform: translate(-50%,-50%) rotate(0deg) scale(0.05); opacity: 0; }
  12%  { opacity: 0.9; }
  75%  { opacity: 0.8; }
  100% { transform: translate(-50%,-50%) rotate(55deg) scale(2.6); opacity: 0; }
}

/* ── Layout ──────────────────────────────────────── */
.pack-anim-container {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 34px;
  width: 100%;
  max-width: 380px;
}

.pack-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
  width: 100%;
}
.pack-stage.hidden { display: none; }

/* ── 3D Card ─────────────────────────────────────── */
.pack-flip-wrapper {
  perspective: 900px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  position: relative;
}

.pack-flipper {
  width: 200px;
  height: 268px;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.72s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.pack-flipper.flipped { transform: rotateY(180deg); }

.pack-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.pack-front {
  background: linear-gradient(148deg, #141d30 0%, #0d1526 50%, #0a1132 100%);
  border: 1.5px solid rgba(255,255,255,0.18);
  animation: pack-front-glow 2.3s ease-in-out infinite;
}

@keyframes pack-front-glow {
  0%,100% { box-shadow: 0 0 32px rgba(79,195,247,0.22), 0 0 70px rgba(79,195,247,0.07); }
  50%      { box-shadow: 0 0 58px rgba(79,195,247,0.50), 0 0 120px rgba(79,195,247,0.20); }
}

.pack-glyph {
  font-size: 86px;
  font-weight: 900;
  color: #fff;
  line-height: 1;
  animation: glyph-pulse 2.3s ease-in-out infinite;
}

@keyframes glyph-pulse {
  0%,100% { text-shadow: 0 0 18px #4fc3f7, 0 0 42px rgba(79,195,247,0.6); }
  50%      { text-shadow: 0 0 28px #4fc3f7, 0 0 65px rgba(79,195,247,1.0), 0 0 110px rgba(79,195,247,0.4); }
}

.pack-type-name {
  font-size: 0.68rem;
  color: rgba(255,255,255,0.38);
  text-transform: uppercase;
  letter-spacing: 3.5px;
  margin-top: 16px;
}

.pack-back {
  transform: rotateY(180deg);
  overflow: hidden;
  border-radius: 18px;
}

.pack-back-hero-name {
  font-size: 1.4rem;
  font-weight: 900;
  color: rgba(255,255,255,0.92);
  text-align: center;
  padding: 18px;
  text-shadow: 0 2px 14px rgba(0,0,0,0.5);
  letter-spacing: 0.05em;
}

/* ── Card Entry Animation ────────────────────────── */
.pack-flip-wrapper.pack-enter {
  animation: pack-wrapper-enter 0.80s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes pack-wrapper-enter {
  from { transform: translateY(110px) scale(0.62); opacity: 0; }
  to   { transform: translateY(0)     scale(1);    opacity: 1; }
}

/* Idle float after entering */
.pack-flipper.pack-idle {
  animation: pack-idle-float 4.0s ease-in-out infinite;
}

@keyframes pack-idle-float {
  0%,100% { transform: translateY(0)   rotate(-0.7deg); }
  50%      { transform: translateY(-13px) rotate(0.7deg); }
}

/* Shake when tapped too early */
.pack-flipper.pack-loading-shake {
  animation: pack-loading-shake 0.44s ease-in-out !important;
}

@keyframes pack-loading-shake {
  0%,100% { transform: translateX(0); }
  18%     { transform: translateX(-10px) rotate(-2.5deg); }
  36%     { transform: translateX(10px)  rotate(2.5deg); }
  54%     { transform: translateX(-7px)  rotate(-1.5deg); }
  72%     { transform: translateX(7px)   rotate(1.5deg); }
}

/* ── Tap Hint ────────────────────────────────────── */
.pack-tap-hint {
  font-size: 0.78rem;
  font-weight: 700;
  color: rgba(255,255,255,0.6);
  text-transform: uppercase;
  letter-spacing: 5px;
  user-select: none;
  animation: tap-hint-pulse 1.4s ease-in-out infinite;
}
.pack-tap-hint.hidden { display: none; }

@keyframes tap-hint-pulse {
  0%,100% { opacity: 0.35; letter-spacing: 5px; }
  50%      { opacity: 1;    letter-spacing: 6.5px; }
}

/* ── Particle Burst ──────────────────────────────── */
.pack-particles {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 20;
  overflow: visible;
}

.pack-particle {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: particle-burst 1.05s ease-out forwards;
}

@keyframes particle-burst {
  0%   { transform: translate(-50%,-50%) scale(1.3); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(0); opacity: 0; }
}

/* ── Hero Reveal ─────────────────────────────────── */
.reveal-hero-avatar {
  width: 130px;
  height: 130px;
  border-radius: 22px;
  opacity: 0;
}

.reveal-hero-avatar.enter {
  animation: hero-avatar-enter 0.95s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes hero-avatar-enter {
  0%   { transform: scale(0.08) rotate(-20deg); opacity: 0; }
  62%  { transform: scale(1.14) rotate(2.5deg); opacity: 1; }
  80%  { transform: scale(0.96) rotate(-1deg);  }
  100% { transform: scale(1)    rotate(0);      opacity: 1; }
}

.reveal-hero-name {
  font-size: 2.1rem;
  font-weight: 900;
  color: #fff;
  text-align: center;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  opacity: 0;
  animation: reveal-fade-up 0.55s 0.24s ease-out forwards;
}

.reveal-hero-badges {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  opacity: 0;
  animation: reveal-fade-up 0.55s 0.45s ease-out forwards;
}

@keyframes reveal-fade-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal-hero-rarity {
  padding: 5px 16px;
  border-radius: 20px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 2px;
}
.reveal-hero-rarity.rarity-common    { background: rgba(55,71,79,0.7);  color: #b0bec5; border: 1px solid #546e7a; }
.reveal-hero-rarity.rarity-rare      { background: rgba(21,30,100,0.7); color: #90caf9; border: 1px solid #3949ab; }
.reveal-hero-rarity.rarity-epic      { background: rgba(58,0,90,0.7);   color: #e040fb; border: 1px solid #7b1fa2; }
.reveal-hero-rarity.rarity-legendary { background: rgba(60,28,0,0.7);   color: #ffd54f; border: 1px solid #f57f17; }

.reveal-result-badge {
  padding: 5px 16px;
  border-radius: 20px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 2px;
}
.badge-new {
  background: #f7c94f;
  color: #1a1200;
  border: 1px solid #ffd54f;
  box-shadow: 0 0 20px rgba(247,201,79,0.6);
  animation: badge-new-pop 0.58s 0.46s cubic-bezier(0.34,1.56,0.64,1) both;
}
.badge-dup {
  background: rgba(22,22,34,0.85);
  color: #50505a;
  border: 1px solid #252530;
}

@keyframes badge-new-pop {
  from { transform: scale(0.3); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}

/* ── Continue Button ─────────────────────────────── */
.pack-done-btn {
  position: absolute;
  bottom: max(44px, calc(env(safe-area-inset-bottom, 0px) + 34px));
  /* Center horizontally WITHOUT transform: the shared .btn-primary:active rule
     sets `transform: scale(0.96)` on press, which — being more specific than a
     single-class selector — used to override a `translateX(-50%)` centering and
     make the button jump sideways out from under the pointer (so the click never
     landed and you had to press twice / hold). Centering via auto margins keeps
     transform free for the press-scale effect. */
  left: 0;
  right: 0;
  margin-inline: auto;
  width: fit-content;
  z-index: 3;
  white-space: nowrap;
}
.pack-done-btn.hidden { display: none !important; }

/* ── Leaderboard Screen ──────────────────────────── */
.leaderboard-wrap {
  width: 100%;
  max-width: 480px;
  margin: 0 auto 24px;
}

/* Only the table scrolls horizontally — the controls above and pagination below
   stay put so they're always reachable while scrolling the table on mobile. */
.lb-table-scroll {
  width: 100%;
  overflow-x: auto;
}

.leaderboard-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.leaderboard-table th {
  text-align: left;
  padding: 8px 12px;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}

.leaderboard-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}

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

.lb-rank  { width: 36px; font-size: 18px; text-align: center; }
.lb-name  { font-weight: 600; }
.lb-score { text-align: right; font-variant-numeric: tabular-nums; color: var(--accent); }
.lb-wave  { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); width: 60px; }

.lb-gold   td { background: rgba(255, 200, 0,  0.07); }
.lb-silver td { background: rgba(180, 190, 210, 0.06); }
.lb-bronze td { background: rgba(180, 100, 40,  0.07); }

.lb-time  { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); width: 56px; }
.lb-coins { text-align: right; font-variant-numeric: tabular-nums; color: #f7c94f;      width: 70px; }

.lb-team-cell { width: 1%; white-space: nowrap; }
.lb-team {
  display: inline-flex;
  align-items: center;
}
.lb-team-hero {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid var(--border);
  margin-left: -5px;      /* slight overlap to stay compact */
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.lb-team-hero:first-child { margin-left: 0; }
.lb-team-empty { color: var(--muted); font-size: 12px; }
.lb-team-clickable { cursor: pointer; }
.lb-team-clickable:hover .lb-team-hero { border-color: var(--accent); }

/* ── Leaderboard team modal ─────────────────────────────── */
.tm-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 4px 0 20px;
}
.tm-hero {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border);
}
.tm-portrait {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  flex-shrink: 0;
  border: 1px solid var(--border);
}
.tm-info { flex: 1; min-width: 0; }
.tm-name { font-weight: 700; font-size: 15px; }
.tm-meta {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 2px;
  font-size: 13px;
}
.tm-stars { color: #f7c94f; letter-spacing: 1px; }
.tm-level { color: var(--muted); }
.tm-stats {
  display: flex;
  gap: 14px;
  margin-top: 5px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.lb-sortable        { cursor: pointer; user-select: none; }
.lb-sortable:hover  { color: var(--text); }
.lb-sorted          { color: var(--accent); }

.lb-me td           { background: rgba(99, 102, 241, 0.12) !important; }
.lb-me .lb-name     { color: var(--accent); font-weight: 700; }

/* ── Profile screen ─────────────────────────────── */
.profile-card {
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px 18px;
  margin-bottom: 14px;
}
.profile-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, var(--accent), #7c3aed);
  overflow: hidden;
}
.profile-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.profile-name  { font-size: 20px; font-weight: 800; }

/* Cosmetic label next to a username (e.g. "Dev"), shown in profile, friends list
   and leaderboards. Decoupled from the login name — see badge column in models. */
.name-badge {
  display: inline-block;
  vertical-align: middle;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  border: 0.5px solid var(--accent);
  background: rgba(93, 202, 165, 0.12);
  color: var(--accent);
  font-size: 0.68em;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.5;
  white-space: nowrap;
}

/* Own-profile edit pencil, top-right of the identity card. */
.profile-card-editable { position: relative; padding-right: 44px; }
.profile-edit-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #9a9a97;                 /* grey by default */
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.profile-edit-btn:hover { color: #fff; background: rgba(255,255,255,0.08); }
.profile-edit-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(93,202,165,0.5); }

/* ── Edit-profile modal ────────────────────────────────────────────────── */
.avatar-preview {
  width: 72px; height: 72px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, #5DCAA5, #7c3aed);
}
.avatar-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-remove[hidden] { display: none; }

.pe-section { text-align: left; }
.pe-avatar-row { display: flex; align-items: center; gap: 16px; }
.pe-avatar-actions { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 0; }
.pe-avatar-actions button { width: 100%; text-align: center; }
.pe-subtitle { font-size: 14px; font-weight: 700; color: #e8e5df; margin: 0 0 6px; }
.pe-hint { font-size: 12px; color: #888; line-height: 1.5; margin: 10px 0 0; }
.pe-divider { height: 1px; background: var(--border); margin: 20px 0; }
.pe-form { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.pe-form input {
  background: #111110; border: 0.5px solid #2a2a28; border-radius: 12px;
  color: #e8e5df; padding: 10px 12px;
  font-family: 'Courier New', Courier, monospace; font-size: 14px; width: 100%;
  box-sizing: border-box; transition: border-color 0.15s, box-shadow 0.15s;
}
.pe-form input:focus {
  outline: none; border-color: #5DCAA5; box-shadow: 0 0 0 1px rgba(93,202,165,0.18);
}
.pe-form button { width: 100%; text-align: center; }
.settings-msg { min-height: 16px; font-size: 11px; letter-spacing: 0.06em; margin: 8px 0 0; }
.settings-msg.ok  { color: #5DCAA5; }
.settings-msg.err { color: #e05555; }

/* Upload / processing progress bar */
.pe-progress { margin-top: 12px; }
.pe-progress[hidden] { display: none; }
.pe-progress-label { font-size: 12px; color: #bbb; margin-bottom: 6px; }
.pe-progress-track {
  height: 8px; background: #2a2a28; border-radius: 6px; overflow: hidden;
}
.pe-progress-bar {
  height: 100%; width: 0%; border-radius: 6px;
  background: linear-gradient(90deg, #5DCAA5, #7c3aed);
  transition: width 0.2s ease;
}
/* Indeterminate sweep while the server re-encodes (no measurable progress). */
.pe-progress-bar.indeterminate {
  width: 40%;
  animation: pe-indet 1.1s ease-in-out infinite;
}
@keyframes pe-indet {
  0%   { margin-left: -40%; }
  100% { margin-left: 100%; }
}
.pe-busy .modal-box { cursor: progress; }
.profile-since { font-size: 13px; margin-top: 2px; }

.profile-stats {
  display: flex;
  gap: 12px;
  margin-bottom: 18px;
}
.profile-stat {
  flex: 1;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  text-align: center;
}
.profile-stat-label {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  margin-bottom: 4px;
}
.profile-stat-value {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.profile-section {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 18px;
}
.profile-section h3 { margin: 0 0 6px; font-size: 15px; }
.profile-section p  { margin: 0; font-size: 13px; line-height: 1.6; }

/* Clickable leaderboard usernames → public profile */
.lb-name-link { cursor: pointer; }
.lb-name-link:hover { color: var(--accent); text-decoration: underline; }

/* Public profile extras */
.pubprofile-endless { display: flex; align-items: baseline; gap: 8px; font-size: 16px; font-weight: 700; }
.pubprofile-endless-score { color: var(--accent); font-variant-numeric: tabular-nums; }
.pubprofile-team { margin-top: 10px; display: inline-flex; }
.pubprofile-locked { opacity: 0.7; }
.pubprofile-friend-btn { width: 100%; margin-top: 4px; text-align: center; }

/* Own-profile privacy overview + shortcuts */
.profile-privacy { margin: 8px 0 12px; }
.privacy-hint-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.privacy-hint-row:last-child { border-bottom: none; }
.privacy-hint-label { color: var(--muted); letter-spacing: .04em; }
.privacy-hint-state { font-weight: 600; }
.privacy-hint-state.privacy-hidden  { color: var(--muted); }
.privacy-hint-state.privacy-visible { color: var(--accent); }
.profile-privacy-btn, .profile-friends-btn { width: 100%; margin-top: 4px; text-align: center; }

/* Profile campaign progress */
.profile-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.profile-section-head h3 { margin: 0; }
.profile-section-pct {
  font-size: 16px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.progress-bar {
  height: 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--border);
  overflow: hidden;
  margin-bottom: 12px;
}
.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), #7c3aed);
  border-radius: 999px;
  transition: width .4s ease;
}
.profile-campaign .profile-stats { margin-bottom: 0; }
.profile-stats-3 { gap: 8px; }
.profile-stats-3 .profile-stat { padding: 10px 8px; }
.profile-stats-3 .profile-stat-value { font-size: 15px; }

/* Endless run totals */
.profile-endless-meta {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

/* Profile achievements */
.ach-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
}
.ach-badge {
  position: relative;
  text-align: center;
  padding: 10px 6px 8px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--bg2);
}
.ach-icon { font-size: 24px; line-height: 1; margin-bottom: 4px; }
.ach-name { font-size: 11px; font-weight: 700; line-height: 1.2; }
.ach-tier {
  font-size: 9px;
  letter-spacing: .06em;
  text-transform: uppercase;
  margin: 2px 0 6px;
  color: var(--muted);
}
.ach-progress {
  height: 5px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  overflow: hidden;
}
.ach-progress-fill { height: 100%; border-radius: 999px; background: var(--accent); }
.ach-progress-text {
  font-size: 9px;
  color: var(--dim);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
}
.ach-max {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--accent);
  margin-top: 6px;
}
/* Locked badges are dimmed until the first tier is reached. */
.ach-badge.ach-locked { opacity: .5; }
.ach-badge.ach-locked .ach-icon { filter: grayscale(1); }
/* Medal-tinted borders/tiers by rank. */
.ach-badge.tier-bronze   { border-color: #cd7f32; }
.ach-badge.tier-silver   { border-color: #c0c0c0; }
.ach-badge.tier-gold     { border-color: #ffd54f; }
.ach-badge.tier-platinum { border-color: #7fd4e0; }
.ach-badge.tier-diamond  { border-color: #67e8f9; box-shadow: 0 0 10px rgba(103,232,249,0.25); }
/* Tier label text colour */
.tier-bronze   .ach-tier { color: #cd7f32; }
.tier-silver   .ach-tier { color: #d8d8d8; }
.tier-gold     .ach-tier { color: #ffd54f; }
.tier-platinum .ach-tier { color: #7fd4e0; }
.tier-diamond  .ach-tier { color: #67e8f9; }
/* Progress-bar fill colour per tier */
.tier-bronze   .ach-progress-fill { background: #cd7f32; }
.tier-silver   .ach-progress-fill { background: #c0c0c0; }
.tier-gold     .ach-progress-fill { background: #ffd54f; }
.tier-platinum .ach-progress-fill { background: #7fd4e0; }
.tier-diamond  .ach-progress-fill { background: #67e8f9; }

/* Profile hero collection */
.collection-packs {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 13px;
  margin-bottom: 12px;
}
.collection-packs-val { font-weight: 700; font-variant-numeric: tabular-nums; }
.collection-count {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 4px;
}
.collection-count .muted { font-size: 13px; letter-spacing: .04em; }
.collection-count-val {
  font-size: 18px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.rarity-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.rarity-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--border);
}
.rarity-chip b { font-variant-numeric: tabular-nums; }
.rarity-chip.rarity-common    { background: rgba(55,71,79,0.35);  color: #b0bec5; border-color: #546e7a; }
.rarity-chip.rarity-rare      { background: rgba(21,30,100,0.35); color: #90caf9; border-color: #3949ab; }
.rarity-chip.rarity-epic      { background: rgba(58,0,90,0.35);   color: #e040fb; border-color: #7b1fa2; }
.rarity-chip.rarity-legendary { background: rgba(60,28,0,0.4);    color: #ffd54f; border-color: #f57f17; }

.showcase-hero {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 12px;
}
.showcase-hero.rarity-common    { border-color: rgba(84,110,122,0.55); }
.showcase-hero.rarity-rare      { border-color: rgba(79,195,247,0.45); }
.showcase-hero.rarity-epic      { border-color: rgba(206,147,216,0.45); }
.showcase-hero.rarity-legendary { border-color: rgba(247,201,79,0.55); }
.showcase-portrait {
  width: 52px;
  height: 52px;
  border-radius: 10px;
  flex-shrink: 0;
  background-color: #2a2a2a;
}
.showcase-info { min-width: 0; }
.showcase-label {
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.showcase-name { font-size: 15px; font-weight: 700; }
.showcase-meta { font-size: 12px; color: var(--dim); margin-top: 1px; }
.showcase-stars { color: var(--accent); letter-spacing: 1px; }
.showcase-stats {
  display: flex;
  gap: 12px;
  margin-top: 4px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.collection-team-label {
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.pubprofile-current-team { display: inline-flex; }

/* Friends list */
.friends-section { margin-bottom: 20px; }
.friends-section h3 {
  margin: 0 0 8px;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.friend-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 8px;
}
.friend-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, var(--accent), #7c3aed);
  overflow: hidden;
}
.friend-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.friend-name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.friend-actions { display: flex; gap: 6px; flex-shrink: 0; }
.friend-status-label { font-size: 12px; color: var(--accent); font-weight: 600; }

/* Friend search */
.friend-search { margin-bottom: 14px; }
.friend-search-input {
  width: 100%;
  box-sizing: border-box;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  color: var(--text);
  padding: 10px 14px;
  font-size: 14px;
}
.friend-search-input:focus {
  outline: none;
  border-color: var(--accent);
}
.friend-search-empty { padding: 8px 2px; }

/* ── Leaderboard controls & pagination ──────────── */
.lb-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.lb-per-page-label {
  color: var(--muted);
  font-size: 12px;
  margin-right: 4px;
}

.lb-size-btn {
  background: var(--bg2);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
}

.lb-size-btn.active,
.lb-size-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Column-visibility toggles — pushed to the right end of the controls row. */
.lb-col-toggles {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  flex-wrap: wrap;
}

.lb-col-label {
  color: var(--muted);
  font-size: 12px;
  margin-right: 2px;
}

.lb-col-btn {
  background: var(--bg2);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
}

.lb-col-btn::before {
  content: "＋ ";
  opacity: 0.7;
}

.lb-col-btn.active {
  border-color: var(--accent);
  color: var(--accent);
}

.lb-col-btn.active::before {
  content: "✓ ";
}

.lb-col-btn:hover {
  border-color: var(--accent);
}

/* Hide the descriptive labels when the controls row would otherwise wrap to a
   second line, keeping the buttons on one line. This can't be a viewport media
   query: the row lives in a 480px-capped container, so on a wide PC screen the
   endless-mode row (which adds the "Spalten" column-toggle group) overflows the
   container and wraps while the viewport is still far above any mobile
   breakpoint. Key off the toggle group's presence instead — it only exists in
   endless mode, where space is tight; campaign mode has room to keep its label.
   The "Spalten" label lives inside .lb-col-toggles, so it is always dropped. */
.lb-controls:has(.lb-col-toggles) .lb-per-page-label,
.lb-col-label { display: none; }

.lb-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 14px;
}

.lb-page-btn {
  background: var(--bg2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 6px 14px;
  font-size: 13px;
  cursor: pointer;
}

.lb-page-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.lb-page-btn:disabled              { opacity: 0.35; cursor: default; }

.lb-page-info {
  color: var(--muted);
  font-size: 13px;
  min-width: 60px;
  text-align: center;
}

.lb-date  { text-align: right; color: var(--muted); font-size: 12px; white-space: nowrap; }

/* ── Leaderboard mode tabs ──────────────────────────── */
.lb-tabs {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin: 0 auto 16px;
  max-width: 480px;
  width: 100%;
}

.lb-tab {
  flex: 1;
  background: var(--bg2);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 8px;
  padding: 8px 0;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

.lb-tab:hover       { border-color: var(--accent); color: var(--text); }
.lb-tab.active      { border-color: var(--accent); color: var(--accent); background: rgba(99,102,241,0.08); }

/* ── Campaign leaderboard columns ───────────────────── */
.lb-stars  { text-align: right; font-variant-numeric: tabular-nums; color: #f7c94f; }
.lb-levels { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); width: 60px; }
.lb-max    { color: var(--muted); font-size: 11px; }

/* ── Welcome / Starter Pack Overlay ─────────────────── */
.welcome-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 20px;
}
.welcome-overlay.hidden { display: none; }

.welcome-pack-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  max-width: 380px;
  width: 100%;
  text-align: center;
}

.welcome-subtitle {
  color: var(--dim);
  font-size: 14px;
  line-height: 1.6;
  letter-spacing: 0.04em;
}

.welcome-pack-card {
  background: linear-gradient(150deg, #1a2a20 0%, #141412 100%);
  border: 1.5px solid rgba(93,202,165,0.35);
  border-radius: 20px;
  padding: 28px 32px 24px;
  width: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  box-shadow: 0 0 24px rgba(93,202,165,0.08);
}

.welcome-pack-free-badge {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  padding: 4px 14px;
  border-radius: 20px;
}

.welcome-pack-card h3 {
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  margin: 8px 0 0;
}

.welcome-pack-icon {
  font-size: 52px;
  line-height: 1;
  margin: 12px 0;
  filter: drop-shadow(0 0 12px rgba(93,202,165,0.3));
}

/* ── Gem Shop nav button in main shop ───────────────── */
.btn-gem-shop-nav {
  display: block;
  width: 100%;
  padding: 18px 24px;
  background: linear-gradient(135deg, #1a1060 0%, #0d0830 100%);
  border: 1px solid rgba(121,134,203,0.4);
  border-radius: 14px;
  color: #a5b4fc;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.06em;
  cursor: pointer;
  text-align: center;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.btn-gem-shop-nav:hover {
  border-color: rgba(121,134,203,0.7);
  box-shadow: 0 0 18px rgba(99,102,241,0.12);
}

/* ── Gem Shop screen ────────────────────────────────── */
#screenGemShop .gem-bundles {
  width: 100%;
  max-width: 480px;
}

/* ── Boot loader overlay ─────────────────────────────────
   Covers the async startup after login (user data, sprites,
   heroes, campaign defs). Visible by default; main.js hides it. */
#bootLoader {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg);
  transition: opacity 0.35s ease;
}
#bootLoader.hidden {
  opacity: 0;
  pointer-events: none;
}
#bootLoader .boot-spinner {
  width: 38px;
  height: 38px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: bootspin 0.8s linear infinite;
}
@keyframes bootspin { to { transform: rotate(360deg); } }
#bootLoader .boot-text {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dim);
}
/* Error state — shown when the startup sequence throws */
#bootLoader .boot-error {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
#bootLoader .boot-error-msg {
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--danger);
}
#bootLoader.error .boot-spinner,
#bootLoader.error .boot-text { display: none; }
#bootLoader.error .boot-error { display: flex; }

/* ==========================================================================
   Events page — tab hub + Login-Event reward grid
   ========================================================================== */
.event-tabs {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0 auto 18px;
  max-width: 480px;
  width: 100%;
}
.event-tab {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--dim);
  border-radius: 8px;
  padding: 8px 18px;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.event-tab:hover  { border-color: var(--accent); color: var(--text); }
.event-tab.active { border-color: var(--accent); color: var(--accent); background: rgba(93,202,165,0.08); }

.event-content { max-width: 620px; margin: 0 auto; width: 100%; }

.event-login-desc {
  color: var(--dim);
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
  margin-bottom: 18px;
}

.event-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  margin-bottom: 20px;
}
@media (max-width: 520px) {
  .event-grid { grid-template-columns: repeat(4, 1fr); gap: 6px; }
}

.event-tile {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 4px 7px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-height: 78px;
  justify-content: center;
  transition: transform 0.12s, border-color 0.15s, box-shadow 0.2s;
}
.event-tile-day {
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--dim);
  text-transform: uppercase;
}
.event-tile-icon  { font-size: 22px; line-height: 1; }
.event-tile-label { font-size: 12px; font-weight: 700; color: var(--text); }

/* Claimed — dimmed with a check overlay */
.event-tile.claimed { opacity: 0.45; }
.event-tile.claimed .event-tile-label { color: var(--dim); }
.event-tile-check {
  position: absolute;
  top: 4px;
  right: 5px;
  color: var(--accent);
  font-size: 13px;
  font-weight: 900;
}

/* Locked — muted, not interactive */
.event-tile.locked { opacity: 0.6; }

/* Claimable — highlighted, pulsing, clickable */
.event-tile.claimable {
  border-color: var(--accent);
  cursor: pointer;
  animation: eventPulse 1.6s ease-in-out infinite;
}
.event-tile.claimable:hover { transform: translateY(-2px); }
@keyframes eventPulse {
  0%, 100% { box-shadow: 0 0 4px rgba(93,202,165,0.30); }
  50%      { box-shadow: 0 0 16px rgba(93,202,165,0.55); }
}

/* Milestone tiles (Premium / multi-pack) get a golden accent */
.event-tile.milestone {
  border-color: rgba(247,201,79,0.55);
  background: linear-gradient(160deg, rgba(247,201,79,0.10), var(--surface));
}
.event-tile.milestone .event-tile-label { color: #f7c94f; }
.event-tile.milestone.claimable { animation: eventPulseGold 1.6s ease-in-out infinite; }
@keyframes eventPulseGold {
  0%, 100% { box-shadow: 0 0 5px rgba(247,201,79,0.35); }
  50%      { box-shadow: 0 0 18px rgba(247,201,79,0.65); }
}

.event-login-footer { text-align: center; min-height: 44px; }
.event-login-footer .btn-primary { min-width: 200px; }
.event-login-status {
  color: var(--dim);
  font-size: 14px;
  padding: 10px 0;
}
.event-login-status.done { color: var(--accent); font-weight: 700; }
#eventCountdown { color: var(--text); font-variant-numeric: tabular-nums; margin-left: 4px; }

/* ── Quests & daily quests ───────────────────────────────────────────────── */
.quest-group-title {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--dim);
  margin: 18px 0 8px;
}
.quest-list { display: flex; flex-direction: column; gap: 8px; }
.quest-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--card, rgba(255,255,255,0.03));
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-radius: 10px;
}
.quest-row.completed { border-color: var(--accent); background: rgba(93,202,165,0.08); }
.quest-row.claimed { opacity: 0.5; }
.quest-row.claimed .quest-reward { color: var(--dim); }
.quest-main { flex: 1; min-width: 0; }
.quest-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
}
.quest-bar {
  height: 6px;
  border-radius: 3px;
  background: rgba(255,255,255,0.10);
  overflow: hidden;
}
.quest-bar-fill {
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
  transition: width 0.3s ease;
}
.quest-reward {
  font-size: 13px;
  font-weight: 700;
  color: #f7c94f;
  white-space: nowrap;
}
.quest-reward.pending { color: var(--dim); opacity: 0.6; }
.quest-status {
  min-width: 44px;
  text-align: right;
  font-size: 13px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.quest-check { color: var(--accent); font-size: 18px; font-weight: 700; }
.quest-claim {
  min-width: 0;
  padding: 6px 14px;
  font-size: 13px;
  white-space: nowrap;
}

/* ==========================================================================
   Pack-info page — full hero roster grouped by rarity
   ========================================================================== */
/* Match the centered content column of the drop-rate cards (max-width 320px,
   margin auto) so the roster lines up with the rest of the page instead of
   stretching full-width and drifting to the left on wide screens. */
.packinfo-heroes-section {
  width: 100%;
  max-width: 320px;
  margin: 26px auto 0;
}
.packinfo-heroes-section > h3 {
  font-size: 15px;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
  color: var(--accent);
  text-align: center;
}
.packinfo-heroes-section > .packinfo-sub {
  margin-left: auto;
  margin-right: auto;
}
.packinfo-heroes { margin-top: 14px; }

.packinfo-heroes-group { margin-bottom: 16px; }
.packinfo-heroes-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}
.packinfo-heroes-rarity {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.packinfo-heroes-rarity.rarity-common    { color: #b0bec5; }
.packinfo-heroes-rarity.rarity-rare      { color: #90caf9; }
.packinfo-heroes-rarity.rarity-epic      { color: #e040fb; }
.packinfo-heroes-rarity.rarity-legendary { color: #ffd54f; }
.packinfo-heroes-count {
  font-size: 11px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.packinfo-heroes-count::before { content: "· "; }

.hero-chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
.hero-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
}
.hero-chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.hero-chip.rarity-common    { border-color: #546e7a; }
.hero-chip.rarity-rare      { border-color: #3949ab; }
.hero-chip.rarity-epic      { border-color: #7b1fa2; }
.hero-chip.rarity-legendary { border-color: #f57f17; }

/* ==========================================================================
   Off-field penalty warning — red pulsing edge glow + centred text shown while
   a hero is pushed ≥50% out of the playfield (driven by GameUI.setOffFieldWarning).
   pointer-events:none so it never blocks touch; z-index below .overlay (10) so
   pause/game-over screens cover it.
   ========================================================================== */
.offfield-warning {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.35s ease;
}
/* base intensity ramps 0.55 → 1.0 as the HP-drain deadline (5s) approaches. */
.offfield-warning.visible { opacity: calc(0.55 + 0.45 * var(--warn-intensity, 0)); }
.offfield-warning::before {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 40px 6px rgba(255,45,45,0.55),
              inset 0 0 110px 30px rgba(255,0,0,0.28);
  animation: offfieldPulse 1.1s ease-in-out infinite;
}
.offfield-warning.danger::before { animation-duration: 0.7s; }  /* pulse faster while draining */
.offfield-text {
  position: relative;
  color: rgba(255,70,70,0.82);
  font-family: var(--font);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 15px;
  line-height: 1.4;
  text-align: center;
  padding: 0 26px;
  text-shadow: 0 0 14px rgba(255,0,0,0.55);
}
@keyframes offfieldPulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/* ── PVP formation comparison (end screen) ──────────────────────────── */
.pvpc-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 62vh;
  overflow-y: auto;
}
.pvpc-row {
  display: grid;
  grid-template-columns: 38px 1fr 24px 1fr;
  align-items: stretch;
  gap: 8px;
}
.pvpc-head { align-items: center; }
.pvpc-col-name {
  text-align: center;
  font-weight: 700;
  color: var(--accent);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pvpc-pos {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  color: var(--dim);
  text-align: center;
  line-height: 1.15;
}
.pvpc-vs {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--dim);
}
.pvpc-hero {
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid var(--border);
  border-radius: 12px;
  padding: 8px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
}
.pvpc-empty {
  justify-content: center;
  color: var(--dim);
  font-size: 20px;
}
.pvpc-portrait {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.pvpc-name { font-weight: 700; font-size: 12px; }
.pvpc-meta { display: flex; gap: 6px; font-size: 10px; color: var(--dim); }
.pvpc-stars { color: #f2c14e; letter-spacing: -1px; }
.pvpc-stats {
  display: flex;
  gap: 8px;
  font-size: 11px;
  flex-wrap: wrap;
  justify-content: center;
}
.pvpc-stats span { color: var(--text); }
.pvpc-up   { color: var(--accent) !important; font-weight: 700; }
.pvpc-down { color: #e0574b !important; }

/* ── PVP variant picker (mode-select card) ──────────────────────────── */
.pvp-variants { display: flex; flex-direction: column; gap: 8px; }
.pvp-variant {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: rgba(255, 255, 255, 0.03);
  border: 0.5px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
  text-align: left;
  color: var(--text);
}
.pvp-variant:hover {
  border-color: var(--accent);
  background: rgba(93, 202, 165, 0.07);
}
.pvp-variant-name {
  font-weight: 800;
  font-size: 16px;
  color: var(--accent);
  min-width: 28px;
}
.pvp-variant-sub { flex: 1; font-size: 11px; color: var(--dim); }
.pvp-variant-q { font-size: 11px; color: var(--dim); white-space: nowrap; }
.pvp-qcount { font-weight: 700; color: var(--text); }

/* === Settings screen (#screenSettings) =====================================
   Migrated from the standalone settings.html. Everything is scoped to the screen
   id: the class names here (.switch, .user-info, …) are generic enough that a
   global rule would be a trap for later screens. `.settings-msg` is NOT redefined
   — it already lives with the profile-edit forms above and is shared. */
#screenSettings .settings-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  width: 100%;
  max-width: 360px;
}
#screenSettings .settings-card {
  width: 100%;
  box-sizing: border-box;
  background: linear-gradient(150deg, #1e1e1c 0%, #141412 100%);
  border: 0.5px solid #2a2a28;
  border-radius: 18px;
  padding: 28px 28px 24px;
}
/* The danger zone is a settings card, but shut it is only one line of text — the card's
   generous padding made that one line look like a button three times its own height.
   Needs the #id to outweigh `#screenSettings .settings-card` above. Opening it gives the
   content back its breathing room. */
#screenSettings .danger-zone        { padding: 12px 20px; }
#screenSettings .danger-zone[open]  { padding: 16px 22px 20px; }

#screenSettings .settings-card h2 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
}
#screenSettings .user-info {
  font-size: 12px;
  color: #666;
  letter-spacing: 0.06em;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 0.5px solid #2a2a28;
}
#screenSettings .user-info strong { color: var(--text); }
#screenSettings .current-value {
  font-size: 11px;
  color: #555;
  letter-spacing: 0.06em;
  margin-bottom: 16px;
}
#screenSettings .current-value span { color: #888; }

/* Forms */
#screenSettings form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}
#screenSettings form label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #555;
}
#screenSettings form input {
  background: #111110;
  border: 0.5px solid #2a2a28;
  border-radius: 12px;
  color: var(--text);
  padding: 10px 12px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.15s, box-shadow 0.15s;
}
#screenSettings form input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(93,202,165,0.18);
}
/* A password manager autofills "current password", and Chromium then paints its own
   pale background over that field — glaring next to the dark ones around it. An
   autofilled input ignores `background`; only a large inset shadow covers it, and
   the text needs -webkit-text-fill-color rather than `color`. The absurd transition
   delay is the standard trick to stop Chromium fading its colour in at all. */
#screenSettings form input:-webkit-autofill,
#screenSettings form input:-webkit-autofill:hover,
#screenSettings form input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #111110 inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 9999s ease-in-out 0s;
}
/* Focus ring would be swallowed by the inset fill above — restate it alongside. */
#screenSettings form input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #111110 inset, 0 0 0 1px rgba(93,202,165,0.18);
}
/* Same for Firefox, via the standard pseudo-class (it tints autofilled fields too).
   Deliberately a SEPARATE block: a browser that does not know one of the two
   selectors would otherwise drop the whole rule along with it. */
#screenSettings form input:autofill {
  box-shadow: 0 0 0 1000px #111110 inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  filter: none;
}
#screenSettings form input:autofill:focus {
  box-shadow: 0 0 0 1000px #111110 inset, 0 0 0 1px rgba(93,202,165,0.18);
}
#screenSettings form .btn-primary {
  width: 100%;
  text-align: center;
  margin-top: 4px;
}

/* Toggle rows (privacy + display) */
#screenSettings .privacy-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 0.5px solid #2a2a28;
}
#screenSettings .privacy-row:last-of-type { border-bottom: none; }
#screenSettings .privacy-label { font-size: 13px; color: var(--text); letter-spacing: 0.04em; }
#screenSettings .switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; }
#screenSettings .switch input { opacity: 0; width: 0; height: 0; }
#screenSettings .switch .slider {
  position: absolute; inset: 0; cursor: pointer;
  background: #2a2a28; border-radius: 24px; transition: background 0.15s;
}
#screenSettings .switch .slider::before {
  content: ""; position: absolute; height: 18px; width: 18px; left: 3px; top: 3px;
  background: #888; border-radius: 50%; transition: transform 0.15s, background 0.15s;
}
#screenSettings .switch input:checked + .slider { background: rgba(93,202,165,0.35); }
#screenSettings .switch input:checked + .slider::before { transform: translateX(20px); background: var(--accent); }
#screenSettings .switch input:focus-visible + .slider { box-shadow: 0 0 0 2px rgba(93,202,165,0.4); }

/* Master volume slider */
#screenSettings .sound-row { display: flex; align-items: center; justify-content: space-between; padding: 2px 0 12px; }
#screenSettings .sound-value { font-size: 13px; color: var(--accent); font-variant-numeric: tabular-nums; }
#screenSettings .sound-slider {
  width: 100%; -webkit-appearance: none; appearance: none;
  height: 6px; border-radius: 3px; background: #2a2a28; outline: none;
}
#screenSettings .sound-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none;
}
#screenSettings .sound-slider::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none;
}
#screenSettings .sound-slider:focus-visible { box-shadow: 0 0 0 2px rgba(93,202,165,0.4); }

/* === Equipment screen ===================================================== */
/* Item cards reuse .hero-card (rarity gradients, gold "in use" border), so only
   the item-specific bits live here. */

/* Sticky, exactly like the hero screen's formation header: while the inventory scrolls,
   the heroes you are equipping have to stay on screen — dragging an item onto a hero you
   can no longer see is impossible, and even tapping means scrolling back and forth.
   Same padding trick: the header itself provides the clearance for the fixed user bar, so
   its opaque box pins seamlessly at top: 0 (see .heroes-header). */
.equip-header {
  width: 100%;
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
  position: sticky;
  top: 0;
  z-index: 30;
  align-self: stretch;
  background: var(--bg);
  margin: 0 -20px 14px;
  padding: max(58px, calc(env(safe-area-inset-top, 0px) + 46px)) 20px 12px;
  box-shadow: 0 6px 14px -8px rgba(0,0,0,0.7);
}
/* The header now provides the top clearance, so the screen itself must not add it. */
#screenEquipment { padding-top: 0; }
.equip-header > h2 {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.22em;
  color: var(--dim); margin-bottom: 0;
}

/* The formation, as a row of equip targets. */
/* The formation must stay ONE row, on every phone: five heroes wrapping onto a second
   line stop reading as a formation. So the cards share the available width instead of
   claiming a fixed one — they shrink together (down to a floor) rather than breaking. */
.equip-heroes {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  justify-content: center;
  align-items: stretch;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
}
.equip-hero {
  position: relative;
  flex: 1 1 0;           /* equal share of the row … */
  min-width: 0;          /* … and allowed to shrink below its content width */
  max-width: 84px;       /* on a wide screen they stay hero-card sized, not stretched */
  padding: 8px 3px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  text-align: center; cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.equip-hero.active {
  border-color: var(--accent);
  box-shadow: 0 0 10px rgba(93,202,165,0.25);
}
.equip-hero-avatar {
  width: 100%; max-width: 44px; aspect-ratio: 1 / 1;
  margin: 0 auto 4px;
  border-radius: 10px; overflow: hidden;
}
.equip-hero-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.equip-hero-name {
  display: block; font-size: 10px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Narrow phones: buy the width back from the paddings and the label before the avatars
   have to get tiny. */
@media (max-width: 380px) {
  .equip-heroes { gap: 4px; }
  .equip-hero { padding: 6px 2px; }
  .equip-hero-name { font-size: 9px; }
}

/* The one item slot per hero: empty socket, or the item's icon. */
.equip-socket {
  margin-top: 6px;
  width: 30px; height: 30px; border-radius: 8px;
  background: #14140f;
  border: 1px dashed var(--border);
  color: var(--dim); font-size: 15px; line-height: 1;
  cursor: pointer;
}
.equip-socket.filled { border-style: solid; color: var(--text); }
.equip-socket.filled.rarity-common    { border-color: rgba(84,110,122,0.75);  background: #1f2d33; }
.equip-socket.filled.rarity-rare      { border-color: rgba(79,195,247,0.65);  background: #141e6b; }
.equip-socket.filled.rarity-epic      { border-color: rgba(206,147,216,0.65); background: #2e0850; }
.equip-socket.filled.rarity-legendary { border-color: rgba(247,201,79,0.75);  background: #3d1e00; }

/* Slot filters above the inventory. */
.equip-filters {
  display: flex; flex-wrap: wrap; gap: 6px;
  justify-content: center; margin-bottom: 12px;
}
.equip-filter {
  padding: 5px 11px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border);
  color: var(--dim); font-family: var(--font); font-size: 11px; cursor: pointer;
}
.equip-filter.active { border-color: var(--accent); color: var(--accent); }

/* Inventory card internals. */
.item-card .item-icon { font-size: 26px; line-height: 1; margin-bottom: 6px; }
.item-card .item-effects {
  margin-top: 6px; font-size: 10px; line-height: 1.5; color: var(--text); opacity: 0.85;
}
.item-card .item-worn { margin-top: 6px; font-size: 9px; color: #ffd54f; }

.equip-empty {
  color: var(--dim); font-size: 12px; line-height: 1.7;
  text-align: center; max-width: 320px; margin: 8px auto;
}
.item-card .item-power { margin-top: 6px; font-size: 10px; color: var(--dim); }
/* A rolled item may carry a curse: a negative affix bought with a bigger bonus. It has to
   read as a drawback at a glance, not blend into the bonus list. Used on the equipment
   cards AND in the PVP end-screen comparison. */
.item-curse { color: #e05555; }

/* PVP end screen: the item each hero fought with. Items feed into the stats above it, so
   the comparison cannot be read without them — a hero winning on damage may simply be
   wearing a ring. */
.pvpc-item {
  margin-top: 6px; padding: 5px 6px;
  border-top: 1px solid rgba(255,255,255,0.08);
  font-size: 9px; line-height: 1.5; text-align: center;
}
.pvpc-item-name { display: block; color: var(--text); font-weight: 700; }
.pvpc-item-fx   { display: block; color: var(--dim); }
.pvpc-item-none { color: var(--dim); opacity: 0.6; }
.pvpc-item.rarity-common    .pvpc-item-name { color: #b0bec5; }
.pvpc-item.rarity-rare      .pvpc-item-name { color: #4fc3f7; }
.pvpc-item.rarity-epic      .pvpc-item-name { color: #ce93d8; }
.pvpc-item.rarity-legendary .pvpc-item-name { color: #f7c94f; }

/* === Equipment drag & drop ================================================ */
/* Same gesture vocabulary as the hero screen: a ghost follows the finger, the hero under
   it lights up, and dragging a worn item away from every hero dims the formation to say
   "let go here and it goes back to the inventory". */
.drag-ghost-item {
  display: flex; align-items: center; justify-content: center;
  background: var(--surface);
  border: 1px solid var(--accent);
  font-size: 26px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.55);
}
.equip-hero.drop-target {
  border-color: var(--accent) !important;
  box-shadow: 0 0 16px rgba(93,202,165,0.5);
  transform: scale(1.06);
}
.equip-heroes.dnd-removing .equip-hero { opacity: 0.45; }

/* The item icon must not swallow the gesture (same reason as the hero portraits: the
   browser would start its own native drag on the image/emoji). */
.equip-hero-avatar img,
.item-card .item-icon { pointer-events: none; }

.equip-hero { cursor: grab; }
body.dnd-active .equip-hero,
body.dnd-active .item-card { cursor: grabbing; }
/* Freeze the inventory while an item is "in hand", so the drag cannot scroll the list out
   from under the pointer. */
body.dnd-active #screenEquipment { overflow: hidden; touch-action: none; }
