
  :root {
    --bg-0: #0a0612;
    --bg-1: #14091f;
    --bg-2: #1d0f2e;
    --ink: #dfc9f2;
    --ink-dim: #b6a7cf;
    --ink-faint: #6b5a85;
    --neon: #ff3da6;
    --neon-2: #7b5cff;
    --neon-3: #00e6c3;
    --gold: #ffce4f;
    --danger: #ff5764;
    --card: #1a0f2b;
    --card-2: #25153d;
    --line: #2c1c44;
    --shadow: 0 12px 48px rgba(0,0,0,0.55);
    --px: "Press Start 2P", monospace;
    --term: "VT323", monospace;
  }

  * { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; image-rendering: pixelated; }
  html, body { height: 100%; }
  body {
    font-family: var(--term);
    font-size: 18px;
    /* Solid bg-0 only. Removed the two radial gradients that created
       visible compounded bands on wide screens / when scrolling. The
       body::after vignette still darkens corners for depth. */
    background: var(--bg-0);
    background-attachment: fixed;
    color: var(--ink);
    min-height: 100vh;
    overflow-x: hidden;
    line-height: 1.3;
    text-shadow: 0 0 1px rgba(244,238,251,0.3);
  }
  /* CRT scanlines + vignette removed entirely — the cabinet looks
     cleaner without the overlay. */
  h1, h2, h3, h4, .px { font-family: var(--px); letter-spacing: 0.5px; line-height: 1.4; }

  /* ---------- Layout ---------- */
  #app {
    max-width: 480px;
    margin: 0 auto;
    min-height: 100vh;
    padding: 0 0 96px;
    position: relative;
  }

  .screen { padding: 20px 18px 24px; animation: fadeUp .35s ease; }
  @keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

  .top-bar {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 18px 12px;
    position: sticky; top: 0; z-index: 10;
    background: linear-gradient(180deg, var(--bg-0) 70%, transparent);
    gap: 8px;
  }
  .top-bar .brand-side {
    display: flex; align-items: center; gap: 10px;
    min-width: 0;          /* let the brand text shrink-truncate */
    flex: 1 1 auto;
    overflow: hidden;
  }
  .top-bar .brand {
    font-family: var(--px);
    /* Sized + spaced so the longest random handle (14 chars) fits between
       the avatar and the stats cluster on a 480px viewport. Truncates
       with ellipsis if a custom user name runs longer. */
    font-size: 11px;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 rgba(0,0,0,0.6);
    letter-spacing: 0.5px;
    cursor: pointer;
    user-select: none;
    transition: transform .06s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1 1 auto;
    min-width: 0;
  }
  .top-bar .brand:active { transform: translate(1px, 1px); }
  .top-bar .stats {
    display: flex; gap: 8px; align-items: center;
    font-family: var(--px); font-size: 9px; color: var(--ink-dim);
  }
  .pill {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 6px 10px; border-radius: 0;
    background: var(--card);
    border: 2px solid var(--line);
    box-shadow: 3px 3px 0 #000;
    font-family: var(--px); font-size: 9px; color: var(--ink);
    min-width: 64px; height: 30px; box-sizing: border-box;
  }
  .pill .dot { width: 8px; height: 8px; background: var(--neon-3); border-radius: 0; box-shadow: 0 0 6px var(--neon-3); }

  /* ---------- Bottom Nav ---------- */
  nav.tabs {
    position: fixed; bottom: 0; left: 0; right: 0;
    max-width: 480px; margin: 0 auto;
    /* Grid auto-fits whatever number of buttons the tab bar renders —
       no manual count to keep in sync when tabs come or go (e.g.
       dev-mode adding/removing the Ideas tab). */
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    background: #0a0410;
    border-top: 4px solid var(--neon-2);
    box-shadow: 0 -4px 0 #000;
    z-index: 20;
  }
  nav.tabs button {
    background: none; border: none; color: var(--ink-faint);
    padding: 12px 4px 16px;
    font-family: var(--px); font-size: 8px;
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    cursor: pointer; transition: color .15s;
    border-right: 2px solid var(--line);
  }
  nav.tabs button:last-child { border-right: none; }
  nav.tabs button .ic { font-size: 22px; line-height: 1; }
  /* Pixel-art PNG tab icons render at the same visual height as emoji
     glyphs but use crisp-pixel scaling and a tighter vertical fit. */
  nav.tabs button .ic .tab-img {
    width: 28px; height: 28px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
    margin: -3px 0;
  }
  nav.tabs button.active { color: var(--gold); background: rgba(255,206,79,0.08); }
  nav.tabs button.active .ic { filter: drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 2px var(--gold)); }
  /* NEW badge for tabs (e.g. bag has new items) */
  nav.tabs button .ic { position: relative; }
  nav.tabs button .tab-badge {
    position: absolute;
    top: -8px; right: -14px;
    background: var(--neon);
    color:var(--ink);
    font-family: var(--px); font-size: 7px;
    padding: 3px 5px;
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    text-shadow: 1px 1px 0 #000;
    letter-spacing: 0.5px;
    line-height: 1;
    animation: blink 1.4s steps(2) infinite;
    pointer-events: none;
  }

  /* ---------- Buttons (chunky pixel) ---------- */
  .btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 8px; padding: 14px 16px; border-radius: 0;
    font-family: var(--px); font-size: 11px; letter-spacing: 0.5px;
    border: 3px solid #000;
    background: var(--card); color: var(--ink);
    cursor: pointer; transition: transform .06s, box-shadow .06s;
    width: 100%;
    box-shadow:
      inset -3px -3px 0 rgba(0,0,0,0.5),
      inset 3px 3px 0 rgba(255,255,255,0.1),
      4px 4px 0 #000;
    text-transform: uppercase;
  }
  .btn:active {
    transform: translate(3px, 3px);
    box-shadow:
      inset -3px -3px 0 rgba(0,0,0,0.5),
      inset 3px 3px 0 rgba(255,255,255,0.1),
      1px 1px 0 #000;
  }
  .btn.primary {
    background: var(--neon);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }
  .btn.ghost {
    background: var(--card);
  }
  .btn.danger { background: var(--danger); color:var(--ink); text-shadow: 1px 1px 0 #000; }
  .btn.gold { background: var(--gold); color: #2a1500; }
  .btn.sm { padding: 9px 11px; font-size: 9px; }
  .btn:disabled { opacity: 0.35; cursor: not-allowed; }
  .row { display: flex; gap: 10px; }
  .row > .btn { flex: 1; }

  /* ---------- Cards ---------- */
  .card {
    background: var(--card);
    border: 3px solid #000;
    box-shadow:
      inset -2px -2px 0 rgba(0,0,0,0.5),
      inset 2px 2px 0 rgba(255,255,255,0.06),
      4px 4px 0 #000;
    border-radius: 0;
    padding: 16px;
    margin-bottom: 16px;
  }
  .card h3 { font-size: 12px; margin-bottom: 10px; color: var(--gold); }
  .card p { color: var(--ink-dim); font-size: 16px; }

  /* ---------- Home ---------- */
  .hero {
    margin: 4px 0 22px;
    padding: 22px 18px;
    border: 4px solid #000;
    background:
      repeating-linear-gradient(45deg, rgba(255,255,255,0.025) 0 6px, transparent 6px 12px),
      linear-gradient(135deg, #2a1247, #45125f);
    box-shadow: inset 0 0 0 2px var(--neon-2), 6px 6px 0 #000;
    position: relative; overflow: hidden;
    text-align: center;
  }
  /* hero-slim (build 250): a compact logo strip so the Party/Solo
     play cards sit at the top of the screen, not below the fold.
     Build 252 — no box: just the transparent logo, the tagline and
     the floating sparkles sitting on the page background. */
  .hero.hero-slim {
    margin: 2px 0 14px; padding: 6px 0 10px;
    border: 0; background: none; box-shadow: none;
    overflow: visible;
  }
  /* Logo spans the full content width — edge to edge. */
  .hero.hero-slim .hero-scroll-img { max-width: 100%; }
  /* Insert-coin easter egg — demoted from the hero to a quiet line at
     the bottom of the home screen so it stops competing with PLAY. */
  .coin-egg {
    display: block; text-align: center;
    margin: 18px 0 4px;
    font-family: var(--px); font-size: 9px;
    color: var(--ink-faint); letter-spacing: 1px;
    cursor: pointer; opacity: 0.5;
    transition: opacity 0.2s;
  }
  .coin-egg:hover { opacity: 0.9; }
  .hero h1 {
    font-size: 18px; line-height: 1.6; margin: 0;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 4px 4px 0 #000;
    text-align: center;
  }
  /* Pixel-art scroll banner that wraps the QUEST IRL title. Two
     wooden cap rolls flank a parchment paper center. The whole
     banner sways slowly side to side so the title rides on a gentle
     pendulum motion — the inner text moves with it because both
     caps and paper are flex children of the same container. */
  /* Single pixel-art QUEST IRL logo image (replaces the CSS-built
     scroll banner). Same gentle pendulum sway animation rides the
     <img> directly. */
  .hero-scroll-img {
    display: block;
    /* Negative bottom margin pulls the tag line up — the source PNG
       has its own transparent margin around the artwork, which left a
       visible empty gap below the scroll. */
    margin: 0 auto -8px;
    width: 100%;
    max-width: 380px;
    height: auto;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    user-select: none;
    -webkit-user-drag: none;
    transform-origin: 50% 0;
    animation: heroScrollSway 5.6s ease-in-out infinite;
    will-change: transform;
    /* Soft purple-pink glow matching the cabinet's magical aesthetic. */
    filter:
      drop-shadow(0 0 6px rgba(255,61,166,0.45))
      drop-shadow(0 0 12px rgba(180,108,255,0.3));
  }
  @keyframes heroScrollSway {
    0%   { transform: translate(0, 0)        rotate(-1.4deg); }
    25%  { transform: translate(-2px, -1px)  rotate(-0.4deg); }
    50%  { transform: translate(0, 0)        rotate(1.4deg); }
    75%  { transform: translate(2px, -1px)   rotate(0.4deg); }
    100% { transform: translate(0, 0)        rotate(-1.4deg); }
  }
  .hero .tag {
    color: var(--ink); font-size: 18px;
    font-family: var(--term);
  }
  /* Magical firefly sparkles scattered across the hero box. Each one
     fades in and out on its own slow timer so the hero feels alive
     without competing with the scroll sway / INSERT COIN blink. */
  .hero-sparkle {
    position: absolute;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      rgba(255,206,79,1) 0%,
      rgba(255,61,166,0.6) 45%,
      rgba(180,108,255,0.2) 75%,
      transparent 100%
    );
    pointer-events: none;
    opacity: 0;
    filter: blur(0.5px);
    animation: heroSparkleTwinkle 5s ease-in-out infinite;
  }
  .hero-sparkle.hs-1 { top: 14%; left: 6%;  width: 5px; height: 5px; animation-delay: 0s;   }
  .hero-sparkle.hs-2 { top: 68%; left: 12%; width: 7px; height: 7px; animation-delay: 1.4s; }
  .hero-sparkle.hs-3 { top: 22%; left: 88%; width: 6px; height: 6px; animation-delay: 2.6s; animation-duration: 6s; }
  .hero-sparkle.hs-4 { top: 78%; left: 82%; width: 4px; height: 4px; animation-delay: 0.9s; animation-duration: 4.5s; }
  .hero-sparkle.hs-5 { top: 48%; left: 3%;  width: 5px; height: 5px; animation-delay: 3.4s; animation-duration: 5.5s; }
  @keyframes heroSparkleTwinkle {
    0%, 100% { opacity: 0;    transform: scale(0.5); }
    45%      { opacity: 0.9;  transform: scale(1.15); }
    55%      { opacity: 0.9;  transform: scale(1.15); }
  }
  .hero .blink {
    display: block; margin-top: 12px;
    font-family: var(--px); font-size: 10px; color: var(--neon-3);
    animation: blink 1s steps(2) infinite;
  }
  @keyframes blink { 50% { opacity: 0; } }

  /* ---------- Mode picker (Party / Solo) — BIG CTA ---------- */
  .mode-grid {
    display: grid; grid-template-columns: 1fr; gap: 16px;
    margin: 8px 0 22px;
  }
  .mode-card {
    position: relative;
    border: 4px solid #000;
    padding: 22px 20px;
    cursor: pointer;
    transition: transform .08s;
    overflow: hidden;
    box-shadow:
      inset 0 0 0 2px rgba(255,255,255,0.15),
      inset -4px -4px 0 rgba(0,0,0,0.45),
      6px 6px 0 #000;
  }
  .mode-card:active { transform: translate(4px, 4px); box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), inset -4px -4px 0 rgba(0,0,0,0.45), 2px 2px 0 #000; }
  .mode-card::before {
    content: ''; position: absolute; inset: 0;
    background: repeating-linear-gradient(
      0deg,
      rgba(255,255,255,0.04) 0 2px,
      transparent 2px 5px
    );
    pointer-events: none;
  }
  .mode-card.party {
    background:
      radial-gradient(circle at 80% 30%, rgba(255,206,79,0.25), transparent 55%),
      linear-gradient(160deg, #ff3da6, #7b5cff);
    animation: pulsePink 2s ease-in-out infinite;
  }
  .mode-card.solo {
    background:
      radial-gradient(circle at 20% 30%, rgba(255,61,166,0.25), transparent 55%),
      linear-gradient(160deg, #00e6c3, #1e6bd8);
    animation: pulseTeal 2s ease-in-out infinite;
  }
  @keyframes pulsePink {
    0%,100% { box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), inset -4px -4px 0 rgba(0,0,0,0.45), 6px 6px 0 #000, 0 0 0 0 rgba(255,61,166,0.7); }
    50%     { box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), inset -4px -4px 0 rgba(0,0,0,0.45), 6px 6px 0 #000, 0 0 24px 6px rgba(255,61,166,0.55); }
  }
  @keyframes pulseTeal {
    0%,100% { box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), inset -4px -4px 0 rgba(0,0,0,0.45), 6px 6px 0 #000, 0 0 0 0 rgba(0,230,195,0.7); }
    50%     { box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), inset -4px -4px 0 rgba(0,0,0,0.45), 6px 6px 0 #000, 0 0 24px 6px rgba(0,230,195,0.55); }
  }
  .mode-card .ic {
    font-size: 64px; line-height: 1;
    text-shadow: 4px 4px 0 #000;
    display: block; margin-bottom: 10px;
    animation: bob 1.4s ease-in-out infinite;
  }
  /* Pixel-art SVG icon variant — chunky, no antialiasing, with the
     same offset drop shadow as the emoji icons. */
  .mode-card .ic.ic-pixel {
    font-size: 0; line-height: 0;
    /* Fixed-height icon row + bottom-anchored art so the Party and
       Solo cards stay identical height — the Solo versus-art layout
       box (110px) is taller than the Party trio's default 72px box. */
    height: 110px;
    display: flex; align-items: flex-end;
    filter: drop-shadow(4px 4px 0 #000);
    /* Slower, gentler float than the default emoji-card bob. */
    animation: pixelFloat 3.2s ease-in-out infinite;
  }
  @keyframes pixelFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-7px); }
  }
  .mode-card .ic.ic-pixel svg,
  .mode-card .ic.ic-pixel .ic-pixel-img {
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    width: 72px; height: 72px;
    object-fit: contain;
    display: block;
  }
  /* Solo's versus-art uses a wider/taller box than the Party trio;
     the fixed 110px row height on .ic-pixel above keeps both cards
     the same height regardless of each icon's box size. */
  .mode-card .ic.ic-pixel .ic-pixel-img {
    /* Default: just upscale; per-icon transforms below add nudges. */
    transform: scale(2.25);
    transform-origin: center center;
  }
  .mode-card .ic.ic-pixel .ic-pixel-img.ic-img-pvp {
    /* Adventurer trio — keep the nudge-right so the group sits over
       the word "PARTY" but pull the scale down slightly so the trio
       doesn't dominate the card. */
    transform: translateX(34px) scale(1.85);
  }
  .mode-card .ic.ic-pixel .ic-pixel-img.ic-img-solo {
    /* Versus composition — left-aligned so the visible art starts
       above the "S" of SOLO and ends around the "N" of RUN, sitting
       over the heading like the party trio sits over PARTY. Width
       roughly matches the heading text; no scale because the box is
       already at the right size for the source aspect. */
    width: 200px;
    height: 110px;
    margin: 0;
    transform: translate(-12px, 12px);
    transform-origin: left bottom;
  }
  /* Both mode-card icons bob in sync — no animation-delay so the
     party trio and solo versus art rise/fall on the same beat. */
  @keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
  .mode-card h4 {
    font-size: 22px;
    color:var(--ink);
    text-shadow: 3px 3px 0 #000;
    margin-bottom: 6px;
  }
  /* Avatar sitters — small emojis perched on top of the mode-card
     headings. Each emoji rocks back and forth like it's idly swinging
     its legs over the edge. Multiple sitters share one .sitter-row
     above the heading; staggered animation delays so they're not in
     phase with each other. */
  .mode-card .mode-h4 {
    position: relative;
    /* No extra padding — the row is absolute and sits above the text. */
  }
  .mode-card .sitter-row {
    position: absolute;
    left: 0; right: 0;
    bottom: calc(100% + 4px);     /* sit just above the heading text */
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: 14px;
    pointer-events: none;
    z-index: 2;
  }
  .mode-card .sitter-row.solo { gap: 0; }
  .mode-card .run-sitter {
    display: inline-block;
    line-height: 1;
    transform-origin: 50% 100%;   /* swing pivots from the bum */
    animation: sitterWaddleA 0.9s ease-in-out infinite;
  }
  .mode-card .run-sitter.sitter-1 {
    animation-name: sitterWaddleB;
    animation-duration: 0.85s;
  }
  .mode-card .run-sitter.sitter-2 {
    animation-name: sitterWaddleA;
    animation-duration: 1.05s;
    animation-delay: 0.18s;
  }
  .mode-card .run-sitter .sitter-emoji {
    display: inline-block;
    font-size: 15px;
    line-height: 1;
    text-shadow: 2px 2px 0 #000;
    /* Tiny vertical bob so the emoji also bounces slightly while it
       rocks left-right — sells the "kicking legs" idea without needing
       separate leg sprites. */
    animation: sitterBob 1.1s ease-in-out infinite;
  }
  .mode-card .run-sitter.sitter-1 .sitter-emoji { animation-delay: 0.22s; }
  .mode-card .run-sitter.sitter-2 .sitter-emoji { animation-delay: 0.45s; }
  @keyframes sitterWaddleA {
    0%, 100% { transform: rotate(-7deg); }
    50%      { transform: rotate(7deg); }
  }
  @keyframes sitterWaddleB {
    0%, 100% { transform: rotate(8deg); }
    50%      { transform: rotate(-8deg); }
  }
  @keyframes sitterBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-2px); }
  }
  .mode-card p {
    color:var(--ink);
    font-family: var(--term); font-size: 18px;
    text-shadow: 2px 2px 0 rgba(0,0,0,0.6);
  }
  /* Corner-ribbon style: diagonal banner clipped by the card's overflow:hidden,
     sitting across the top-right corner reading top-left → bottom-right. */
  .mode-card .badge {
    position: absolute;
    top: 18px;
    right: -42px;
    width: 150px;
    text-align: center;
    background: var(--gold);
    color: #2a1500;
    font-family: var(--px); font-size: 9px;
    letter-spacing: 3px;
    padding: 6px 0;
    border-top: 2px solid #000;
    border-bottom: 2px solid #000;
    box-shadow: 0 3px 0 rgba(0,0,0,0.55);
    transform: rotate(45deg);
    transform-origin: center;
    text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
    /* Match the 2s tempo of pulsePink / pulseTeal on .mode-card so the
       ribbon breathes in time with the buttons it sits on. */
    animation: ribbonPulse 2s ease-in-out infinite;
    pointer-events: none;
  }
  @keyframes ribbonPulse {
    /* Combine rotate (the corner-banner angle) with scale so the START
       text breathes — shrinks during the dim phase, grows back as it
       brightens. Same 2s tempo as the mode-card glow underneath. */
    0%,100% { transform: rotate(45deg) scale(0.92); filter: brightness(0.9);  box-shadow: 0 3px 0 rgba(0,0,0,0.55); }
    50%     { transform: rotate(45deg) scale(1.06); filter: brightness(1.25); box-shadow: 0 3px 0 rgba(0,0,0,0.55), 0 0 18px rgba(255,206,79,0.8); }
  }
  .mode-card .arrow {
    position: absolute; right: 16px; bottom: 18px;
    font-family: var(--px); font-size: 16px; color:var(--ink);
    text-shadow: 2px 2px 0 #000;
    animation: nudge 0.8s ease-in-out infinite;
  }
  @keyframes nudge { 0%,100% { transform: translateX(0); } 50% { transform: translateX(6px); } }

  /* ---------- Setup wizard ---------- */
  .step-head { margin-bottom: 14px; }
  .step-head .crumb { font-family: var(--px); font-size: 9px; color: var(--neon-3); letter-spacing: 1.5px; text-transform: uppercase; }
  .step-head h2 { font-size: 16px; margin-top: 8px; color: var(--gold); text-shadow: 2px 2px 0 #000; }
  .step-head .sub { color: var(--ink-dim); font-family: var(--term); font-size: 17px; margin-top: 6px; }
  .progress {
    display: flex; gap: 4px; margin: 14px 0 20px;
  }
  .progress .seg { flex: 1; height: 10px; border: 2px solid #000; background: var(--bg-1); box-shadow: inset 1px 1px 0 rgba(255,255,255,0.05); }
  .progress .seg.on { background: var(--neon-3); box-shadow: inset -1px -1px 0 rgba(0,0,0,0.5), 0 0 8px var(--neon-3); }

  textarea, input[type="text"] {
    width: 100%; padding: 12px 14px;
    border: 3px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4);
    background: var(--bg-1); color: var(--ink);
    font-family: var(--term); font-size: 18px; outline: none;
  }
  textarea { min-height: 84px; resize: vertical; }
  textarea:focus, input:focus { background: #1f1235; }

  /* Themed range slider — chunky pixel track with a neon thumb. */
  input[type="range"].arcade-range {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 22px; padding: 0;
    background: transparent; outline: none; cursor: pointer;
  }
  input[type="range"].arcade-range::-webkit-slider-runnable-track {
    height: 10px;
    background: var(--bg-1);
    border: 2px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
  }
  input[type="range"].arcade-range::-moz-range-track {
    height: 10px;
    background: var(--bg-1);
    border: 2px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
  }
  input[type="range"].arcade-range::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 22px;
    margin-top: -8px;
    background: var(--neon);
    border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    cursor: pointer;
  }
  input[type="range"].arcade-range::-moz-range-thumb {
    width: 18px; height: 22px; border-radius: 0;
    background: var(--neon);
    border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    cursor: pointer;
  }
  input[type="range"].arcade-range::-moz-range-progress {
    height: 10px;
    background: var(--neon-3);
    box-shadow: inset 0 0 6px rgba(0,230,195,0.5);
  }

  /* Themed dropdown — pixel border, neon caret, no native chrome. */
  select.arcade-select {
    -webkit-appearance: none; appearance: none;
    width: 100%; padding: 10px 32px 10px 12px;
    background: var(--card) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><polygon points='0,0 10,0 5,6' fill='%2300e6c3'/></svg>") no-repeat right 12px center;
    background-size: 10px 6px;
    border: 3px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    color: var(--ink); font-family: var(--term); font-size: 15px;
    outline: none; cursor: pointer;
  }
  select.arcade-select:focus { background-color: #1f1235; }
  select.arcade-select option {
    background: var(--bg-1); color: var(--ink);
    font-family: var(--term);
  }

  .chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .chip {
    padding: 8px 12px; border-radius: 0;
    background: var(--card); border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    font-family: var(--px); font-size: 9px; color: var(--ink); cursor: pointer;
    user-select: none; transition: transform .06s;
    display: inline-flex; align-items: center; gap: 6px;
  }
  .chip .btn-ic, .chip .vibe-ic, .chip .place-ic { margin: 0; }
  .chip[data-ctx="custom"]:not(.on):not(.disabled) {
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000, 0 0 10px rgba(79, 227, 214, 0.35);
  }
  .chip:active { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 0 0 0 #000; }
  .chip.on { background: var(--neon); color:var(--ink); text-shadow: 1px 1px 0 #000; }
  .chip.deny.on { background: var(--danger); color:var(--ink); text-shadow: 1px 1px 0 #000; }
  /* Allow chips — positive permissions. Gold border + faint glow when
     off, full gold fill when on. Visually distinct from the deny chips
     (red on) so the player reads "this UNLOCKS something" instead of
     "this restricts something". */
  .chip.allow {
    border-color: var(--gold);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000, 0 0 8px rgba(245, 194, 66, 0.18);
  }
  .chip.allow.on {
    background: var(--gold); color: #1a0d28; text-shadow: 1px 1px 0 rgba(255,255,255,0.25);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000, 0 0 14px rgba(245, 194, 66, 0.55);
  }
  /* Vibe chips that are currently un-pickable (max-3 cap reached, or
     conflict with an already-selected vibe). Still clickable so the
     click handler can fire a toast explaining why. */
  .chip.blocked { opacity: 0.35; filter: grayscale(0.5); cursor: not-allowed; }
  /* Armed-item chips on the Review screen */
  .chip.arm-chip {
    background: var(--bg-1);
    border-color: var(--neon-3);
    color: var(--neon-3);
  }
  .chip.armed-chip {
    background: var(--gold);
    color: #2a1500;
    border-color: #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.3), 2px 2px 0 var(--neon), 4px 4px 0 #000;
    text-shadow: none;
  }

  .difficulty-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .diff {
    padding: 14px; border-radius: 0;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 4px 4px 0 #000;
    cursor: pointer; transition: transform .08s;
  }
  .diff:active { transform: translate(2px,2px); }
  .diff.on { background: var(--neon-2); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 4px 4px 0 var(--gold); }
  .diff h4 { font-size: 11px; margin-bottom: 6px; color: var(--gold); }
  .diff .pill-sm { font-family: var(--px); font-size: 8px; color: var(--neon-3); }
  .diff p { font-family: var(--term); font-size: 16px; color: var(--ink-dim); margin-top: 6px; }
  .diff.on h4 { color:var(--ink); text-shadow: 2px 2px 0 #000; }
  .diff.on p { color:var(--ink); }

  /* ---------- Unhinged Mode toggle ---------- */
  .unhinged-toggle {
    display: flex; align-items: center; gap: 14px;
    padding: 14px;
    background: linear-gradient(135deg, #1a0530 0%, #0a0212 100%);
    border: 4px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5),
                inset 2px 2px 0 rgba(255,255,255,0.05),
                4px 4px 0 #000;
    cursor: pointer;
    margin-bottom: 18px;
    position: relative;
    overflow: hidden;
    transition: transform 0.1s steps(2);
  }
  .unhinged-toggle:active { transform: translate(1px, 1px); }
  .unhinged-toggle::before {
    content: '';
    position: absolute; inset: 0;
    background: repeating-linear-gradient(
      135deg,
      transparent 0px, transparent 6px,
      rgba(255,255,255,0.02) 6px, rgba(255,255,255,0.02) 7px
    );
    pointer-events: none;
  }
  .unhinged-toggle.on {
    background: linear-gradient(135deg, #2a0848 0%, #4a0a52 50%, #1a0530 100%);
    border-color: var(--neon);
    box-shadow: inset 0 0 0 2px var(--neon),
                inset -2px -2px 0 rgba(0,0,0,0.5),
                4px 4px 0 #000,
                0 0 24px rgba(255,61,166,0.4);
    animation: unhingedPulse 2.4s steps(8) infinite;
  }
  @keyframes unhingedPulse {
    0%, 100% { box-shadow: inset 0 0 0 2px var(--neon), inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 #000, 0 0 24px rgba(255,61,166,0.35); }
    50%      { box-shadow: inset 0 0 0 2px var(--neon-2), inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 #000, 0 0 32px rgba(123,92,255,0.55); }
  }
  .unhinged-toggle .ic {
    font-size: 38px;
    line-height: 1;
    flex-shrink: 0;
    text-shadow: 3px 3px 0 #000;
    filter: drop-shadow(0 0 6px rgba(255,61,166,0.4));
    transition: transform 0.2s steps(4);
  }
  /* Bespoke gremlin-bat portrait shared across the unhinged toggle,
     host-bubble avatar, and the top-bar UNHINGED pill. Three sizes,
     one image source. Crisp-edge so the painterly pixel art stays
     sharp when scaled down. */
  .unhinged-bat-img {
    width: 56px; height: 56px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }
  /* System AI face — same crisp-edge treatment as the bat. Three sizes
     to match the avatar slots: sm (chat / host bubbles), md (abandon
     modal centerpiece), lg (intro / cinematic). */
  .system-av-img {
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }
  .system-av-img.sm { width: 36px; height: 36px; }
  .system-av-img.md { width: 96px; height: 96px; }
  .system-av-img.lg { width: 140px; height: 140px; }
  /* Laughing animation — slight rocking shake while the smug mouth
     flaps. Used by the abandon-run modal in non-unhinged runs. */
  .system-av-img.system-av-laughing {
    animation: systemLaughShake 0.35s steps(2) infinite;
  }
  @keyframes systemLaughShake {
    0%, 100% { transform: translate(0, 0) rotate(-2deg); }
    50%      { transform: translate(0, -2px) rotate(2deg); }
  }
  /* Same rocking shake as the System AI laugh — reuses systemLaughShake.
     Applied while the gremlin is mid-cackle (abandon modal, generating
     screen) so the bat physically jiggles, not just mouth-flaps. */
  .unhinged-bat-img.unhinged-av-laughing {
    animation: systemLaughShake 0.35s steps(2) infinite;
  }
  .unhinged-bat-img.sm { width: 36px; height: 36px; }
  .unhinged-bat-img.tiny {
    width: 14px; height: 14px;
    display: inline-block; vertical-align: middle;
    margin-right: 4px; margin-top: -2px;
  }
  .unhinged-toggle .ic .unhinged-bat-img {
    /* Bigger than the default since it sits in a 56×56 slot. */
    width: 56px; height: 56px;
  }
  .host-bubble .av .unhinged-bat-img {
    width: 36px; height: 36px;
  }
  /* When Unhinged is OFF: subtle deep-red pulse beneath the bat — like
     something is breathing under the icon, waiting to be let out. */
  .unhinged-toggle:not(.on) .ic {
    animation: batCreepyUnderglow 2.6s ease-in-out infinite;
  }
  @keyframes batCreepyUnderglow {
    0%, 100% {
      filter: drop-shadow(0 0 6px rgba(255,61,166,0.4))
              drop-shadow(0 0 0 rgba(120,0,0,0));
    }
    50% {
      filter: drop-shadow(0 0 6px rgba(255,61,166,0.4))
              drop-shadow(0 4px 6px rgba(140,0,0,0.55))
              drop-shadow(0 6px 14px rgba(70,0,0,0.45));
    }
  }
  .unhinged-toggle.on .ic {
    animation: unhingedShake 0.8s steps(8) infinite;
  }
  @keyframes unhingedShake {
    0%, 100% { transform: translate(0,0) rotate(-3deg); }
    25%      { transform: translate(1px,-1px) rotate(2deg); }
    50%      { transform: translate(-1px,1px) rotate(-2deg); }
    75%      { transform: translate(1px,0) rotate(3deg); }
  }
  .unhinged-toggle .meta { flex: 1; min-width: 0; position: relative; z-index: 2; }
  .unhinged-toggle .meta h4 {
    font-family: var(--px); font-size: 11px;
    color: var(--ink-faint);
    letter-spacing: 1.5px;
    margin-bottom: 4px;
    text-shadow: 2px 2px 0 #000;
    transition: color 0.2s;
  }
  .unhinged-toggle.on .meta h4 {
    color: var(--neon);
    text-shadow: 2px 2px 0 var(--neon-2), 3px 3px 0 #000;
  }
  .unhinged-toggle .meta p {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim);
    line-height: 1.3;
  }
  .unhinged-toggle.on .meta p { color: var(--ink); }
  .unhinged-toggle .switch {
    flex-shrink: 0;
    font-family: var(--px); font-size: 10px;
    padding: 8px 10px;
    background: var(--bg-0);
    border: 2px solid var(--ink-faint);
    color: var(--ink-faint);
    letter-spacing: 1px;
    text-shadow: 2px 2px 0 #000;
    box-shadow: 2px 2px 0 #000;
    position: relative; z-index: 2;
  }
  .unhinged-toggle.on .switch {
    background: var(--neon);
    border-color: #000;
    color:var(--ink);
    box-shadow: 2px 2px 0 var(--neon-2), 4px 4px 0 #000;
    animation: blink 1.4s steps(2) infinite;
  }

  /* ── Story Mode in-run palette overrides (build 241) ──
     Body-level theme classes mounted during boss/quest/recap views.
     Each theme applies a SUBTLE accent shift — we tune accent colors
     and add a faint screen-edge tint, but don't apply a global CSS
     filter (would wreck pixel-art sprites). Visual cohesion comes from
     prompt voice + boss/step text, not heavy color washing. */
  body.theme-zombie {
    --neon-3: #7caa5c;       /* sickly green replaces teal accent */
  }
  body.theme-zombie::after {
    content: '';
    position: fixed; inset: 0;
    pointer-events: none;
    background: radial-gradient(120% 80% at 50% 110%, rgba(124, 170, 92, 0.10) 0%, transparent 60%);
    z-index: 1;
  }
  body.theme-scifi {
    --neon-3: #6ec4ff;       /* cool cyan accent */
    --neon-2: #4f7bff;
  }
  body.theme-scifi::after {
    content: '';
    position: fixed; inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(110, 196, 255, 0.06) 0%, transparent 30%);
    z-index: 1;
  }
  body.theme-detective {
    --neon-3: #d0c08c;       /* warm sepia accent */
    --gold: #e2c87b;
  }
  body.theme-detective::after {
    content: '';
    position: fixed; inset: 0;
    pointer-events: none;
    background: radial-gradient(100% 100% at 50% 50%, transparent 50%, rgba(0, 0, 0, 0.18) 100%);
    z-index: 1;
  }
  body.theme-fantasy {
    --neon-3: #f0c060;       /* rich gold accent */
    --gold: #ffd56b;
  }
  body.theme-fantasy::after {
    content: '';
    position: fixed; inset: 0;
    pointer-events: none;
    background: radial-gradient(80% 60% at 50% 0%, rgba(255, 213, 107, 0.08) 0%, transparent 60%);
    z-index: 1;
  }
  body.theme-spy {
    --neon-3: #9fb8c6;       /* cold steel accent */
  }
  body.theme-spy::after {
    content: '';
    position: fixed; inset: 0;
    pointer-events: none;
    background: linear-gradient(135deg, rgba(159, 184, 198, 0.05) 0%, transparent 50%);
    z-index: 1;
  }

  /* ── Story Mode toggle (build 241) ──
     Twin to the unhinged toggle but in gold/teal so it reads as a
     distinct optional pathway, not a competing version of unhinged.
     When toggled on, the theme picker card renders below it. */
  .story-mode-toggle {
    display: grid;
    grid-template-columns: 56px 1fr auto;
    gap: 14px; align-items: center;
    padding: 12px 14px;
    margin: 14px 0;
    background: linear-gradient(135deg, rgba(79, 227, 214, 0.10), rgba(123, 92, 255, 0.10));
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 4px 4px 0 #000;
    cursor: pointer;
    user-select: none;
    transition: transform 0.08s;
  }
  .story-mode-toggle:active { transform: translate(2px, 2px); box-shadow: inset 0 0 0 2px var(--neon-3), 2px 2px 0 #000; }
  .story-mode-toggle .ic {
    font-size: 28px; text-align: center;
    filter: drop-shadow(0 0 6px rgba(79, 227, 214, 0.35));
  }
  .story-mode-ic-img {
    width: 44px; height: 44px; object-fit: contain;
    image-rendering: pixelated;
  }
  .story-mode-toggle .meta h4 {
    font-family: var(--px); font-size: 11px; color: var(--neon-3);
    margin: 0 0 4px; letter-spacing: 1.5px;
    text-shadow: 2px 2px 0 #000;
  }
  .story-mode-toggle .meta p {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    line-height: 1.4; margin: 0;
  }
  .story-mode-toggle .switch {
    padding: 8px 14px;
    font-family: var(--px); font-size: 10px;
    background: var(--bg-1);
    border: 2px solid var(--ink-faint);
    color: var(--ink-faint);
    letter-spacing: 1px;
    text-shadow: 2px 2px 0 #000;
    box-shadow: 2px 2px 0 #000;
  }
  .story-mode-toggle.on {
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.18), rgba(79, 227, 214, 0.18));
    box-shadow: inset 0 0 0 2px var(--gold), 4px 4px 0 #000, 0 0 26px rgba(245, 194, 66, 0.25);
  }
  .story-mode-toggle.on .meta h4 { color: var(--gold); }
  .story-mode-toggle.on .meta p { color: var(--ink); }
  .story-mode-toggle.on .switch {
    background: var(--gold); color: #1a0d28;
    border-color: #000;
    box-shadow: 2px 2px 0 var(--neon-3), 4px 4px 0 #000;
  }

  /* Theme picker grid — 2-up tile layout below the Story Mode card */
  .theme-picker-card {
    margin: -4px 0 16px;
    padding: 16px 14px 14px;
    background: var(--card);
    border: 2px dashed var(--gold);
    box-shadow: 4px 4px 0 #000;
  }
  .theme-picker-label {
    font-family: var(--px); font-size: 9px;
    color: var(--gold); letter-spacing: 2px;
    margin-bottom: 12px;
  }
  .theme-picker-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }
  .theme-tile {
    text-align: left;
    padding: 12px 12px 14px;
    background: var(--card);
    border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    color: var(--ink);
    cursor: pointer;
    transition: transform 0.08s, box-shadow 0.08s;
  }
  .theme-tile:active { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 0 0 0 #000; }
  .theme-tile-ic {
    font-size: 24px; margin-bottom: 4px;
    line-height: 1;
  }
  .theme-tile-img {
    width: 40px; height: 40px; object-fit: contain;
    image-rendering: pixelated;
  }
  .theme-tile-name {
    font-family: var(--px); font-size: 10px;
    color: var(--gold); letter-spacing: 1px;
    margin-bottom: 4px;
    text-shadow: 1px 1px 0 #000;
  }
  .theme-tile-short {
    font-family: var(--term); font-size: 12px;
    color: var(--ink-dim);
    line-height: 1.3;
  }
  .theme-tile.on {
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.20), rgba(79, 227, 214, 0.10));
    box-shadow: inset 0 0 0 2px var(--gold), 4px 4px 0 #000, 0 0 16px rgba(245, 194, 66, 0.4);
  }
  .theme-tile.on .theme-tile-name { color: var(--gold); }
  .theme-tile.on .theme-tile-short { color: var(--ink); }

  /* Run header pill — shown during an unhinged run. The pill flies in
     from the left once on appearance, then breathes with a smooth
     opacity/brightness pulse instead of the old hard step-blink. The
     bat icon does its own slow wing-flap inside. */
  .pill.unhinged {
    background: var(--neon);
    color:var(--ink);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    text-shadow: 1px 1px 0 #000;
    animation:
      unhingedFlyIn 620ms cubic-bezier(0.2, 0.85, 0.25, 1) backwards,
      unhingedBreathe 2.6s ease-in-out 620ms infinite;
    transform-origin: left center;
  }
  .pill.unhinged .dot {
    background: #fff;
    box-shadow: 0 0 6px #fff;
  }
  .pill.unhinged .bat {
    display: inline-block;
    animation: batFlap 540ms ease-in-out infinite;
    transform-origin: 50% 60%;
  }
  @keyframes unhingedFlyIn {
    0%   { transform: translateX(-180%) rotate(-22deg) scale(0.6); opacity: 0; }
    55%  { transform: translateX(10%)   rotate(10deg)  scale(1.06); opacity: 1; }
    78%  { transform: translateX(-3%)   rotate(-3deg)  scale(1); opacity: 1; }
    100% { transform: translateX(0)     rotate(0)      scale(1); opacity: 1; }
  }
  @keyframes unhingedBreathe {
    0%, 100% { opacity: 1;    filter: brightness(1); }
    50%      { opacity: 0.55; filter: brightness(1.3); }
  }
  @keyframes batFlap {
    0%, 100% { transform: scaleX(1)   scaleY(1); }
    50%      { transform: scaleX(0.45) scaleY(1.05); }
  }

  /* Nightmare difficulty — full-width, red, ominous */
  .diff[data-diff="nightmare"] {
    grid-column: span 2;
    background: linear-gradient(135deg, #2a0f0f, #3a0820);
    position: relative;
    overflow: hidden;
  }
  .diff[data-diff="nightmare"]::before {
    content: '☠';
    position: absolute;
    top: 8px; right: 14px;
    font-size: 28px;
    filter: drop-shadow(0 0 8px var(--danger));
    animation: blink 1.4s steps(2) infinite;
  }
  .diff[data-diff="nightmare"] h4 {
    color: var(--danger);
    text-shadow: 2px 2px 0 #000;
  }
  .diff[data-diff="nightmare"] .pill-sm {
    color: var(--danger);
  }
  .diff[data-diff="nightmare"] p {
    color: var(--ink);
  }
  .diff[data-diff="nightmare"] .reward-pill {
    background: var(--danger);
    color:var(--ink);
    border-color: #000;
  }
  .diff[data-diff="nightmare"].on {
    background: linear-gradient(135deg, #5a1a1a, #6a1830);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 4px 4px 0 var(--danger);
  }
  .diff[data-diff="nightmare"].on h4 {
    color:var(--ink);
  }

  /* Locked Nightmare card — desaturated, click is a denial. The overlay
     covers the inner content with a soft dark tint and shows progress. */
  .diff.diff-locked {
    position: relative;
    cursor: not-allowed;
    filter: grayscale(0.55);
  }
  .diff.diff-locked > *:not(.diff-lock-overlay):not(.diff-tape) {
    opacity: 0.35;
  }
  .diff-lock-overlay {
    position: absolute; inset: 8px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 6px;
    background: rgba(8, 4, 14, 0.78);
    border: 2px dashed rgba(255, 255, 255, 0.35);
    padding: 10px 12px;
    text-align: center;
    z-index: 5;
  }
  .diff-lock-ic {
    font-size: 26px;
    filter: drop-shadow(0 0 6px rgba(255,61,166,0.4));
  }
  .diff-lock-msg {
    font-family: var(--px); font-size: 9px; letter-spacing: 1px;
    color: var(--ink); line-height: 1.4;
  }
  .diff-lock-bar {
    width: 80%; height: 6px;
    background: rgba(0,0,0,0.6);
    border: 1px solid rgba(255,255,255,0.2);
  }
  .diff-lock-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--gold), var(--neon));
    transition: width .3s ease-out;
  }
  .diff-lock-prog {
    font-family: var(--term); font-size: 12px;
    color: var(--gold);
  }

  /* Tiny "✦ try Brave first" tag on Bold/Chaos for new players. */
  .diff-rec-hint {
    margin-top: 8px;
    font-family: var(--term); font-size: 11px;
    color: var(--neon);
    letter-spacing: 0.5px;
    opacity: 0.85;
  }

  /* Nightmare confirm modal — list of what they're signing up for. */
  .nightmare-warn-modal h3 {
    color: var(--danger);
    text-shadow: 0 0 8px rgba(255, 64, 80, 0.6);
  }
  .nightmare-warn-list {
    list-style: none; padding: 0; margin: 12px 0;
    display: flex; flex-direction: column; gap: 6px;
    text-align: left;
  }
  .nightmare-warn-list li {
    font-family: var(--term); font-size: 14px;
    color: var(--ink);
    padding: 6px 10px;
    background: rgba(255, 64, 80, 0.10);
    border-left: 3px solid var(--danger);
  }
  .nightmare-warn-list li strong {
    color: var(--danger);
  }

  /* ---------- Players list ---------- */
  .players-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
  .player-chip .x {
    background: none; border: none; color: var(--ink-faint);
    font-family: var(--px); font-size: 11px; cursor: pointer; padding: 0 4px;
  }

  /* ---------- Boss card ---------- */
  .boss-card {
    border-radius: 0; overflow: hidden;
    background: #1a081a;
    border: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon), 6px 6px 0 #000;
    margin-bottom: 18px;
  }
  /* Quest-screen variant — pinned to the top so the boss HP bar stays
     visible while the player scrolls through steps. The timer sits
     directly below it (its `top` is bumped accordingly). */
  .boss-card.boss-sticky {
    position: sticky;
    top: 60px;
    z-index: 9;
  }
  .boss-art {
    height: 180px; position: relative;
    background:
      radial-gradient(circle at 50% 50%, rgba(255,61,166,0.4), transparent 60%),
      repeating-linear-gradient(0deg, #3a155a 0 4px, #2a0f43 4px 8px);
    display: flex; align-items: center; justify-content: center;
    font-size: 110px;
    text-shadow: 6px 6px 0 #000;
    border-bottom: 4px solid #000;
    animation: bob 1.6s ease-in-out infinite;
  }
  .boss-art::before {
    content: ''; position: absolute; inset: 0;
    background-image:
      linear-gradient(rgba(255,255,255,0.06) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255,255,255,0.06) 1px, transparent 1px);
    background-size: 16px 16px;
    mask-image: radial-gradient(circle at center, black 20%, transparent 75%);
  }
  /* Boss emblem — pixel-art rune tablet that frames the boss emoji so
     the OS-rendered glyph feels intentional / "carved into stone"
     instead of floating loose against the surrounding pixel art.
     Three size variants: lg (boss reveal), md (recap / boss info modal),
     sm (sticky in-quest boss card). */
  .boss-emblem {
    display: inline-flex; align-items: center; justify-content: center;
    position: relative;
    /* Layered fills: outer dark stone gradient + inner darker well.
       The inset box-shadow draws a thin gold "engraved" ring. */
    background:
      radial-gradient(ellipse at center, #2a1f3a 0%, #16101e 80%);
    border: 4px solid #000;
    box-shadow:
      inset 0 0 0 2px var(--gold),
      inset 0 0 0 4px #000,
      inset 0 0 18px rgba(255, 206, 79, 0.18),
      4px 4px 0 #000;
    line-height: 1;
    text-shadow: 3px 3px 0 #000;
    /* Slight saturate so the emoji reads as part of the stone, not an
       OS UI element. Drop the saturate if it kills the emoji color. */
    filter: saturate(1.1);
  }
  /* Decorative gold rivets in each corner (drawn via pseudo-elements
     stacked with conic-gradient backgrounds — pure CSS, no images). */
  .boss-emblem::before,
  .boss-emblem::after {
    content: '';
    position: absolute;
    width: 10px; height: 10px;
    background: var(--gold);
    border: 2px solid #000;
    box-shadow: inset -1px -1px 0 rgba(0,0,0,0.4);
  }
  .boss-emblem::before { top: -5px; left: -5px; }
  .boss-emblem::after  { bottom: -5px; right: -5px; }
  /* Two more rivets via a pair of inline span pseudo-helpers — added
     as a separate inline ::after on a wrapping span won't work, so we
     stick to the diagonal pair which still reads as a sealed tablet. */
  .boss-emblem.lg { width: 140px; height: 140px; font-size: 78px; }
  .boss-emblem.md { width: 96px;  height: 96px;  font-size: 56px; }
  .boss-emblem.sm { width: 56px;  height: 56px;  font-size: 30px; }

  .boss-body { padding: 18px; }
  .boss-body .name {
    font-family: var(--px); font-size: 14px;
    margin-bottom: 10px;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 4px 4px 0 #000;
  }
  .boss-body .desc { color: var(--ink); font-family: var(--term); font-size: 17px; margin-bottom: 12px; }
  .boss-stat { display: flex; justify-content: space-between; font-family: var(--px); font-size: 8px; color: var(--ink-faint); margin-top: 8px; }
  .hp-bar {
    height: 16px; background: #000;
    overflow: hidden; border: 2px solid #000;
    box-shadow: inset 1px 1px 0 rgba(255,255,255,0.08);
    image-rendering: pixelated;
  }
  .hp-fill {
    height: 100%; transition: width .5s steps(20);
    background: repeating-linear-gradient(
      90deg, #ff5764 0 8px, #ff3da6 8px 16px
    );
    box-shadow: inset 0 -3px 0 rgba(0,0,0,0.4), inset 0 2px 0 rgba(255,255,255,0.25);
  }
  /* Boss reaction when a step lands — flinch + flash + floating damage
     number, so the player can SEE the boss take the hit. */
  @keyframes bossHitFlinch {
    0%   { transform: translateX(0) rotate(0); }
    14%  { transform: translateX(-5px) rotate(-5deg); }
    30%  { transform: translateX(5px)  rotate(5deg); }
    46%  { transform: translateX(-4px) rotate(-3deg); }
    62%  { transform: translateX(3px)  rotate(2deg); }
    100% { transform: translateX(0) rotate(0); }
  }
  .boss-hit-flinch { animation: bossHitFlinch 0.42s ease-out; }
  @keyframes bossHitFlash {
    0%, 100% { filter: none; }
    22%      { filter: brightness(2.4) saturate(0.4); }
  }
  .boss-hit-flash { animation: bossHitFlash 0.34s ease-out; }
  @keyframes dmgFloat {
    0%   { transform: translate(-50%, 4px) scale(0.5); opacity: 0; }
    18%  { transform: translate(-50%, -6px) scale(1.2); opacity: 1; }
    100% { transform: translate(-50%, -52px) scale(1); opacity: 0; }
  }
  .dmg-float {
    position: fixed; z-index: 4000;
    font-family: var(--px); font-size: 20px;
    color: #ff5764; text-shadow: 2px 2px 0 #000, 0 0 10px rgba(255,87,100,0.85);
    pointer-events: none; white-space: nowrap;
    animation: dmgFloat 0.95s ease-out forwards;
  }
  .reward-pill {
    display: inline-block; padding: 6px 10px; border-radius: 0;
    background: var(--gold); color: #2a1500;
    font-family: var(--px); font-size: 9px; margin-top: 10px;
    border: 2px solid #000; box-shadow: 2px 2px 0 #000;
  }

  /* ---------- Boss reveal stats strip ---------- */
  .boss-stats-strip {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0;
    margin: 12px 0 10px;
    border: 3px solid #000;
    background: #000;
    box-shadow: inset 0 0 0 2px var(--neon-2), 3px 3px 0 #000;
  }
  .boss-stats-strip .cell {
    background: var(--bg-1);
    padding: 8px 4px;
    text-align: center;
    border-right: 2px solid #000;
  }
  .boss-stats-strip .cell:last-child { border-right: none; }
  .boss-stats-strip .cell .ic { font-size: 18px; line-height: 1; margin-bottom: 4px; text-shadow: 1px 1px 0 #000; display: flex; align-items: center; justify-content: center; min-height: 24px; }
  .boss-cell-crate { width: 24px; height: 24px; object-fit: contain; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; display: block; }
  .boss-stats-strip .cell .v {
    font-family: var(--px); font-size: 11px; color: var(--gold);
    letter-spacing: 0.5px;
    text-shadow: 1px 1px 0 #000;
    line-height: 1.1;
    word-break: break-word;
  }
  .boss-stats-strip .cell .l {
    font-family: var(--px); font-size: 7px; color: var(--ink-faint);
    letter-spacing: 1px;
    margin-top: 4px;
  }
  /* Tier-themed cell colors */
  .boss-stats-strip .cell.tier-warmup .v   { color: #88e2b8; }
  .boss-stats-strip .cell.tier-brave .v    { color: #1e6bd8; }
  .boss-stats-strip .cell.tier-bold .v     { color: #ff8c4a; }
  .boss-stats-strip .cell.tier-chaos .v    { color: var(--neon); }
  .boss-stats-strip .cell.tier-nightmare .v { color: var(--danger); animation: blink 1.4s steps(2) infinite; }

  /* "What you brought" armed-items row */
  .boss-armed-row {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-bottom: 12px;
    padding: 8px 10px;
    background: rgba(255,206,79,0.06);
    border: 2px solid var(--gold);
    box-shadow: inset 0 0 0 1px #000;
  }
  .boss-armed-row .label {
    font-family: var(--px); font-size: 8px; color: var(--gold);
    letter-spacing: 1.5px;
    text-shadow: 1px 1px 0 #000;
    width: 100%;
    margin-bottom: 2px;
  }
  .boss-armed-row .armed-pill {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 4px 8px;
    background: var(--gold);
    color: #2a1500;
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    font-family: var(--px); font-size: 8px;
    letter-spacing: 0.5px;
  }
  .boss-armed-row .armed-pill.cursed {
    background: var(--neon-2);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }

  /* Location echo pill */
  .boss-location-echo {
    display: inline-block;
    padding: 4px 10px;
    margin-bottom: 12px;
    font-family: var(--px); font-size: 8px;
    color: var(--ink-dim);
    background: var(--bg-1);
    border: 2px solid var(--ink-faint);
    letter-spacing: 1px;
    text-shadow: 1px 1px 0 #000;
  }

  /* Color-coded section headers on the boss card */
  .boss-body .section-title.wants    { color: var(--gold); }
  .boss-body .section-title.beat     { color: var(--neon-3); }
  .boss-body .section-title.timeout  { color: var(--danger); animation: blink 2.6s steps(2) infinite; }
  .boss-body .section-title.wants::before    { background: var(--gold); }
  .boss-body .section-title.beat::before     { background: var(--neon-3); }
  .boss-body .section-title.timeout::before  { background: var(--danger); }

  /* ---------- Store ---------- */
  .store-balance {
    display: flex; justify-content: space-between; align-items: center;
    padding: 10px 14px;
    background: var(--bg-1);
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 3px 3px 0 #000;
    margin-bottom: 14px;
  }
  .store-balance .lbl {
    font-family: var(--px); font-size: 9px;
    color: var(--ink-faint);
    letter-spacing: 1.5px;
  }
  .store-balance .v {
    font-family: var(--px); font-size: 16px;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 #000;
    letter-spacing: 1px;
  }
  .store-card {
    display: flex; align-items: center; gap: 12px;
    padding: 12px;
    background: var(--card);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--neon-3);
    margin-bottom: 10px;
    cursor: pointer;
    transition: transform .06s;
  }
  .store-card:active { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 1px 1px 0 var(--neon-3); }
  .store-card.cursed {
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--neon-2);
    background: linear-gradient(160deg, #1d0f2e, #14091f);
  }
  .store-card.cursed:active { box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 1px 1px 0 var(--neon-2); }
  .store-card.locked {
    opacity: 0.55;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--ink-faint);
    cursor: not-allowed;
  }
  .store-card.locked:active { transform: none; }
  .store-card .ic {
    flex-shrink: 0;
    font-size: 36px; line-height: 1;
    text-shadow: 3px 3px 0 #000;
    width: 52px; text-align: center;
  }
  /* Pixel-art bespoke item portrait — sized variants for each surface
     where item icons render (store / bag / armed-chip / armed-pill /
     in-run drawer / item-detail modal). All share the same crisp-edge
     scaling so the chibi sprites don't blur on the way down. */
  /* Width/height set on the class itself (not on a descendant
     selector) so the image can never render at natural size — even if
     a parent rule changes or the markup nests differently. */
  .store-item-img { width: 52px; height: 52px; display: block; margin: 0 auto; }
  .inv-item-img   { width: 56px; height: 56px; display: block; margin: 0 auto; }
  .place-ic       { width: 28px; height: 28px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .setting-ic     { width: 22px !important; height: 22px !important; min-width: 22px; flex: 0 0 22px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .vibe-ic        { width: 22px; height: 22px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .topbar-ic      { width: 22px; height: 22px; display: inline-block; vertical-align: middle; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .pill-ic        { width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 3px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .chat-ic        { width: 18px; height: 18px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .btn-ic         { width: 18px; height: 18px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  /* Inline UI icons (replaces emoji glyphs across the app). Three sizes:
     .ui-ic       — default 18×18, sits next to button labels/headers.
     .ui-ic-sm    — 14×14 for chips/inline labels.
     .ui-ic-lg    — 26×26 for hero overlays (BETRAY, HOLD TO REVEAL).  */
  .ui-ic, .ui-ic-sm, .ui-ic-lg {
    display: inline-block; vertical-align: middle; object-fit: contain;
    image-rendering: pixelated;
  }
  .ui-ic    { width: 18px; height: 18px; margin-right: 4px; margin-top: -2px; }
  .ui-ic-sm { width: 14px; height: 14px; margin-right: 3px; margin-top: -2px; }
  .ui-ic-lg { width: 26px; height: 26px; margin-right: 6px; margin-top: -3px; }
  .capture-ic     { width: 32px; height: 32px; display: block; margin: 0 auto 4px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .fab-ic         { width: 30px; height: 30px; display: block; margin: 0 auto; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .coin-ic        { width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 3px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .store-cat-ic   { width: 28px; height: 28px; display: inline-block; vertical-align: middle; margin-right: 6px; margin-top: -2px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .gamemode-ic    { width: 64px; height: 64px; display: block; margin: 0 auto 6px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .avatar-ic      { width: 100%; height: 100%; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; display: block; }
  /* Painted MP avatar portraits — replace the unicode emoji that
     used to render in player chips, lobby roster, accusation grid,
     scoreboard, etc. Sized to fully fill the .av/.acc-av/.team-chip-av
     parent slot. */
  .qmp-avatar-img {
    width: 100%; height: 100%;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }
  .qmp-avatar-emoji { display: inline-block; }
  /* Avatar picker button on the party lobby — fixed square slots
     so the painted portraits fit cleanly. */
  .avatar-pick .qmp-avatar-img,
  .avatar-pick .qmp-avatar-emoji {
    width: 36px; height: 36px;
    margin: 0 auto;
  }
  .avatar-pick .qmp-avatar-emoji { font-size: 28px; line-height: 36px; text-align: center; }
  /* Home-screen sitter avatars on the run cards — small. */
  .run-sitter .qmp-avatar-img {
    width: 30px; height: 30px;
  }
  /* Inline avatar in meta lines (photo wall row, photo expanded header,
     anywhere the chibi avatar sits beside text). Constrained so the
     painted PNG doesn't blow up to its natural pixel size. */
  .qmp-avatar-img.inline-meta {
    width: 18px; height: 18px;
    display: inline-block; vertical-align: middle; margin-right: 4px;
  }
  .chip-item-img  { width: 18px; height: 18px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; }
  .pill-item-img  { width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 4px; margin-top: -2px; }
  .row-item-img   { width: 40px; height: 40px; display: block; }
  .item-modal-img { width: 96px; height: 96px; display: block; margin: 0 auto; }
  /* Shared crisp-edge rendering for all bespoke item portraits. */
  .store-item-img,
  .inv-item-img,
  .chip-item-img,
  .pill-item-img,
  .row-item-img,
  .item-modal-img {
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
  }
  .store-card .meta { flex: 1; min-width: 0; }
  .store-card .meta .name {
    font-family: var(--px); font-size: 11px;
    color: var(--gold);
    letter-spacing: 0.5px;
    margin-bottom: 4px;
    text-shadow: 1px 1px 0 #000;
  }
  .store-card.cursed .meta .name {
    color: var(--neon);
    text-shadow: 1px 1px 0 var(--neon-2), 2px 2px 0 #000;
  }
  .store-card .meta .desc {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim);
    line-height: 1.3;
    margin-bottom: 6px;
  }
  .store-card .meta .tags {
    display: flex; flex-wrap: wrap; gap: 4px;
  }
  .store-card .btn {
    flex: 0 0 auto;
    width: auto;
    min-width: 80px;
    padding: 10px 12px;
    white-space: nowrap;
  }
  .store-tag {
    display: inline-block;
    padding: 2px 6px;
    font-family: var(--px); font-size: 7px;
    letter-spacing: 1px;
    border: 2px solid #000;
    text-shadow: 1px 1px 0 #000;
    color:var(--ink);
    line-height: 1.4;
    white-space: nowrap;
  }
  .store-tag.pre      { background: var(--neon-3); color: #000; text-shadow: none; }
  .store-tag.in       { background: var(--neon); }
  .store-tag.party    { background: var(--neon-2); }
  .store-tag.solo     { background: var(--gold); color: #2a1500; text-shadow: none; }
  .store-tag.owned    { background: #000; color: var(--gold); text-shadow: none; border-color: var(--gold); }
  .store-tag.rarity-common    { background: #6b7280; }
  .store-tag.rarity-uncommon  { background: #10b981; }
  .store-tag.rarity-rare      { background: #3b82f6; }
  .store-tag.rarity-epic      { background: #a855f7; }
  .store-tag.rarity-legendary {
    background: linear-gradient(135deg, #ff3da6, #ffce4f, #7b5cff);
    background-size: 300% 300%;
    animation: legendaryShimmer 2.4s steps(12) infinite;
  }

  /* ---------- Quest steps ---------- */
  .step-card {
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 #000;
    border-radius: 0; padding: 18px 18px 18px 24px; margin-bottom: 16px;
    position: relative;
  }
  /* Per-step accent stripe — a colored bar pinned to the left edge of
     each step card. Ramps cool → warm across the 5 steps to telegraph
     escalation AND give every step a unique visual anchor so testers
     can tell "I'm on step 3" at a glance without scanning the number.
     A soft matching tint also washes the card background ~6% so the
     cards don't all read as the same dark purple slab. */
  .step-card::before {
    content: '';
    position: absolute;
    left: -3px; top: -3px; bottom: -3px;
    width: 6px;
    background: var(--neon);
    box-shadow: inset 0 0 0 1px #000;
    pointer-events: none;
    z-index: 1;
  }
  /* Step 1 → teal (chill opener) */
  .step-card.step-accent-1::before { background: #4FE3D6; }
  .step-card.step-accent-1 { background: linear-gradient(135deg, rgba(79, 227, 214, 0.08), rgba(20, 10, 35, 0)), var(--card); }
  /* Step 2 → purple (getting interesting) */
  .step-card.step-accent-2::before { background: #7B5CFF; }
  .step-card.step-accent-2 { background: linear-gradient(135deg, rgba(123, 92, 255, 0.10), rgba(20, 10, 35, 0)), var(--card); }
  /* Step 3 → hot pink (middle chaos) */
  .step-card.step-accent-3::before { background: #FF3DA6; }
  .step-card.step-accent-3 { background: linear-gradient(135deg, rgba(255, 61, 166, 0.10), rgba(20, 10, 35, 0)), var(--card); }
  /* Step 4 → gold (climbing the ramp) */
  .step-card.step-accent-4::before { background: #F5C242; }
  .step-card.step-accent-4 { background: linear-gradient(135deg, rgba(245, 194, 66, 0.10), rgba(20, 10, 35, 0)), var(--card); }
  /* Step 5 → danger red (final boss energy). If the step is also
     TRUE FINAL we let the existing red glow rule win (defined below). */
  .step-card.step-accent-5::before { background: #FF5764; }
  .step-card.step-accent-5 { background: linear-gradient(135deg, rgba(255, 87, 100, 0.10), rgba(20, 10, 35, 0)), var(--card); }
  /* TRUE FINAL already has its own red glow + gradient — don't double-
     paint the stripe. Failed steps get a muted bar so they read as
     "this one's dead" instead of "this one's the danger color". */
  .step-card.true-final::before { display: none; }
  .step-card.failed::before { background: #4a1a1a; box-shadow: inset 0 0 0 1px #000; }
  .step-card.locked::before { opacity: 0.5; }
  .step-card.locked { opacity: 0.4; filter: grayscale(0.7); }
  /* Horizon Map reveal — a one-shot flash so the player can SEE that the
     item actually did something. Triggered by .horizon-flash being toggled
     on every .step-card.locked for ~1.6s after the item fires. */
  @keyframes horizonFlashKF {
    0%   { opacity: 0.4; filter: grayscale(0.7); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 #000, 0 0 0 rgba(255, 218, 92, 0); }
    25%  { opacity: 1;   filter: grayscale(0);   box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 var(--gold, #ffda5c), 0 0 28px rgba(255, 218, 92, 0.7); }
    75%  { opacity: 1;   filter: grayscale(0);   box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 var(--gold, #ffda5c), 0 0 18px rgba(255, 218, 92, 0.5); }
    100% { opacity: 0.4; filter: grayscale(0.7); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 #000, 0 0 0 rgba(255, 218, 92, 0); }
  }
  .step-card.locked.horizon-flash { animation: horizonFlashKF 1.6s ease-out; }
  .step-card.done { box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 4px 4px 0 var(--neon-3); }
  .step-card.true-final {
    background: linear-gradient(160deg, #2a0f0f, #1a0a1a);
    box-shadow: inset 0 0 0 2px var(--danger), 4px 4px 0 #000, 0 0 20px rgba(255,87,100,0.35);
  }
  .step-card.true-final .step-tag {
    background: var(--danger);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
    animation: blink 0.8s steps(2) infinite;
  }
  .step-card.true-final h3 {
    color: var(--danger);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 1px;
  }
  /* Failed step (Nightmare timer expired before completion) */
  .step-card.failed {
    background: linear-gradient(160deg, #2a0f0f, #1a0a0a);
    box-shadow: inset 0 0 0 2px var(--danger), 4px 4px 0 #000;
    filter: saturate(0.7);
  }
  /* DEV SCREENSHOT MODE
     Triggered by profile.screenshotMode (dev-only). Adds body.screenshot-mode.
     Goal: clean quest screen for sharing with the developer. We hide the
     timer ring, host greeting bubble, twist banner, FABs, help/reroll
     buttons, and team progress strip. We keep: boss card, step cards,
     and the dev config badge (shows location · vibes · difficulty). */
  .dev-config-badge {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
    padding: 10px 12px;
    background: #000;
    border: 2px solid var(--gold, #ffda5c);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    font-family: var(--px);
    font-size: 9px;
    letter-spacing: 1px;
    color: var(--gold, #ffda5c);
  }
  .dev-config-badge .label { color: var(--ink-dim); margin-right: 4px; }
  .dev-config-badge .row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
  .dev-config-badge .pill {
    padding: 2px 8px;
    background: rgba(255, 218, 92, 0.12);
    border: 1px solid var(--gold, #ffda5c);
    color:var(--ink);
  }
  body.screenshot-mode .timer-ring-wrap,
  body.screenshot-mode .host-bubble,
  body.screenshot-mode .active-twist-banner,
  body.screenshot-mode .photo-wall-btn,
  body.screenshot-mode .team-progress,
  body.screenshot-mode .nightmare-notice,
  body.screenshot-mode .chat-fab,
  body.screenshot-mode .music-fab,
  body.screenshot-mode .item-fab,
  body.screenshot-mode .fab,
  body.screenshot-mode .row > #help,
  body.screenshot-mode .row > #reroll,
  body.screenshot-mode .row > #abandon,
  body.screenshot-mode #questActions,
  body.screenshot-mode header.hud,
  body.screenshot-mode .hud-pills,
  /* For screenshots we don't need the capture UI — players aren't
     actually doing the quest, they're just photographing the generated
     content for me to review. Drop the photo stages and all the
     capture/submit buttons inside step cards. */
  body.screenshot-mode .photo-stage,
  body.screenshot-mode .multi-photo-grid,
  body.screenshot-mode .photo-input,
  body.screenshot-mode .step-card .row {
    display: none !important;
  }
  /* Photo-judge verdict + completed-proof thumbs are also irrelevant for
     screenshots since the player isn't really submitting anything. */
  body.screenshot-mode .photo-judge,
  body.screenshot-mode .past-proof {
    display: none !important;
  }
  /* Tighten step-card vertical density so 5 fully-revealed steps fit on
     one phone screenshot. */
  body.screenshot-mode .step-card {
    padding: 12px 14px;
    margin-bottom: 10px;
  }
  body.screenshot-mode .step-card.locked {
    /* Auto-revealed by screenshot mode — full opacity, no grayscale. */
    opacity: 1;
    filter: none;
  }
  body.screenshot-mode .step-card ul {
    margin: 4px 0 6px 16px;
    padding: 0;
  }
  body.screenshot-mode .step-card .dmg {
    margin-top: 4px;
  }
  .step-card.failed .step-tag {
    background: var(--danger);
    color:var(--ink);
  }
  .step-card.failed h3 {
    color: var(--danger);
    text-decoration: line-through;
  }
  .step-card.failed .instr {
    color: var(--ink-faint);
  }
  /* Per-step countdown for Nightmare time-pressure modifiers */
  .step-timer {
    display: inline-block;
    margin-left: 8px;
    padding: 4px 8px;
    background: var(--danger);
    color:var(--ink);
    font-family: var(--px); font-size: 8px;
    text-shadow: 1px 1px 0 #000;
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    letter-spacing: 1px;
    vertical-align: middle;
  }
  .step-timer.warn {
    animation: blink 0.4s steps(2) infinite;
  }
  .step-timer.expired {
    background: #444;
    color: var(--danger);
  }
  /* Walk-gate badge — surfaces on the step-tag (visible even when the
     step is locked) so the player anticipates 'oh, step 3 will make
     me walk.' Disappears once the gate is cleared (proof unlocked). */
  .step-walk-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 4px 8px;
    background: linear-gradient(90deg, #4adcff, var(--neon-3));
    color: #002b27;
    font-family: var(--px); font-size: 8px;
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    letter-spacing: 1px;
    vertical-align: middle;
    text-shadow: 1px 1px 0 rgba(255,255,255,0.4);
  }
  /* Nightmare rules notice — wrapped in moving yellow/black hazard tape
     so it reads like a roped-off crime scene. */
  .nightmare-notice {
    margin-top: 14px;
    padding: 14px;
    background: rgba(255, 87, 100, 0.1);
    border: 3px solid var(--danger);
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.5), 4px 4px 0 #000;
    text-align: center;
    font-family: var(--px); font-size: 9px;
    color: var(--danger);
    text-shadow: 1px 1px 0 #000;
    position: relative;
    /* Padded inside so the hazard tape (top + bottom) doesn't crowd the text */
    padding-top: 26px; padding-bottom: 26px;
  }
  .nightmare-notice::before,
  .nightmare-notice::after {
    content: '';
    position: absolute; left: -3px; right: -3px;
    height: 14px;
    background: repeating-linear-gradient(
      -45deg,
      #ffce4f 0 14px,
      #000 14px 28px
    );
    background-size: 40px 40px;
    box-shadow: inset 0 0 0 2px #000;
    animation: hazardScroll 1.2s linear infinite;
  }
  .nightmare-notice::before { top: -3px; }
  .nightmare-notice::after  { bottom: -3px; animation-direction: reverse; }
  @keyframes hazardScroll {
    0%   { background-position: 0 0; }
    100% { background-position: 40px 0; }
  }

  /* Review-screen Nightmare banner — meant to read like a warning sign in
     a horror movie. Hazard tape on top + bottom, deep blood-red body,
     pulsing dark glow, oversized skull, jittering text. */
  .review-nightmare-banner {
    position: relative;
    margin: 14px 0;
    background:
      radial-gradient(circle at 50% 50%, rgba(255,87,100,0.18), transparent 70%),
      linear-gradient(180deg, #1a0408, #0a0204);
    border: 4px solid #000;
    box-shadow:
      inset 0 0 0 2px var(--danger),
      6px 6px 0 #000,
      0 0 24px rgba(140, 0, 0, 0.55);
    overflow: hidden;
    animation: rnbBreathe 2.8s ease-in-out infinite;
  }
  @keyframes rnbBreathe {
    0%, 100% { box-shadow: inset 0 0 0 2px var(--danger), 6px 6px 0 #000, 0 0 24px rgba(140,0,0,0.55); }
    50%      { box-shadow: inset 0 0 0 2px var(--danger), 6px 6px 0 #000, 0 0 38px rgba(200,0,0,0.85); }
  }
  .rnb-tape {
    height: 18px;
    background: repeating-linear-gradient(
      -45deg,
      #ffce4f 0 16px,
      #000 16px 32px
    );
    background-size: 45px 45px;
    box-shadow: inset 0 0 0 2px #000;
    animation: hazardScroll 1.2s linear infinite;
  }
  .rnb-tape.rnb-bottom { animation-direction: reverse; }
  .rnb-body {
    text-align: center;
    padding: 14px 16px;
    color: var(--danger);
  }
  .rnb-skull {
    font-size: 64px;
    text-shadow:
      4px 4px 0 #000,
      0 0 18px rgba(255,87,100,0.6);
    margin-bottom: 4px;
    animation: rnbSkullJitter 0.55s steps(2) infinite;
  }
  @keyframes rnbSkullJitter {
    0% { transform: translate(0,0) rotate(0); }
    25% { transform: translate(-2px,1px) rotate(-2deg); }
    50% { transform: translate(2px,-1px) rotate(2deg); }
    75% { transform: translate(-1px,-2px) rotate(-1deg); }
    100% { transform: translate(1px,2px) rotate(1deg); }
  }
  .review-nightmare-banner h3 {
    font-family: var(--px); font-size: 18px;
    color: var(--danger); letter-spacing: 4px;
    text-shadow: 3px 3px 0 #000, 0 0 8px rgba(255,87,100,0.8);
    margin-bottom: 8px;
    animation: rnbBlink 1.1s steps(2) infinite;
  }
  @keyframes rnbBlink {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.7; }
  }
  .review-nightmare-banner p {
    font-family: var(--term); font-size: 16px;
    color: #f4eefb; line-height: 1.4;
    margin-bottom: 10px;
  }

  /* Same hazard tape on the Nightmare difficulty card in the wizard */
  .diff.diff-nightmare {
    position: relative;
    padding-top: 22px;
    padding-bottom: 22px;
    overflow: hidden;
  }
  .diff-tape {
    position: absolute; left: 0; right: 0;
    height: 12px;
    background: repeating-linear-gradient(
      -45deg,
      #ffce4f 0 14px,
      #000 14px 28px
    );
    background-size: 40px 40px;
    box-shadow: inset 0 0 0 1px #000;
    animation: hazardScroll 1.2s linear infinite;
    pointer-events: none;
  }
  .diff-tape.diff-tape-top    { top: 0; }
  .diff-tape.diff-tape-bottom { bottom: 0; animation-direction: reverse; }

  /* Custom Abandon Run modal — replaces the browser confirm() with
     something on-theme + a typed-in roast from the host persona. */
  .abandon-modal-bg {
    background: rgba(0,0,0,0.85);
  }
  .abandon-modal {
    max-width: 380px; text-align: center;
    border: 4px solid var(--danger);
    background:
      radial-gradient(circle at 50% 0%, rgba(255,87,100,0.18), transparent 70%),
      var(--card);
    box-shadow: 6px 6px 0 #000, 0 0 24px rgba(255,87,100,0.4);
    animation: abandonShake 0.35s ease-out;
  }
  @keyframes abandonShake {
    0%   { transform: translateX(0); }
    20%  { transform: translateX(-6px); }
    40%  { transform: translateX(5px); }
    60%  { transform: translateX(-3px); }
    80%  { transform: translateX(2px); }
    100% { transform: translateX(0); }
  }
  .abandon-ic {
    font-size: 60px; text-shadow: 4px 4px 0 #000;
    margin: 6px 0 8px;
    animation: abandonIcPulse 1.4s ease-in-out infinite;
    display: flex; justify-content: center;
  }
  /* Centre the system AI laughing face inside the abandon modal. */
  .abandon-ic .system-av-img { margin: 0 auto; }
  @keyframes abandonIcPulse {
    0%,100% { transform: scale(1); filter: drop-shadow(0 0 0 transparent); }
    50%     { transform: scale(1.05); filter: drop-shadow(0 0 12px rgba(255,87,100,0.7)); }
  }
  .abandon-modal h3 {
    color: var(--danger);
    font-family: var(--px); font-size: 16px;
    letter-spacing: 3px;
    text-shadow: 3px 3px 0 #000;
    margin-bottom: 10px;
  }
  .abandon-stats {
    font-family: var(--term); font-size: 15px;
    color: var(--ink-dim); margin-bottom: 14px;
    line-height: 1.4;
  }
  .abandon-roast {
    background: var(--bg-1); border: 2px dashed var(--line);
    padding: 12px;
    margin-bottom: 4px;
    text-align: left;
  }
  .abandon-roast .roast-tag {
    font-family: var(--px); font-size: 8px;
    color: var(--ink-faint); letter-spacing: 2px;
    margin-bottom: 6px;
  }
  .abandon-roast .roast-line {
    font-family: var(--term); font-size: 16px;
    color: var(--ink); line-height: 1.4;
    min-height: 24px;
  }
  /* Bucket-specific accents — late-bail gets the most damning red */
  .abandon-modal.abandon-early .abandon-roast { border-color: var(--neon-3); }
  .abandon-modal.abandon-early .abandon-roast .roast-tag { color: var(--neon-3); }
  .abandon-modal.abandon-mid   .abandon-roast { border-color: var(--gold); }
  .abandon-modal.abandon-mid   .abandon-roast .roast-tag { color: var(--gold); }
  .abandon-modal.abandon-late  .abandon-roast { border-color: var(--danger); animation: abandonRoastShake 0.7s steps(2) infinite; }
  .abandon-modal.abandon-late  .abandon-roast .roast-tag { color: var(--danger); }
  @keyframes abandonRoastShake {
    0%,100% { transform: translateX(0); }
    50%     { transform: translateX(1px); }
  }
  .abandon-modal .btn.danger {
    background: var(--danger); color:var(--ink);
    border: 2px solid #000; box-shadow: 3px 3px 0 #000;
    text-shadow: 1px 1px 0 #000;
  }
  .abandon-modal .btn.danger:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }
  .rnb-warn {
    display: inline-block;
    padding: 6px 12px;
    background: var(--danger); color: #000;
    border: 2px solid #000;
    font-family: var(--px); font-size: 10px;
    letter-spacing: 2px;
    animation: rnbWarnPulse 0.9s ease-in-out infinite;
  }
  @keyframes rnbWarnPulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.06); }
  }
    letter-spacing: 1.5px;
    line-height: 1.6;
  }
  .step-tag {
    display: inline-block; padding: 5px 9px;
    font-family: var(--px); font-size: 8px; letter-spacing: 1px;
    background: var(--neon-2); color:var(--ink); text-shadow: 1px 1px 0 #000;
    margin-bottom: 10px;
    border: 2px solid #000; box-shadow: 2px 2px 0 #000;
  }
  .step-hint-icon {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: 8px;
    background: var(--gold); color: #2a1500;
    border: 2px solid #000; box-shadow: 2px 2px 0 #000;
    font-size: 12px; padding: 3px 6px;
    cursor: pointer;
    vertical-align: middle;
    animation: hintGlowPulse 2s ease-in-out infinite;
  }
  .step-hint-icon:active { transform: translate(2px,2px); box-shadow: none; }
  @keyframes hintGlowPulse {
    0%,100% { box-shadow: 2px 2px 0 #000; }
    50%     { box-shadow: 2px 2px 0 #000, 0 0 10px rgba(255,206,79,0.7); }
  }
  .step-card h3 { font-size: 12px; margin-bottom: 8px; color: var(--gold); }
  .step-card .instr { color: var(--ink); font-family: var(--term); font-size: 17px; margin-bottom: 10px; }
  .step-card ul { list-style: none; padding: 0; margin: 8px 0 12px; }
  .step-card ul li {
    font-family: var(--term); font-size: 16px; color: var(--ink-dim);
    padding: 2px 0 2px 16px; position: relative;
  }
  .step-card ul li::before {
    content: '►'; position: absolute; left: 0; color: var(--neon);
    font-size: 10px; top: 4px;
  }
  .step-card .dmg { color: var(--neon); font-family: var(--px); font-size: 10px; }
  /* Double Damage active — equation-style display with bouncy intro and
     a steady gold pulse so it stays visible while the buff is queued. */
  .step-card .dmg-doubled {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--px); font-size: 11px;
    color: var(--gold);
    padding: 4px 8px; background: rgba(255,206,79,0.08);
    border: 2px solid var(--gold); border-radius: 0;
    box-shadow: 2px 2px 0 #000;
    animation: dmgDblPop 0.45s cubic-bezier(.2,1.6,.4,1) both, dmgDblPulse 1.2s ease-in-out 0.45s infinite;
  }
  .step-card .dmg-doubled .dmg-base   { color: var(--ink); opacity: 0.7; text-decoration: line-through; }
  .step-card .dmg-doubled .dmg-x      { color: var(--ink-faint); }
  .step-card .dmg-doubled .dmg-mult   {
    color: var(--neon); font-size: 14px;
    text-shadow: 1px 1px 0 #000;
    animation: dmgDblMultPing 0.6s ease-out both;
  }
  .step-card .dmg-doubled .dmg-eq     { color: var(--ink-faint); }
  .step-card .dmg-doubled .dmg-total  {
    color: var(--gold); font-size: 14px;
    text-shadow: 2px 2px 0 #000;
  }
  .step-card .dmg-doubled .dmg-tag    {
    margin-left: 4px; padding: 2px 6px;
    background: var(--neon); color:var(--ink);
    font-size: 8px; letter-spacing: 1px;
    border: 1px solid #000; text-shadow: 1px 1px 0 #000;
    animation: dmgDblTagWiggle 0.8s ease-in-out infinite;
  }
  @keyframes dmgDblPop {
    0%   { transform: scale(0.6) rotate(-4deg); opacity: 0; }
    60%  { transform: scale(1.18) rotate(2deg); opacity: 1; }
    100% { transform: scale(1) rotate(0); opacity: 1; }
  }
  @keyframes dmgDblPulse {
    0%,100% { box-shadow: 2px 2px 0 #000; transform: scale(1); }
    50%     { box-shadow: 2px 2px 0 #000, 0 0 14px rgba(255,206,79,0.7); transform: scale(1.04); }
  }
  @keyframes dmgDblMultPing {
    0%   { transform: scale(0.4); }
    60%  { transform: scale(1.5); }
    100% { transform: scale(1); }
  }
  @keyframes dmgDblTagWiggle {
    0%,100% { transform: rotate(-3deg); }
    50%     { transform: rotate(3deg); }
  }

  .timer {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px;
    background: #000; border: 3px solid var(--neon-3);
    box-shadow: 4px 4px 0 #000, inset 0 0 0 2px #000;
    margin-bottom: 16px;
  }
  .timer .clock {
    font-family: var(--px); font-size: 22px;
    color: var(--neon-3);
    text-shadow: 0 0 8px var(--neon-3);
    font-variant-numeric: tabular-nums;
  }
  .timer.warn { border-color: var(--danger); }
  .timer.warn .clock {
    color: var(--danger); text-shadow: 0 0 8px var(--danger);
    animation: pulse 0.5s steps(2) infinite;
  }
  @keyframes pulse { 50% { opacity: 0.4; } }

  /* ---------- AI host ---------- */
  .host-bubble {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 12px 14px; border-radius: 0;
    background: #0a1825;
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 4px 4px 0 #000;
    margin-bottom: 14px;
  }
  .host-bubble .av {
    width: 36px; height: 36px; flex-shrink: 0;
    background: var(--neon-2);
    border: 2px solid #000;
    display: flex; align-items: center; justify-content: center;
    font-size: 20px;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4);
  }
  .host-bubble .text {
    font-family: var(--term); font-size: 17px;
    color: var(--neon-3); line-height: 1.3;
  }

  /* ---------- Vote ---------- */
  .vote-list { display: flex; flex-direction: column; gap: 10px; margin: 16px 0; }
  .vote-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; border-radius: 0;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
  }
  .vote-row .name { display: flex; align-items: center; gap: 10px; font-family: var(--px); font-size: 10px; }
  .vote-row .av {
    width: 30px; height: 30px;
    background: var(--neon); border: 2px solid #000;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--px); font-size: 11px; color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }
  .vote-row.yes { box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--neon-3); }

  /* ---------- Reward box ---------- */
  .box-stage {
    display: flex; flex-direction: column; align-items: center;
    padding: 60px 40px;
    max-height: 380px;
    overflow: hidden;
    transition: max-height 0.4s ease, padding 0.3s ease, opacity 0.3s ease;
  }
  .box-stage.collapsed {
    max-height: 0;
    padding: 0;
    opacity: 0;
  }
  .lootbox {
    width: 160px; height: 160px;
    background: transparent;
    border: 0;
    box-shadow: none;
    border-radius: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 84px; text-shadow: 4px 4px 0 #000;
    cursor: pointer;
    position: relative;
    image-rendering: pixelated;
  }
  .lootbox-img {
    width: 100%; height: 100%; object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    pointer-events: none;
  }
  .mp-chest-img {
    width: 80px; height: 80px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
    margin: 0 auto 6px;
  }
  .hero-crew-splash {
    margin: 8px auto 14px;
    text-align: center;
    pointer-events: none;
  }
  .hero-crew-img {
    width: 200px; height: auto; max-width: 70%;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: inline-block;
    user-select: none;
    -webkit-user-drag: none;
    filter: drop-shadow(0 0 12px rgba(255,61,166,0.35)) drop-shadow(0 0 24px rgba(79,227,214,0.18));
  }
  .hero-charge-img {
    display: block;
    margin: 6px auto 14px;
    width: 220px; height: auto; max-width: 60%;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
    filter: drop-shadow(0 0 12px rgba(255,61,166,0.45)) drop-shadow(0 0 26px rgba(79,227,214,0.22));
  }
  /* Per-tier loot box themes — the chest art now carries the look itself,
     so we only add a soft tier-colored drop-shadow glow on the painted
     image. No background box, no border, no inset rings. */
  .lootbox.box-warmup    .lootbox-img { filter: drop-shadow(0 0 14px rgba(136,226,184,0.55)) drop-shadow(0 0 28px rgba(136,226,184,0.25)); }
  .lootbox.box-brave     .lootbox-img { filter: drop-shadow(0 0 16px rgba(74,144,226,0.6))  drop-shadow(0 0 30px rgba(74,144,226,0.3)); }
  .lootbox.box-bold      .lootbox-img { filter: drop-shadow(0 0 18px rgba(255,140,74,0.6))  drop-shadow(0 0 32px rgba(255,140,74,0.3)); }
  .lootbox.box-chaos     .lootbox-img { filter: drop-shadow(0 0 20px rgba(255,61,166,0.65)) drop-shadow(0 0 36px rgba(123,92,255,0.4));
                                        animation: chaosBoxImgPulse 1.6s steps(8) infinite; }
  @keyframes chaosBoxImgPulse {
    0%, 100% { filter: drop-shadow(0 0 20px rgba(255,61,166,0.65)) drop-shadow(0 0 36px rgba(123,92,255,0.4)); }
    50%      { filter: drop-shadow(0 0 28px rgba(255,61,166,0.85)) drop-shadow(0 0 48px rgba(123,92,255,0.55)); }
  }
  .lootbox.box-nightmare .lootbox-img { filter: drop-shadow(0 0 22px rgba(255,40,60,0.75)) drop-shadow(0 0 44px rgba(255,40,60,0.4));
                                        animation: nightmareBoxImgPulse 1.2s steps(6) infinite; }
  @keyframes nightmareBoxImgPulse {
    0%, 100% { filter: drop-shadow(0 0 22px rgba(255,40,60,0.7))  drop-shadow(0 0 44px rgba(255,40,60,0.35)); }
    50%      { filter: drop-shadow(0 0 32px rgba(255,40,60,0.95)) drop-shadow(0 0 60px rgba(255,40,60,0.6)); }
  }
  .lootbox.shake { animation: shake 0.18s steps(2) infinite; }
  /* Tap-to-open hint under the crate — bright, pulsing, points up at it
     so players don't miss that the crate itself is the thing to tap. */
  @keyframes tapHintPulse {
    0%, 100% { transform: scale(1);    opacity: 0.8; }
    50%      { transform: scale(1.07); opacity: 1; }
  }
  .box-tap-label {
    margin-top: 14px;
    font-family: var(--px); font-size: 12px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 1px; text-align: center; line-height: 1.5;
    transition: opacity 0.25s;
    animation: tapHintPulse 1.1s ease-in-out infinite;
  }
  @keyframes shake {
    0%   { transform: translate(-2px, 0) rotate(-3deg); }
    50%  { transform: translate(2px, -2px) rotate(3deg); }
    100% { transform: translate(-2px, 2px) rotate(-2deg); }
  }
  .lootbox.opened { /* stop-motion handles the visual; box-stage.collapsed handles the cleanup */ pointer-events: none; }
  .reward-list { width: 100%; margin-top: 14px; }
  .reward-item {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 14px; border-radius: 0;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold);
    margin-bottom: 10px;
    animation: pop .25s steps(4) both;
  }
  @keyframes pop { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }
  .reward-item .ic { font-size: 28px; text-shadow: 2px 2px 0 #000; display: flex; align-items: center; justify-content: center; }
  .reward-ic-img {
    width: 28px; height: 28px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: inline-block;
    vertical-align: middle;
  }
  .reward-item .meta { flex: 1; }
  .reward-item .meta .n { font-family: var(--px); font-size: 11px; color: var(--gold); }
  .reward-item .meta .d { font-family: var(--term); font-size: 16px; color: var(--ink-dim); }

  /* ---------- Inventory grid ---------- */
  .inv-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  }
  .inv-cell {
    aspect-ratio: 1; border-radius: 0;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 3px 3px 0 #000;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: 8px; text-align: center;
    position: relative;
    cursor: pointer;
    transition: transform .06s;
  }
  .inv-cell:active {
    transform: translate(2px, 2px);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 1px 1px 0 #000;
  }
  .inv-cell .ic { font-size: 36px; text-shadow: 2px 2px 0 #000; }
  .inv-cell .n { font-family: var(--px); font-size: 7px; color: var(--ink-dim); margin-top: 6px; line-height: 1.4; }
  .inv-cell .qty {
    position: absolute; top: 4px; right: 4px;
    font-family: var(--px); font-size: 9px; color: #2a1500;
    background: var(--gold);
    border: 2px solid #000;
    padding: 2px 4px;
  }
  .inv-cell .new-tag {
    position: absolute; top: 4px; left: 4px;
    font-family: var(--px); font-size: 7px;
    background: var(--neon); color:var(--ink);
    padding: 3px 5px;
    border: 2px solid #000;
    text-shadow: 1px 1px 0 #000;
    letter-spacing: 0.5px;
    animation: blink 0.8s steps(2) infinite;
    z-index: 1;
  }

  /* Inventory filter row — wraps so every chip is visible at once */
  .inv-filters {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 4px 2px 8px;
    margin-bottom: 14px;
  }
  .inv-filters .chip.mode-tab {
    background: var(--card-2);
    color: var(--neon-3);
  }
  .inv-filters .chip.mode-tab.on {
    background: var(--neon-2);
    color:var(--ink);
  }

  /* ---------- Photo proof ---------- */
  .photo-stage {
    width: 100%; aspect-ratio: 16/9;
    max-height: 180px;
    border: 3px dashed var(--neon-2);
    display: flex; align-items: center; justify-content: center;
    background:
      repeating-linear-gradient(45deg, #14091f 0 8px, #1a0f2b 8px 16px);
    margin-bottom: 10px; position: relative; overflow: hidden;
  }
  .photo-stage.has-photo {
    border: 3px solid var(--neon-3);
    background:
      repeating-linear-gradient(0deg, #0f2027 0 4px, #1a3340 4px 8px);
    box-shadow: inset 0 0 0 3px #000;
  }
  .photo-stage .placeholder {
    color: var(--ink-faint); font-family: var(--px); font-size: 9px;
    text-align: center; line-height: 2;
  }
  .photo-stage .check { font-size: 64px; text-shadow: 4px 4px 0 #000; }

  /* ─── QUEST FEEDBACK widget on reward screen ─── */
  .quest-feedback {
    background: #0a0518;
    border: 2px solid var(--neon-3);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--neon-3);
    padding: 14px;
    text-align: center;
  }
  .quest-feedback .qf-prompt {
    font-family: var(--px);
    font-size: 11px;
    color: var(--neon-3);
    letter-spacing: 1.5px;
    margin-bottom: 10px;
  }
  .quest-feedback .qf-buttons {
    display: flex;
    gap: 10px;
    justify-content: center;
  }
  .qf-btn {
    flex: 1 1 0;
    max-width: 180px;
    padding: 12px 14px;
    background: var(--bg-1);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    font-family: var(--px);
    font-size: 12px;
    letter-spacing: 1.5px;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: transform 0.08s ease-out;
  }
  .qf-btn:hover:not(:disabled) { transform: translate(-1px, -1px); }
  .qf-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 0 0 0 #000; }
  .qf-btn.qf-yes:hover:not(:disabled),
  .qf-btn.qf-yes.selected { background: var(--neon-3); color: #0a0518; }
  .qf-btn.qf-no:hover:not(:disabled),
  .qf-btn.qf-no.selected { background: var(--danger); color:var(--ink); }
  .qf-btn:disabled { opacity: 0.4; cursor: default; }
  .qf-btn .qf-emoji { font-size: 18px; }
  .quest-feedback .qf-confirm {
    margin-top: 10px;
    font-family: var(--term);
    font-size: 13px;
    color: var(--ink-dim);
    font-style: italic;
  }

  /* ─── LEVEL-UP BAR on reward screen ─── L→R fill animation ───
     Sits under the streak card. Renders from the moment the reward
     screen mounts. The fill bar grows 0→100% over ~1.4s with a
     staggered delay so multiple banners (mode + account) animate
     in sequence rather than simultaneously. ─── */
  @keyframes levelUpBarSlideIn {
    0%   { opacity: 0; transform: translateY(8px); }
    100% { opacity: 1; transform: translateY(0); }
  }
  @keyframes levelUpBarFill {
    0%   { width: 0%; }
    100% { width: 100%; }
  }
  @keyframes levelUpBarShimmer {
    0%, 100% { background-position: -200% 50%; }
    50%      { background-position: 200% 50%; }
  }
  .level-up-bar {
    background: linear-gradient(135deg, #2a1a05 0%, #3d2510 50%, #2a1a05 100%);
    border: 3px solid var(--gold, #ffda5c);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold, #ffda5c), 0 0 14px rgba(255, 218, 92, 0.45);
    padding: 10px 14px 12px;
    margin: 0 0 12px;
    animation: levelUpBarSlideIn 0.45s ease-out both;
    position: relative;
    overflow: hidden;
  }
  .level-up-bar.account {
    background: linear-gradient(135deg, #1a0a2e 0%, #2a1a4e 50%, #1a0a2e 100%);
    border-color: #b8a5ff;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #b8a5ff, 0 0 14px rgba(184, 165, 255, 0.45);
    animation-delay: 0.4s;
  }
  .level-up-bar::before {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(90deg,
      transparent 0%,
      rgba(255, 218, 92, 0.15) 50%,
      transparent 100%);
    background-size: 200% 100%;
    animation: levelUpBarShimmer 2.6s ease-in-out infinite;
    pointer-events: none;
  }
  .level-up-bar.account::before {
    background: linear-gradient(90deg, transparent 0%, rgba(184, 165, 255, 0.15) 50%, transparent 100%);
    background-size: 200% 100%;
  }
  .level-up-bar .lub-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    position: relative; z-index: 1;
  }
  .level-up-bar .lub-ic {
    font-size: 22px;
    text-shadow: 2px 2px 0 #000, 0 0 10px rgba(255, 218, 92, 0.8);
  }
  .level-up-bar.account .lub-ic { text-shadow: 2px 2px 0 #000, 0 0 10px rgba(184, 165, 255, 0.8); }
  .level-up-bar .lub-label {
    flex: 1;
    font-family: var(--px);
    font-size: 11px;
    color: var(--gold, #ffda5c);
    letter-spacing: 1.5px;
    text-shadow: 2px 2px 0 #000;
  }
  .level-up-bar.account .lub-label { color: #b8a5ff; }
  .level-up-bar .lub-nums {
    font-family: var(--term);
    font-size: 14px;
    color: var(--ink);
  }
  .level-up-bar .lub-nums strong {
    color: var(--gold, #ffda5c);
    font-size: 18px;
    text-shadow: 2px 2px 0 #000;
  }
  .level-up-bar.account .lub-nums strong { color: #d4c3ff; }
  .level-up-bar .lub-track {
    width: 100%;
    height: 14px;
    background: rgba(0, 0, 0, 0.5);
    border: 2px solid #000;
    box-shadow: inset 1px 1px 0 rgba(0,0,0,0.6);
    position: relative; z-index: 1;
    overflow: hidden;
  }
  .level-up-bar .lub-fill {
    height: 100%;
    background: linear-gradient(90deg, #ffda5c 0%, #ffb443 50%, #ffda5c 100%);
    box-shadow: 0 0 12px rgba(255, 218, 92, 0.85);
    width: 0%;
    /* Slowed from 1.4s → 2.4s so the climb feels earned, paces with
       the levelUp() sfx that fires alongside it. */
    animation: levelUpBarFill 2.4s cubic-bezier(0.16, 1, 0.3, 1) 0.4s both;
  }
  .level-up-bar.account .lub-fill {
    background: linear-gradient(90deg, #b8a5ff 0%, #8c6dff 50%, #b8a5ff 100%);
    box-shadow: 0 0 12px rgba(184, 165, 255, 0.85);
    /* Account bar starts 2.4s later so it follows the mode bar
       sequentially rather than overlapping. */
    animation-delay: 2.8s;
  }

  /* Funfair payoff — after the fill completes, the whole banner SHAKES
     for ~0.7s then BURSTS with a flash + scale pulse. JS triggers
     these classes on a timeout that matches the fill animation end. */
  @keyframes funfairShake {
    0%, 100% { transform: translateX(0) rotate(0); }
    8%   { transform: translateX(-5px) rotate(-1.2deg); }
    16%  { transform: translateX(6px) rotate(1.2deg); }
    24%  { transform: translateX(-7px) rotate(-1.5deg); }
    32%  { transform: translateX(7px) rotate(1.5deg); }
    40%  { transform: translateX(-6px) rotate(-1deg); }
    48%  { transform: translateX(6px) rotate(1deg); }
    56%  { transform: translateX(-4px) rotate(-0.8deg); }
    64%  { transform: translateX(4px) rotate(0.8deg); }
    72%  { transform: translateX(-2px); }
    80%  { transform: translateX(2px); }
    88%  { transform: translateX(-1px); }
  }
  @keyframes funfairBurst {
    0%   { transform: scale(1); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold, #ffda5c), 0 0 14px rgba(255, 218, 92, 0.45); }
    15%  { transform: scale(1.18); box-shadow: 0 0 60px 20px rgba(255, 218, 92, 1), 0 0 0 4px rgba(255, 218, 92, 0.8); }
    40%  { transform: scale(0.96); box-shadow: 0 0 40px 12px rgba(255, 218, 92, 0.7); }
    100% { transform: scale(1); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold, #ffda5c), 0 0 14px rgba(255, 218, 92, 0.45); }
  }
  @keyframes funfairBurstAccount {
    0%   { transform: scale(1); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #b8a5ff, 0 0 14px rgba(184, 165, 255, 0.45); }
    15%  { transform: scale(1.18); box-shadow: 0 0 60px 20px rgba(184, 165, 255, 1), 0 0 0 4px rgba(184, 165, 255, 0.8); }
    40%  { transform: scale(0.96); box-shadow: 0 0 40px 12px rgba(184, 165, 255, 0.7); }
    100% { transform: scale(1); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #b8a5ff, 0 0 14px rgba(184, 165, 255, 0.45); }
  }
  .level-up-bar.shaking { animation: funfairShake 0.7s ease-in-out; }
  .level-up-bar.bursting { animation: funfairBurst 0.65s cubic-bezier(0.34, 1.56, 0.64, 1); }
  .level-up-bar.account.bursting { animation: funfairBurstAccount 0.65s cubic-bezier(0.34, 1.56, 0.64, 1); }
  /* Post-burst state — bar drains back to 0%, the "from → to" pair
     swaps for just "LV N" (the new level) bigger and centered. Drives
     home the "you ARE level N now, starting fresh" feeling. */
  .level-up-bar.settled .lub-nums {
    font-size: 18px;
    color: var(--gold, #ffda5c);
    text-shadow: 2px 2px 0 #000;
  }
  .level-up-bar.account.settled .lub-nums {
    color: #d4c3ff;
  }
  @keyframes lubSettleIn {
    0%   { opacity: 0; transform: scale(0.6); }
    60%  { opacity: 1; transform: scale(1.2); }
    100% { opacity: 1; transform: scale(1); }
  }
  .level-up-bar.settled .lub-nums strong {
    font-size: 22px;
    display: inline-block;
    animation: lubSettleIn 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  }
  @keyframes lubNumberPunch {
    0%   { transform: scale(1); color: var(--gold, #ffda5c); }
    25%  { transform: scale(1.7); color:var(--ink); text-shadow: 0 0 16px var(--gold, #ffda5c), 2px 2px 0 #000; }
    100% { transform: scale(1); color: var(--gold, #ffda5c); }
  }
  .level-up-bar.bursting .lub-nums strong {
    display: inline-block;
    animation: lubNumberPunch 0.6s ease-out;
  }
  .level-up-bar.account.bursting .lub-nums strong {
    animation: lubNumberPunch 0.6s ease-out;
    color: #d4c3ff;
  }

  /* ─── HOLD proof ─── press-and-hold-to-fill button + moving track ─── */
  .hold-stage {
    display: flex; flex-direction: column; align-items: stretch; gap: 8px;
    margin: 12px 0;
  }
  .hold-stage .hold-label {
    font-family: var(--px); font-size: 10px; color: var(--neon-3);
    text-align: center; letter-spacing: 1.5px;
  }
  /* The track holds the button via flex (NOT position:absolute — that
     was flaky for touch events on iOS). The button is a flex item
     that can translateX within these bounds while the player is
     holding it. Dashed border shows the "play area." */
  .hold-track {
    width: 100%;
    height: 76px;
    border: 2px dashed rgba(0, 230, 195, 0.45);
    background: rgba(0, 0, 0, 0.3);
    box-shadow: inset 0 0 0 2px #000;
    padding: 6px;
    display: flex;
    align-items: stretch;
    overflow: hidden;
    box-sizing: border-box;
  }
  /* .hold-btn is a STYLED DIV — not a <button> — so it doesn't inherit
     any .btn class CSS that was previously stomping our positioning
     and transform. Built from scratch to look like an arcade button. */
  .hold-btn {
    flex: 0 0 55%;
    position: relative;
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    pointer-events: auto;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--neon);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
    border: 3px solid #000;
    box-shadow:
      inset -3px -3px 0 rgba(0,0,0,0.5),
      inset 3px 3px 0 rgba(255,255,255,0.1),
      4px 4px 0 #000;
    font-family: var(--px);
    font-size: 14px;
    letter-spacing: 2px;
    text-transform: uppercase;
    transition: transform 0.65s cubic-bezier(0.4, 0.0, 0.2, 1), filter 0.1s;
    will-change: transform;
    transform: translateX(0);
    -webkit-tap-highlight-color: transparent;
  }
  .hold-btn.done {
    background: var(--gold, #ffda5c);
    color: #2a1500;
    text-shadow: none;
  }
  .hold-btn[aria-disabled="true"] {
    cursor: default;
    pointer-events: none;
  }
  .hold-btn:active {
    /* Visual press feedback — brighten + slight inset shift. Does NOT
       touch transform so our translateX-based movement is preserved. */
    filter: brightness(1.15);
    box-shadow:
      inset -3px -3px 0 rgba(0,0,0,0.6),
      inset 3px 3px 0 rgba(255,255,255,0.2),
      2px 2px 0 #000;
  }
  .hold-btn .hold-fill {
    position: absolute; top: 0; left: 0; bottom: 0;
    width: 0%;
    z-index: 0;
    /* Color travels teal → gold as the player approaches 100%. The
       transition handles both width AND background-color smoothly. */
    background: linear-gradient(90deg,
      rgba(0, 230, 195, 0.40) 0%,
      rgba(0, 230, 195, 0.40) 60%,
      rgba(255, 218, 92, 0.55) 100%);
    transition: width 0.05s linear;
  }
  .hold-btn.done .hold-fill {
    background: rgba(255, 218, 92, 0.65);
  }
  .hold-btn .hold-text {
    position: relative; z-index: 1;
  }
  .hold-stage .hold-hint {
    font-family: var(--term); font-size: 12px; color: var(--ink-faint);
    text-align: center; font-style: italic;
  }
  /* Whisper text that surfaces during the hold — System's voice in
     real time. Fades in, sits above the button, accent style for the
     final-completion line. */
  .hold-whisper,
  .tap-whisper {
    min-height: 18px;
    font-family: var(--term);
    font-size: 14px;
    color: var(--neon-3);
    text-align: center;
    letter-spacing: 0.5px;
    transition: opacity 0.18s ease-out;
    opacity: 1;
    font-style: italic;
  }
  .hold-whisper.accent,
  .tap-whisper.accent {
    color: var(--gold, #ffda5c);
    font-style: normal;
    text-shadow: 1px 1px 0 #000;
    font-size: 16px;
    font-weight: bold;
  }
  /* Per-tap pop-in animation for the tap whisper word */
  @keyframes tapWhisperPunch {
    0%   { transform: scale(0.6); opacity: 0; }
    35%  { transform: scale(1.18); opacity: 1; }
    100% { transform: scale(1.0); opacity: 1; }
  }
  .tap-whisper.punch {
    animation: tapWhisperPunch 0.18s ease-out;
  }

  /* ─── TAP proof ─── counted-tap button ─── */
  .tap-stage {
    display: flex; flex-direction: column; align-items: stretch; gap: 8px;
    margin: 12px 0;
  }
  .tap-stage .tap-label {
    font-family: var(--px); font-size: 14px; color: var(--gold);
    text-align: center; letter-spacing: 2px;
  }
  .tap-btn {
    min-height: 80px;
    font-size: 18px;
    letter-spacing: 4px;
    user-select: none;
    -webkit-user-select: none;
  }
  .tap-btn:active:not(:disabled) {
    transform: translate(3px, 3px) scale(0.98);
  }
  .tap-btn.done {
    background: var(--gold);
    color: #2a1500;
  }

  /* Multi-photo grid — N capture slots side by side */
  .multi-photo-grid {
    display: grid;
    gap: 8px;
    margin-bottom: 10px;
  }
  .multi-photo-grid.cols-2 { grid-template-columns: 1fr 1fr; }
  .multi-photo-grid.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
  .multi-photo-grid.cols-4 { grid-template-columns: 1fr 1fr; }  /* 2x2 */
  .multi-photo-grid .photo-stage {
    margin-bottom: 0;
    aspect-ratio: 1;
    max-height: none;
  }
  .multi-photo-grid .photo-stage .slot-num {
    position: absolute;
    top: 4px; left: 4px;
    font-family: var(--px); font-size: 9px;
    background: rgba(0,0,0,0.75);
    color: var(--gold);
    padding: 3px 6px;
    text-shadow: 1px 1px 0 #000;
    z-index: 2;
    pointer-events: none;
  }
  .multi-photo-grid .photo-stage img.snap {
    width: 100%; height: 100%; object-fit: cover;
  }
  .multi-photo-progress {
    text-align: center;
    font-family: var(--px); font-size: 10px;
    color: var(--ink-dim);
    letter-spacing: 1.5px;
    margin-bottom: 8px;
    text-shadow: 2px 2px 0 #000;
  }
  .multi-photo-progress.complete { color: var(--neon-3); }
  body.unhinged-run .multi-photo-progress.complete { color: var(--neon); }

  /* ---------- Misc ---------- */
  .meta-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
  .boss-ic-img {
    width: 100%; height: 100%; max-width: 100%; max-height: 100%;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }

  /* ──────── BAG / STORE redesign ──────── */
  /* Hero header card — replaces flat "Bag / Inventory" text */
  .bag-hero, .store-hero {
    position: relative;
    margin-bottom: 14px;
    padding: 14px 16px;
    background:
      linear-gradient(160deg, rgba(245, 194, 66, 0.18) 0%, rgba(255, 61, 166, 0.14) 60%, rgba(20, 10, 35, 0.0) 100%),
      var(--card);
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 5px 5px 0 #000;
  }
  .bag-hero h2, .store-hero h2 {
    font-family: var(--px); font-size: 16px; color: var(--gold);
    letter-spacing: 1px; margin: 0 0 4px;
    text-shadow: 2px 2px 0 #000;
    display: flex; align-items: center; gap: 8px;
  }
  .bag-hero .meta, .store-hero .meta {
    font-family: var(--term); font-size: 13px; color: var(--neon-3);
    letter-spacing: 0.5px;
  }
  .bag-hero .new-pill {
    display: inline-block; margin-left: 6px;
    background: var(--neon); color: #000;
    font-family: var(--px); font-size: 8px; padding: 2px 6px;
    letter-spacing: 1px; box-shadow: 1px 1px 0 #000;
  }

  /* Hero wallet — store top */
  .store-wallet {
    display: flex; align-items: center; gap: 12px;
    margin-top: 10px;
    padding: 10px 14px;
    background: rgba(20, 10, 35, 0.6);
    border: 2px solid var(--gold);
    box-shadow: inset 0 0 0 1px rgba(245, 194, 66, 0.3);
  }
  .store-wallet img {
    width: 36px; height: 36px; image-rendering: pixelated;
  }
  .store-wallet .v {
    font-family: var(--px); font-size: 22px; color: var(--gold);
    text-shadow: 2px 2px 0 #000; letter-spacing: 1px;
  }
  .store-wallet .lbl {
    font-family: var(--px); font-size: 8px; color: var(--ink-dim);
    letter-spacing: 1.5px; margin-top: 4px;
  }

  /* Bag search input */
  .inv-search {
    width: 100%; box-sizing: border-box;
    padding: 8px 12px;
    margin-bottom: 10px;
    background: var(--bg-1);
    border: 2px solid var(--line);
    color: var(--ink);
    font-family: var(--term); font-size: 14px;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.3);
  }
  .inv-search:focus {
    outline: none; border-color: var(--neon-3);
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.3), 0 0 8px rgba(0, 230, 195, 0.4);
  }
  /* Filter chips — horizontal scroll, fits one row */
  .inv-filter-scroll {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px 8px;
    margin-bottom: 14px;
    padding: 4px 2px 8px;
  }
  .inv-filter-scroll .chip {
    text-align: center;
    font-size: 9px; padding: 8px 10px;
    letter-spacing: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: transform .06s, box-shadow .06s, background .12s;
  }
  .inv-filter-scroll .chip.on {
    background: var(--gold) !important;
    color: #2a1500 !important;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000, 0 0 12px rgba(245, 194, 66, 0.6);
    border-color: #000 !important;
    text-shadow: none !important;
  }
  .inv-filter-scroll .chip.empty-cat {
    opacity: 0.35;
    pointer-events: none;
  }

  /* "Just in reach" featured row in the store */
  .store-featured-card {
    margin: 14px 0 18px;
    padding: 12px 14px;
    background: linear-gradient(135deg, rgba(255, 61, 166, 0.18), rgba(123, 92, 255, 0.18));
    border: 2px dashed var(--neon);
    box-shadow: 4px 4px 0 #000;
  }
  .store-featured-card .h {
    font-family: var(--px); font-size: 9px; color: var(--neon);
    letter-spacing: 2px; margin-bottom: 8px;
    display: flex; align-items: center; gap: 6px;
  }
  .store-featured-card .empty {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    text-align: center; padding: 6px 0;
  }

  /* ──────── Store v2 layout ──────── */
  /* Hero wallet — big anchor at the top of the store screen */
  .store-v2-wallet {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 18px;
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.20), rgba(255, 61, 166, 0.15));
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 5px 5px 0 #000, 0 0 24px rgba(245, 194, 66, 0.18);
    margin-bottom: 14px;
  }
  .store-v2-wallet img {
    width: 48px; height: 48px; image-rendering: pixelated;
    flex-shrink: 0;
    filter: drop-shadow(0 0 8px rgba(245, 194, 66, 0.6));
  }
  .store-v2-wallet .v {
    font-family: var(--px); font-size: 28px; color: var(--gold);
    text-shadow: 2px 2px 0 #000; letter-spacing: 1px; line-height: 1;
  }
  .store-v2-wallet .lbl {
    font-family: var(--px); font-size: 8px; color: var(--ink-dim);
    letter-spacing: 1.5px; margin-top: 6px;
  }
  .store-v2-wallet .delta {
    font-family: var(--term); font-size: 12px; color: var(--neon-3);
    margin-top: 3px;
  }

  /* Just-in-reach row */
  .store-v2-reach {
    margin-bottom: 18px;
    padding: 12px 14px;
    background: linear-gradient(135deg, rgba(255, 61, 166, 0.16), rgba(123, 92, 255, 0.16));
    border: 2px dashed var(--neon);
    box-shadow: 4px 4px 0 #000;
  }
  .store-v2-reach .h {
    font-family: var(--px); font-size: 9px; color: var(--neon);
    letter-spacing: 2px; margin-bottom: 10px;
  }
  .store-v2-reach .grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  }
  .store-v2-reach .pick {
    padding: 8px 6px; text-align: center; cursor: pointer;
    background: rgba(20, 10, 35, 0.55); border: 2px solid var(--neon-2);
    transition: transform .06s;
  }
  .store-v2-reach .pick:active { transform: translate(2px, 2px); }
  .store-v2-reach .pick img { width: 36px; height: 36px; image-rendering: pixelated; display: block; margin: 0 auto 4px; }
  .store-v2-reach .pick .nm {
    font-family: var(--px); font-size: 7px; color: var(--ink);
    letter-spacing: 0.5px; line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    min-height: 18px;
  }
  .store-v2-reach .pick .price {
    font-family: var(--px); font-size: 8px; color: var(--gold);
    margin-top: 4px; display: inline-flex; align-items: center; gap: 3px;
  }
  .store-v2-reach .pick .price img { width: 11px; height: 11px; margin: 0; display: inline-block; }
  .store-v2-reach .saving {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    text-align: center; padding: 4px 0;
  }
  .store-v2-reach .saving-bar {
    margin-top: 8px; height: 5px; background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--neon-2);
  }
  .store-v2-reach .saving-bar-fill {
    height: 100%; background: linear-gradient(90deg, var(--neon-3), var(--gold));
    box-shadow: 0 0 6px rgba(245, 194, 66, 0.6);
  }

  /* Category nav — 2x2 grid so all sections fit on screen without scroll */
  .store-v2-nav {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 4px 0 0;
    margin: 0 0 14px;
  }
  .store-v2-nav .nav-pill {
    padding: 10px 12px;
    background: var(--card); border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    font-family: var(--px); font-size: 9px; color: var(--ink);
    letter-spacing: 1px; cursor: pointer;
    display: flex; align-items: center; gap: 8px;
    transition: transform .06s, background .12s;
    text-align: left;
    min-width: 0;
  }
  .store-v2-nav .nav-pill img { width: 22px; height: 22px; image-rendering: pixelated; flex-shrink: 0; }
  .store-v2-nav .nav-pill span {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0;
  }
  .store-v2-nav .nav-pill:active { transform: translate(2px, 2px); box-shadow: 0 0 0 #000; }
  .store-v2-nav .nav-pill.active {
    background: var(--gold); color: #2a1500;
    box-shadow: 2px 2px 0 #000, 0 0 10px rgba(245, 194, 66, 0.45);
  }

  /* Section bar — chunky chapter divider */
  .store-section-bar-v2 {
    display: flex; align-items: center; gap: 12px;
    margin: 24px 0 12px;
    padding: 10px 14px;
    background: linear-gradient(90deg, rgba(245, 194, 66, 0.20) 0%, rgba(123, 92, 255, 0.10) 50%, transparent 100%);
    border-left: 6px solid var(--gold);
    box-shadow: inset -2px -2px 0 rgba(0, 0, 0, 0.3);
  }
  .store-section-bar-v2 .ic-img {
    width: 36px; height: 36px; image-rendering: pixelated;
    flex-shrink: 0; object-fit: contain;
  }
  .store-section-bar-v2 .text { flex: 1; min-width: 0; }
  .store-section-bar-v2 h3 {
    font-family: var(--px); font-size: 12px; color: var(--gold);
    letter-spacing: 1.5px; margin: 0;
    text-shadow: 1px 1px 0 #000;
  }
  .store-section-bar-v2 .sub {
    font-family: var(--term); font-size: 12px; color: var(--ink-dim);
    margin-top: 3px;
  }

  /* 1-column item grid — full-width row cards with name + desc visible */
  .store-v2-grid {
    display: flex; flex-direction: column; gap: 8px;
    margin-bottom: 8px;
  }
  .store-v2-card {
    position: relative;
    padding: 10px 12px;
    background: var(--card); border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    cursor: pointer;
    transition: transform .06s;
    overflow: hidden;
    display: grid;
    grid-template-columns: 56px 1fr auto;
    gap: 12px;
    align-items: center;
  }
  .store-v2-card:active { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 0 0 0 #000; }
  .store-v2-card.cursed { border-color: var(--neon); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--neon); }
  .store-v2-card.locked { opacity: 0.6; filter: grayscale(0.4); }
  .store-v2-card.locked:hover { opacity: 0.85; }
  .store-v2-card .ic-wrap { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .store-v2-card .ic-wrap img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
  .store-v2-card .meta { min-width: 0; }
  .store-v2-card .nm {
    font-family: var(--px); font-size: 10px; color: var(--gold);
    letter-spacing: 0.5px; line-height: 1.3; margin-bottom: 4px;
    text-shadow: 1px 1px 0 #000;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .store-v2-card .desc {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    line-height: 1.35;
    overflow: hidden; text-overflow: ellipsis;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }
  .store-v2-card .price {
    flex-shrink: 0;
    display: inline-flex; align-items: center; gap: 4px;
    background: var(--card); border: 2px solid var(--gold);
    color: var(--gold); font-family: var(--px); font-size: 10px;
    padding: 6px 10px; letter-spacing: 0.5px;
    box-shadow: 2px 2px 0 #000;
    white-space: nowrap;
  }
  .store-v2-card .price img { width: 12px; height: 12px; image-rendering: pixelated; }
  .store-v2-card .price.afford { background: var(--gold); color: #2a1500; }
  .store-v2-card .owned-stripe {
    position: absolute; top: 6px; right: -28px;
    transform: rotate(35deg);
    background: var(--neon-3); color: #000;
    font-family: var(--px); font-size: 7px;
    padding: 2px 30px; letter-spacing: 1px;
    box-shadow: 1px 1px 0 #000;
    z-index: 2;
  }

  /* First-run onboarding overlay */
  .onboard-bg {
    position: fixed; inset: 0; background: rgba(10, 5, 24, 0.92);
    z-index: 300; display: flex; align-items: center; justify-content: center;
    padding: 20px;
    animation: fadeIn 0.25s ease-out;
  }
  .onboard {
    width: 100%; max-width: 360px;
    background: var(--card);
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 6px 6px 0 #000, 0 0 32px rgba(255, 61, 166, 0.25);
    padding: 18px;
    text-align: center;
  }
  .onboard-art {
    height: 140px;
    border: 2px solid #000;
    box-shadow: inset 0 0 0 2px rgba(255, 61, 166, 0.25);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 16px;
  }
  .onboard-art img {
    width: 100px; height: 100px; image-rendering: pixelated;
    object-fit: contain;
    filter: drop-shadow(0 0 12px rgba(245, 194, 66, 0.5));
  }
  .onboard h2 {
    font-family: var(--px); font-size: 14px; color: var(--gold);
    letter-spacing: 1px; margin: 0 0 10px;
    text-shadow: 2px 2px 0 #000;
  }
  .onboard p {
    font-family: var(--term); font-size: 14px; color: var(--ink);
    line-height: 1.45; margin: 0 0 16px;
  }
  .onboard-dots {
    display: flex; justify-content: center; gap: 8px; margin-bottom: 14px;
  }
  .onboard-dots .dot {
    width: 8px; height: 8px;
    background: var(--card-2);
    border: 1px solid var(--ink-faint);
  }
  .onboard-dots .dot.on { background: var(--neon); border-color: var(--neon); }
  .onboard-actions {
    display: grid; grid-template-columns: 1fr 2fr; gap: 8px;
  }
  /* Name-picker slide variant — single-column action row (no Skip) and
     a tight input/randomize block above the dots. */
  .onboard-actions.onboard-actions-solo {
    grid-template-columns: 1fr;
  }
  .onboard-name-row {
    margin: 0 0 12px;
  }
  .onboard-name-input {
    width: 100%;
    box-sizing: border-box;
    background: rgba(10, 5, 24, 0.85);
    border: 2px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon);
    color: var(--neon);
    font-family: var(--px); font-size: 13px;
    letter-spacing: 1px; text-align: center;
    padding: 12px 10px;
    outline: none;
    text-transform: none;
  }
  .onboard-name-input::placeholder {
    color: rgba(79, 227, 214, 0.45);
  }
  .onboard-name-input:focus {
    box-shadow: inset 0 0 0 2px var(--gold), 0 0 12px rgba(245, 194, 66, 0.4);
  }
  .onboard-name-random {
    margin-top: 10px;
  }
  .onboard-actions .btn.primary:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    filter: grayscale(0.4);
  }

  /* Detail bottom-sheet modal */
  .store-detail-bg {
    position: fixed; inset: 0; background: rgba(10, 5, 24, 0.82);
    z-index: 200; display: flex; align-items: flex-end; justify-content: center;
    animation: fadeIn 0.2s ease-out;
  }
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
  .store-detail {
    width: 100%; max-width: 480px;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 6px 0 0 #000;
    padding: 18px 18px 24px;
    border-bottom: 0;
    animation: slideUp 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
  }
  @keyframes slideUp { from { transform: translateY(40px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
  .store-detail .closeX {
    float: right; background: transparent; border: 0;
    color: var(--ink-dim); font-size: 16px; cursor: pointer; padding: 4px 8px;
  }
  .store-detail .head {
    display: flex; align-items: center; gap: 14px; margin-bottom: 14px;
    clear: right;
  }
  .store-detail .head img { width: 64px; height: 64px; image-rendering: pixelated; flex-shrink: 0; }
  .store-detail .head h3 {
    font-family: var(--px); font-size: 14px; color: var(--gold);
    letter-spacing: 1px; margin: 0 0 4px;
  }
  .store-detail .head .tags {
    display: flex; gap: 6px; flex-wrap: wrap;
  }
  .store-detail .desc {
    font-family: var(--term); font-size: 14px; color: var(--ink);
    line-height: 1.5; margin-bottom: 14px;
  }
  .store-detail .price-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px; background: rgba(20, 10, 35, 0.6);
    border: 2px solid var(--gold); margin-bottom: 14px;
  }
  .store-detail .price-row .price-big {
    font-family: var(--px); font-size: 18px; color: var(--gold);
    display: inline-flex; align-items: center; gap: 8px;
  }
  .store-detail .price-row .price-big img { width: 24px; height: 24px; image-rendering: pixelated; }
  .store-detail .price-row .own-count {
    font-family: var(--term); font-size: 12px; color: var(--neon-3);
  }
  .store-detail .actions {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  }

  /* Section divider — store category headers */
  .store-section-bar {
    display: flex; align-items: center; gap: 10px;
    margin: 22px 0 6px;
    padding: 8px 12px;
    background: linear-gradient(90deg, rgba(245, 194, 66, 0.16), transparent);
    border-left: 4px solid var(--gold);
    box-shadow: 0 1px 0 rgba(245, 194, 66, 0.2);
  }
  .store-section-bar .ic-img {
    width: 32px; height: 32px; image-rendering: pixelated;
    object-fit: contain; flex-shrink: 0;
  }
  .store-section-bar h3 {
    font-family: var(--px); font-size: 11px; color: var(--gold);
    letter-spacing: 1.5px; margin: 0;
    text-shadow: 1px 1px 0 #000;
  }

  /* ──────── PROFILE SCREEN — redesigned ──────── */
  /* Hero card: gradient backdrop, avatar floats over a name+title plate */
  .profile-hero {
    position: relative;
    margin-bottom: 18px;
    padding: 12px 18px 18px;
    background:
      linear-gradient(160deg, rgba(255, 61, 166, 0.18) 0%, rgba(123, 92, 255, 0.18) 50%, rgba(20, 10, 35, 0.0) 100%),
      var(--card);
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon), 6px 6px 0 #000, 0 0 28px rgba(255, 61, 166, 0.18);
  }
  .profile-hero::before {
    content: '';
    position: absolute; inset: 6px;
    border: 1px dashed rgba(255, 61, 166, 0.25);
    pointer-events: none;
  }
  /* Profile hero layout: avatar on top, name+title+actions stacked
     vertically below. This keeps the player's full handle visible at
     every viewport width — at the old 2-column layout the SELECT
     AVATAR button squeezed names down to "S..." on narrow phones. */
  .profile-hero-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    text-align: center;
  }
  .profile-hero-row > div { min-width: 0; max-width: 100%; }
  .profile-hero-name {
    font-family: var(--px); font-size: 18px; color: var(--gold);
    margin-bottom: 4px; letter-spacing: 0.5px;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    text-shadow: 2px 2px 0 #000;
    overflow: hidden;
    max-width: 100%;
  }
  .profile-hero-name > span:first-child {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0; max-width: 100%;
  }
  .profile-hero-title {
    font-family: var(--term); font-size: 14px; color: var(--neon);
    text-transform: uppercase; letter-spacing: 1.5px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    max-width: 100%;
  }
  .profile-hero-actions {
    margin-top: 4px;
    display: flex; gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
  }
  .profile-hero-actions .btn {
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .profile-hero-tag {
    display: inline-block;
    font-family: var(--px); font-size: 8px; letter-spacing: 1.5px;
    color: var(--neon-3); margin-bottom: 6px;
  }

  /* Stats panel: progress bars + inline icons, all in one frame */
  .profile-stats-card {
    margin-top: 16px;
    padding: 14px 16px;
    background: var(--card);
    border: 3px solid #000;
    box-shadow: 4px 4px 0 #000;
  }
  .profile-stats-card h3 {
    font-family: var(--px); font-size: 11px; color: var(--gold);
    margin-bottom: 12px; letter-spacing: 1px;
    border-bottom: 2px dashed rgba(245, 194, 66, 0.3);
    padding-bottom: 6px;
  }
  .profile-stat-row {
    display: grid;
    grid-template-columns: 26px 1fr auto;
    gap: 10px; align-items: center;
    padding: 6px 0;
  }
  .profile-stat-row + .profile-stat-row { border-top: 1px solid rgba(123, 92, 255, 0.18); }
  .profile-stat-row .ic-img { width: 22px; height: 22px; object-fit: contain; image-rendering: pixelated; }
  .profile-stat-row .stat-label {
    font-family: var(--px); font-size: 8px; color: var(--ink-dim);
    letter-spacing: 1px;
  }
  .profile-stat-row .stat-bar {
    height: 6px; background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(123, 92, 255, 0.3);
    margin-top: 4px; position: relative; overflow: hidden;
  }
  .profile-stat-row .stat-bar-fill {
    position: absolute; left: 0; top: 0; bottom: 0;
    background: linear-gradient(90deg, var(--neon-3), var(--gold));
    box-shadow: 0 0 8px rgba(255, 206, 79, 0.5);
  }
  .profile-stat-row .stat-value {
    font-family: var(--px); font-size: 10px; color: var(--gold);
    text-shadow: 1px 1px 0 #000;
    text-align: right; min-width: 60px;
  }
  .profile-stat-row .stat-value .stat-sub {
    display: block; font-size: 7px; color: var(--ink-faint);
    margin-top: 2px; letter-spacing: 0.5px;
  }
  .profile-stat-row.coins-row .stat-value { color: var(--neon-3); }

  /* Section title with gold underline accent for the profile screen */
  .profile-section-title {
    font-family: var(--px); font-size: 11px; color: var(--gold);
    letter-spacing: 2px; margin: 22px 0 4px;
    padding-bottom: 6px;
    border-bottom: 2px solid var(--gold);
    box-shadow: 0 1px 0 #000;
    display: flex; align-items: baseline; gap: 8px;
  }
  .profile-section-title .pst-count {
    font-size: 9px; color: var(--neon); letter-spacing: 1px;
  }
  .profile-section-help {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    margin: 6px 0 12px;
  }

  /* Achievements call-to-action button on the profile screen */
  .ach-cta {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%;
    margin: 22px 0 8px;
    padding: 14px 16px;
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.18), rgba(255, 61, 166, 0.12));
    border: 3px solid var(--gold);
    box-shadow: 5px 5px 0 #000, inset 0 0 0 1px rgba(0,0,0,0.4);
    color: var(--ink);
    text-align: left;
    cursor: pointer;
    font-family: var(--px);
  }
  .ach-cta:active {
    transform: translate(2px, 2px);
    box-shadow: 3px 3px 0 #000, inset 0 0 0 1px rgba(0,0,0,0.4);
  }
  .ach-cta-l { display: flex; flex-direction: column; gap: 4px; }
  .ach-cta-h    { font-size: 12px; color: var(--gold); letter-spacing: 2px; }
  .ach-cta-sub  { font-size: 10px; color: var(--neon); letter-spacing: 1px; }
  .ach-cta-next { font-family: var(--term); font-size: 13px; color: var(--ink-dim); }
  .ach-cta-next strong { color: var(--ink); }
  .ach-cta-arrow { font-size: 32px; color: var(--gold); padding-left: 12px; }

  /* Achievements detail screen */
  .ach-header { margin-bottom: 18px; }
  .ach-header h2 { font-family: var(--px); color: var(--gold); letter-spacing: 2px; margin: 10px 0 6px; }
  .ach-summary { font-family: var(--term); font-size: 14px; color: var(--ink-dim); margin-bottom: 8px; }
  .ach-overall-bar {
    height: 10px; background: rgba(0,0,0,0.6); border: 2px solid var(--line);
    box-shadow: inset 1px 1px 0 #000;
  }
  .ach-overall-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--gold), var(--neon));
    transition: width .4s ease-out;
  }
  .ach-list {
    display: flex; flex-direction: column; gap: 10px;
    margin-bottom: 24px;
  }
  .ach-row {
    position: relative;
    display: flex; gap: 12px; align-items: stretch;
    padding: 12px;
    background: var(--card);
    border: 2px solid var(--line);
    box-shadow: 4px 4px 0 #000;
  }
  .ach-row.done {
    border-color: var(--gold);
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.08), transparent);
  }
  .ach-row.locked { opacity: 0.85; }
  .ach-icon {
    flex: 0 0 44px;
    display: flex; align-items: center; justify-content: center;
  }
  .ach-icon-img {
    width: 40px; height: 40px;
    image-rendering: pixelated;
    object-fit: contain;
    filter: drop-shadow(0 2px 0 rgba(0,0,0,0.5));
  }
  .ach-row.done .ach-icon-img {
    filter: drop-shadow(0 0 8px rgba(245,194,66,0.6)) drop-shadow(0 2px 0 rgba(0,0,0,0.5));
  }
  .ach-row.locked .ach-icon-img {
    filter: grayscale(0.4) drop-shadow(0 2px 0 rgba(0,0,0,0.5));
    opacity: 0.85;
  }
  /* Inline icon used in headers ("★ ACHIEVEMENTS" → trophy + ACHIEVEMENTS) */
  .ach-h-ic {
    width: 22px; height: 22px;
    image-rendering: pixelated;
    vertical-align: -5px;
    margin-right: 4px;
  }
  /* Tiny inline icon used in the reward line (REWARD: ★ <Title>) */
  .ach-mini-ic {
    width: 14px; height: 14px;
    image-rendering: pixelated;
    vertical-align: -2px;
    margin-right: 2px;
  }
  .ach-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
  .ach-row-h {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  }
  .ach-name { font-family: var(--px); font-size: 12px; letter-spacing: 1px; color: var(--ink); }
  .ach-row.done .ach-name { color: var(--gold); }
  .ach-pill {
    font-family: var(--px); font-size: 8px; letter-spacing: 1px;
    background: var(--gold); color: #2a1500;
    padding: 3px 7px; border: 1px solid #000;
  }
  .ach-pct {
    font-family: var(--px); font-size: 9px; color: var(--neon);
    letter-spacing: 1px;
  }
  .ach-desc {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
    line-height: 1.35;
  }
  .ach-bar {
    height: 8px; margin-top: 4px;
    background: rgba(0,0,0,0.6); border: 1px solid var(--line);
  }
  .ach-bar-fill {
    height: 100%; background: var(--neon);
    transition: width .4s ease-out;
  }
  .ach-row.done .ach-bar-fill { background: var(--gold); }
  .ach-foot {
    display: flex; justify-content: space-between; gap: 8px;
    flex-wrap: wrap;
    font-family: var(--term); font-size: 12px;
    color: var(--ink-dim);
  }
  .ach-prog-num { color: var(--ink); font-weight: bold; }
  .ach-reward strong { color: var(--gold); }

  /* "Ready to claim" state — hot pink/gold pulse on the row + a hovering
     CLAIM button that bobs. Clears on claim. */
  .ach-row.ready {
    position: relative;
    border-color: var(--neon);
    background: linear-gradient(135deg, rgba(255, 61, 166, 0.18), rgba(245, 194, 66, 0.12));
    animation: achRowPulse 1.6s ease-in-out infinite;
  }
  @keyframes achRowPulse {
    0%, 100% { box-shadow: 4px 4px 0 #000, 0 0 0 rgba(255,61,166,0); }
    50%      { box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255, 61, 166, 0.6); }
  }
  .ach-row.ready .ach-icon {
    animation: achIconBob 1.1s ease-in-out infinite;
  }
  .ach-row.ready .ach-icon-img {
    filter: drop-shadow(0 0 10px rgba(255,61,166,0.8)) drop-shadow(0 2px 0 rgba(0,0,0,0.5));
  }
  @keyframes achIconBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
  }
  .ach-pill.ready {
    background: var(--neon); color:var(--ink);
    text-shadow: 0 0 4px rgba(0,0,0,0.7);
    animation: achPillFlash 1.2s ease-in-out infinite;
  }
  @keyframes achPillFlash {
    0%, 100% { background: var(--neon); }
    50%      { background: var(--gold); color: #2a1500; }
  }

  /* CLAIM button — full-width block under the description so it can't
     push the row past its container. Still bobs + glows for the
     "hey tap me" energy without the layout tax. */
  .ach-claim-btn {
    display: block;
    width: 100%;
    margin-top: 10px;
    background: linear-gradient(180deg, var(--gold), #f0a82d);
    color: #2a1500;
    border: 3px solid #000;
    box-shadow: 3px 3px 0 #000, 0 0 14px rgba(245, 194, 66, 0.55);
    padding: 12px 14px;
    font-family: var(--px); font-size: 13px; letter-spacing: 3px;
    text-align: center;
    cursor: pointer;
    animation: achClaimBob 1.4s ease-in-out infinite;
  }
  .ach-claim-btn:hover { filter: brightness(1.1); }
  .ach-claim-btn:active {
    transform: translate(2px, 2px);
    box-shadow: 2px 2px 0 #000, 0 0 8px rgba(245, 194, 66, 0.4);
  }
  @keyframes achClaimBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
  }
  /* Claim animation — flash to gold, snap, ready for re-render. */
  .ach-row.claiming {
    animation: achClaimFlash 0.8s ease-out;
  }
  @keyframes achClaimFlash {
    0%   { transform: scale(1);    background: linear-gradient(135deg, rgba(255, 61, 166, 0.18), rgba(245, 194, 66, 0.12)); }
    20%  { transform: scale(1.04); background: rgba(245, 194, 66, 0.55); box-shadow: 6px 6px 0 #000, 0 0 32px rgba(245,194,66,0.9); }
    60%  { transform: scale(1.02); background: rgba(245, 194, 66, 0.35); }
    100% { transform: scale(1);    background: rgba(245, 194, 66, 0.10); }
  }

  /* Sparkle burst — overlay layer that the JS dumps spans into. Each
     spark animates outward from the row center then fades. */
  .ach-spark-layer {
    position: fixed; inset: 0; pointer-events: none;
    z-index: 9999;
  }
  .ach-spark {
    position: absolute;
    width: 28px; height: 28px;
    image-rendering: pixelated;
    transform: translate(-50%, -50%);
    filter: drop-shadow(0 0 6px rgba(245,194,66,0.9)) drop-shadow(0 0 12px rgba(255,61,166,0.6));
    animation: achSparkFly var(--dur, 0.7s) cubic-bezier(.2,.7,.4,1) forwards;
    pointer-events: none;
  }
  @keyframes achSparkFly {
    0%   { opacity: 1; transform: translate(-50%, -50%) translate(0, 0)         scale(0.4) rotate(0deg); }
    35%  { opacity: 1; transform: translate(-50%, -50%) translate(calc(var(--dx) * 0.5), calc(var(--dy) * 0.5)) scale(1.2) rotate(120deg); }
    100% { opacity: 0; transform: translate(-50%, -50%) translate(var(--dx), var(--dy))     scale(0.5) rotate(360deg); }
  }

  /* Ready flag in the achievements summary header. */
  .ach-ready-flag {
    display: inline-block;
    margin-left: 8px;
    padding: 3px 8px;
    background: var(--neon); color:var(--ink);
    font-family: var(--px); font-size: 9px; letter-spacing: 1px;
    border: 2px solid #000;
    animation: achPillFlash 1.2s ease-in-out infinite;
  }

  /* Profile-screen CTA gets a glowing badge when claims are pending. */
  .ach-cta.has-ready {
    border-color: var(--neon);
    background: linear-gradient(135deg, rgba(255, 61, 166, 0.22), rgba(245, 194, 66, 0.16));
    animation: achRowPulse 1.6s ease-in-out infinite;
  }
  .ach-cta-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    background: var(--neon); color:var(--ink);
    border: 2px solid #000;
    font-size: 10px;
    animation: achIconBob 1.1s ease-in-out infinite;
  }
  .ach-cta-ready {
    color: var(--neon);
    font-weight: bold;
    text-shadow: 0 0 6px rgba(255,61,166,0.4);
  }

  /* Title cells — locked vs unlocked styling */
  .title-cell.locked {
    opacity: 0.42;
    filter: grayscale(0.6);
    position: relative;
  }
  .title-cell.locked::after {
    content: '🔒';
    position: absolute; top: 4px; right: 6px; font-size: 10px;
    opacity: 0.7;
  }
  .title-cell.unlocked-recent {
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000, 0 0 12px rgba(255, 206, 79, 0.4);
  }
  .meta-grid .m {
    background: #000; border: 2px solid var(--neon-2);
    box-shadow: 2px 2px 0 #000;
    border-radius: 0; padding: 10px 12px;
  }
  .meta-grid .m .l { font-family: var(--px); font-size: 7px; color: var(--neon-3); letter-spacing: 1px; }
  .meta-grid .m .v { font-family: var(--px); font-size: 11px; color: var(--gold); margin-top: 6px; }

  .toast {
    position: fixed; left: 50%; bottom: 110px; transform: translateX(-50%);
    background: #000; border: 3px solid var(--neon-3);
    color: var(--neon-3); padding: 10px 18px; border-radius: 0;
    font-family: var(--px); font-size: 9px; box-shadow: 4px 4px 0 #000;
    z-index: 50; opacity: 0; pointer-events: none;
    transition: opacity .15s steps(3), transform .15s;
    max-width: 88%; text-align: center;
  }
  .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

  .section-title {
    font-family: var(--px); font-size: 9px; color: var(--neon-3);
    letter-spacing: 1.5px; margin: 20px 0 12px;
    border-left: 4px solid var(--neon);
    padding-left: 10px;
  }
  /* Limits wizard step — quick-pick preset row, grouped section titles,
     emoji icons on each chip, and a live count badge above NEXT. The
     goal is to let new players one-tap into a sane setup while still
     giving veterans the granular toggles below. */
  .limit-presets-row {
    position: relative;
    display: flex; flex-wrap: wrap; gap: 8px;
    margin: 24px 0 18px;
    padding: 14px 12px 12px;
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.10), rgba(123, 92, 255, 0.10));
    border: 2px dashed rgba(245, 194, 66, 0.35);
  }
  .limit-presets-row::before {
    content: '▶ QUICK PRESETS';
    position: absolute;
    top: -10px; left: 12px;
    background: var(--bg-0); padding: 2px 8px;
    font-family: var(--px); font-size: 8px; letter-spacing: 2px;
    color: var(--gold); border: 1px dashed rgba(245, 194, 66, 0.4);
  }
  .limit-preset {
    flex: 1 1 auto;
    min-width: calc(50% - 4px);
    padding: 10px 12px;
    background: var(--card);
    border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.45), 2px 2px 0 #000;
    color: var(--ink);
    font-family: var(--px); font-size: 9px;
    letter-spacing: 0.5px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    transition: transform 0.06s, box-shadow 0.06s;
    text-align: center;
  }
  .limit-preset:active,
  .limit-preset.limit-preset-flash {
    transform: translate(2px, 2px);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.45), 0 0 0 #000;
  }
  .limit-preset-clear {
    background: rgba(255, 87, 100, 0.12);
    color: var(--danger);
  }
  .limit-preset-ic { font-size: 14px; line-height: 1; }
  .limit-preset-label { white-space: nowrap; }
  /* Group header — same .section-title styling but tighter top margin
     when it lives inside the limits step (the first one shouldn't have
     a big gap below the presets card). */
  .limit-group-title:first-child { margin-top: 12px; }
  .limit-chip-group { margin-bottom: 4px; }
  .limit-chip-ic {
    font-size: 11px; line-height: 1;
    margin-right: 2px;
  }
  /* Pet picker — inline row that appears below the "Playing with a
     pet here" allowance chip when toggled on. Visually nested (left
     border, indented padding) so the link to its parent chip is clear. */
  .pet-picker {
    flex-basis: 100%;
    margin: 4px 0 8px;
    padding: 10px 12px;
    border-left: 3px solid var(--gold);
    background: linear-gradient(135deg, rgba(245, 194, 66, 0.06), rgba(20, 10, 35, 0));
  }
  .pet-picker-label {
    font-family: var(--px); font-size: 8px;
    color: var(--gold); letter-spacing: 2px;
    margin-bottom: 8px;
  }
  .pet-picker-chips {
    gap: 6px;
  }
  .chip.pet-chip {
    font-size: 8px;
    padding: 6px 10px;
    border-color: rgba(245, 194, 66, 0.45);
  }
  .chip.pet-chip.on {
    background: var(--gold); color: #1a0d28;
    text-shadow: 1px 1px 0 rgba(255,255,255,0.25);
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
  }
  /* ALLOWANCES section header — uses the same .section-title pattern
     but in gold to signal "unlock" rather than the neon-green "restrict"
     hue used by the deny groups above. */
  .allow-group-title {
    color: var(--gold);
    border-left-color: var(--gold);
    margin-top: 26px;
  }
  .allow-group-sub {
    font-family: var(--term); font-size: 11px;
    color: var(--ink-faint); letter-spacing: 0.5px;
    margin-left: 6px;
  }
  /* Count badge — sits between the chips and the wizard's BACK/NEXT
     row. Subtle when empty, gold when picks exist. */
  .limits-count {
    display: flex; align-items: baseline; justify-content: center;
    gap: 8px;
    margin: 22px 0 6px;
    padding: 10px 14px;
    border: 2px solid var(--line);
    background: var(--card);
    font-family: var(--px); letter-spacing: 1.5px;
    color: var(--ink-faint);
    transition: color 0.2s, border-color 0.2s, box-shadow 0.2s;
  }
  .limits-count.has-picks {
    color: var(--gold); border-color: var(--gold);
    box-shadow: 2px 2px 0 #000, 0 0 12px rgba(245, 194, 66, 0.18);
  }
  .limits-count-num { font-size: 18px; }
  .limits-count-label { font-size: 9px; }
  /* ── Style step (build 245): one-tap preset cards ────────────────
     Quick-style + Story-mode universe cards on the new Style step. */
  .style-card-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    margin: 8px 0 4px;
  }
  .style-card {
    display: flex; flex-direction: column; align-items: center;
    text-align: center; gap: 4px;
    padding: 14px 10px;
    background: var(--card);
    border: 3px solid #000;
    box-shadow: 4px 4px 0 #000;
    cursor: pointer;
    transition: transform 0.08s, box-shadow 0.08s, border-color 0.15s;
    font-family: var(--term);
  }
  .style-card:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 #000; }
  .style-card.on {
    border-color: var(--neon-3);
    box-shadow: 4px 4px 0 #000, inset 0 0 0 2px var(--neon-3), 0 0 14px rgba(0,230,195,0.3);
  }
  .style-card-ic { font-size: 30px; line-height: 1; }
  .style-card-img {
    width: 46px; height: 46px; object-fit: contain;
    image-rendering: pixelated;
  }
  /* Painted pixel-art symbol icons inside limit / allowance / preset /
     pet chips (build 247 — replaced the old emoji). */
  .chip-ic-img {
    width: 16px; height: 16px; object-fit: contain;
    image-rendering: pixelated; vertical-align: middle;
  }
  .limit-preset-ic .chip-ic-img { width: 18px; height: 18px; }
  .style-card-name {
    font-family: var(--px); font-size: 11px; letter-spacing: 1px;
    color: var(--ink); margin-top: 2px;
  }
  .style-card.on .style-card-name { color: var(--neon-3); }
  .style-card-blurb { font-size: 12px; color: var(--ink-dim); line-height: 1.35; }
  .story-sub {
    font-family: var(--term); font-size: 12px;
    color: var(--ink-faint); letter-spacing: 0; text-transform: none;
  }
  .style-advanced-toggle {
    width: 100%; margin-top: 18px;
    padding: 12px 14px;
    background: var(--card);
    border: 2px dashed var(--line);
    color: var(--ink-dim);
    font-family: var(--px); font-size: 10px; letter-spacing: 1px;
    text-align: left; cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
  }
  .style-advanced-toggle.open { color: var(--neon-3); border-color: var(--neon-3); }
  .style-advanced-body {
    margin-top: 4px; padding: 12px;
    border: 2px solid var(--line); border-top: 0;
    background: rgba(0,0,0,0.18);
  }
  /* When the gremlin's running the show, swap the dashed gold accent
     for a faint cursed green so the preset row still reads as "his". */
  body.unhinged-run .limit-presets-row {
    background: linear-gradient(135deg, rgba(124, 252, 0, 0.08), rgba(123, 92, 255, 0.10));
    border-color: rgba(124, 252, 0, 0.32);
  }
  body.unhinged-run .limit-presets-row::before {
    color: var(--unhinged-green, #7CFC00);
    border-color: rgba(124, 252, 0, 0.4);
  }

  .empty {
    text-align: center; padding: 36px 16px; color: var(--ink-faint);
    font-family: var(--px); font-size: 9px; line-height: 1.8;
  }

  /* Phase 5 — Pixel-art arcade cabinet wrapping the home screen. Inspired
     by classic upright cabinets: curved top → pink marquee → recessed
     CRT → teal control panel with joystick + buttons → purple coin door
     at the base. Pink/magenta highlight strips run down both sides as
     the cabinet's neon trim. Restrained palette so the menu inside
     stays the visual hero. */
  /* Magical obsidian pedestal that sits directly under the cabinet,
     making it look "placed" on a magical platform rather than
     floating in the dark void. Same max-width as the cabinet so they
     visually line up; small negative top margin tucks it under the
     cabinet's bottom edge so there's no visible seam. */
  .arcade-pedestal {
    display: block;
    /* Negative side margins pull the pedestal wider than the
       cabinet/#app container so the rock visually extends past the
       machine's footprint, anchoring it. */
    margin: -4px -8px 14px -8px;
    width: calc(100% + 16px);
    max-width: none;
    height: auto;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
    /* Stronger magical glow on the rock with a slow breathing pulse
       — three layered drop-shadows give it a hot-pink core, a
       softer purple halo, and a wider pink ambient bloom.
       Combined with a gentle ±4px vertical float so the island
       feels suspended, not pasted. */
    animation: arcadePedestalGlow 6s ease-in-out infinite;
  }
  @keyframes arcadePedestalGlow {
    0%, 100% {
      filter:
        drop-shadow(0 0 5px  rgba(255,61,166,0.35))
        drop-shadow(0 0 12px rgba(180,108,255,0.22))
        drop-shadow(0 0 22px rgba(255,61,166,0.12));
    }
    50% {
      filter:
        drop-shadow(0 0 8px  rgba(255,61,166,0.5))
        drop-shadow(0 0 18px rgba(180,108,255,0.35))
        drop-shadow(0 0 30px rgba(255,61,166,0.2));
    }
  }
  @keyframes arcadePedestalFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(4px); }
  }
  .arcade-cabinet {
    position: relative;
    /* Bottom margin removed so the pedestal sits flush against the
       cabinet's bottom edge — the pedestal carries its own bottom
       margin to space the next page element. */
    margin: 6px auto 0;
    max-width: 520px;
    /* Bottom padding removed so the controls panel can flush against
       the cabinet's bottom border. */
    padding: 14px 22px 0;
    background: linear-gradient(180deg, #1f1235 0%, #150b25 55%, #0a0518 100%);
    border: 3px solid #000;
    border-top-left-radius: 26px;
    border-top-right-radius: 26px;
    box-shadow:
      inset 0 0 0 2px #b46cff,
      inset 0 0 0 6px #150b25,
      6px 6px 0 #000,
      0 0 18px rgba(180,108,255,0.28);
    /* Slow phosphorescent breathing glow on the cabinet outline. ~4s
       cycle so it doesn't distract; intensity rides between a low
       resting glow and a brighter peak. */
    animation: arcadeGlowPulse 4s ease-in-out infinite;
  }
  @keyframes arcadeGlowPulse {
    0%, 100% {
      box-shadow:
        inset 0 0 0 2px #b46cff,
        inset 0 0 0 6px #150b25,
        6px 6px 0 #000,
        0 0 14px rgba(180,108,255,0.22);
    }
    50% {
      box-shadow:
        inset 0 0 0 2px #d4a3ff,
        inset 0 0 0 6px #150b25,
        6px 6px 0 #000,
        0 0 38px rgba(180,108,255,0.65);
    }
  }
  /* Continuous pink-purple frame wrapping the entire cabinet —
     curves at the top corners, runs down both sides, connects across
     the bottom. Replaces the previous separate left/right side
     strips. Rendered as a single ::before that sits BEHIND the
     cabinet body (z-index: -1) so only the 6px ring around the
     cabinet's edges is visible. */
  .arcade-cabinet::before {
    content: '';
    position: absolute;
    inset: -6px;
    background: linear-gradient(180deg, #d4a3ff 0%, #b46cff 50%, #5a2a99 100%);
    border: 2px solid #000;
    border-radius: 32px 32px 16px 16px;
    box-shadow:
      inset 0 0 6px rgba(255,255,255,0.45),
      0 0 14px rgba(180,108,255,0.6);
    z-index: -1;
    pointer-events: none;
  }

  .arcade-marquee {
    position: relative;
    text-align: center;
    font-family: var(--px); font-size: 11px;
    color: #1a0a3d;
    letter-spacing: 4px;
    padding: 8px 4px;
    background: linear-gradient(180deg, #d4a3ff 0%, #b46cff 100%);
    border: 2px solid #000;
    box-shadow:
      inset 0 -3px 0 rgba(0,0,0,0.22),
      inset 0 2px 0 rgba(255,255,255,0.45),
      0 2px 0 #000,
      0 0 14px rgba(180,108,255,0.5);
    text-shadow: 0 1px 0 rgba(255,255,255,0.45);
    margin-bottom: 10px;
  }
  /* Marquee end-cap blocks (the dark squares at each end of an arcade marquee). */
  .arcade-marquee::before,
  .arcade-marquee::after {
    content: '';
    position: absolute;
    top: 50%;
    width: 8px; height: 8px;
    background: #2a1740;
    border: 2px solid #000;
    transform: translateY(-50%);
  }
  .arcade-marquee::before { left: -2px; }
  .arcade-marquee::after  { right: -2px; }

  .arcade-screen-wrap {
    position: relative;
    /* Dark-purple panel (build 254) — ties the content to the purple
       cabinet instead of reading as flat void. A faint top glow + 1.5%
       diagonal stripes give the dead space depth without ever
       competing with the neon cards. */
    background:
      radial-gradient(ellipse 120% 55% at 50% 0%, rgba(123,92,255,0.12), transparent 70%),
      repeating-linear-gradient(45deg, rgba(255,255,255,0.015) 0 7px, transparent 7px 14px),
      #160c2b;
    border: 2px solid #000;
    box-shadow:
      inset 0 0 0 2px #5a3580,
      inset 0 0 0 4px #2a1740,
      inset 0 0 50px rgba(0,0,0,0.9);
    padding: 6px;
    overflow: hidden;
    border-radius: 6px / 8px;
  }
  .arcade-screen-wrap > .screen {
    margin: 0;
    padding: 8px 8px 14px;
    /* Floor on the screen height so the cabinet doesn't collapse on
       short content (e.g. an empty bag), but kept low enough that
       home doesn't have a giant dead-space gap under the SOLO card. */
    min-height: 44vh;
    background: transparent;
    border-radius: 4px / 6px;
  }
  /* Header (QUESTIRL + lvl + coins) when it's mounted inside the cabinet:
     drop the sticky positioning, sit on the cabinet's purple body, and
     align with the marquee width. */
  .arcade-cabinet > .top-bar {
    position: static;
    background: transparent;
    padding: 8px 14px 6px;
    border-bottom: 1px dashed rgba(180,108,255,0.22);
    margin: 0 0 8px;
  }
  /* Tab nav inside the cabinet — sits in the cabinet's flow at the
     bottom of the screen wrap, scoped to the cabinet width so it
     visually belongs to the machine body. Smooth purple-pink border
     with rounded corners + soft outer glow + a rotating lighter-
     purple spotlight that orbits the perimeter. */
  /* Tab nav now reads as a recessed slot cut into the cabinet body —
     no rounded corners, no outer glow, no orbiting spark. Faint
     wood-grain stripes for surface texture matching the control
     panel below, plus inset shadows that simulate the slot being
     pressed into the cabinet wood. */
  .arcade-cabinet > nav.tabs {
    position: relative;
    max-width: none;
    width: 100%;
    margin: 10px 0 0;
    background:
      repeating-linear-gradient(
        90deg,
        rgba(180,108,255,0.05) 0 1px,
        transparent 1px 4px
      ),
      linear-gradient(180deg, #1f1235 0%, #150b25 55%, #0a0518 100%);
    border: 2px solid #1a0a18;
    border-radius: 0;
    box-shadow:
      /* recessed-slot effect: dark inner shadow at the top + a
         subtle highlight at the bottom edge */
      inset 0 4px 6px rgba(0,0,0,0.7),
      inset 0 -1px 0 rgba(180,108,255,0.18),
      inset 1px 0 0 rgba(0,0,0,0.5),
      inset -1px 0 0 rgba(0,0,0,0.5);
    z-index: auto;
  }

  /* Control panel — purple slab matching the cabinet body, with a faint
     neon-purple top edge highlight + bottom shadow for plastic depth.
     Joystick on the left, buttons in the middle, coin slot on the right. */
  /* Single-image control panel — keypad sticker + joystick + 3 buttons
     + coin slot, all on the magical-wood panel body, are one PNG.
     New image is natively 4:1 with the panel filling the canvas, so
     we render at natural aspect — no CSS crop hack needed. */
  /* Flush against the tabs above and the cabinet bottom border below.
     Slight negative horizontal margin pulls the panel out modestly
     past the cabinet's 22px padding (not the full distance) for a
     snug fit that still leaves a hint of cabinet trim showing on
     each side. */
  .arcade-controls {
    position: relative;
    margin: 0 -12px;
    width: calc(100% + 24px);
    aspect-ratio: 4 / 1;
    line-height: 0;
  }
  .arcade-controls-panel {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
    /* Magical pink/purple glow around the panel — drop-shadow follows
       the alpha channel of the PNG so the glow hugs the panel's actual
       edges (and the gold filigree corners) instead of a rectangle. */
    filter:
      drop-shadow(0 0 6px rgba(255,61,166,0.55))
      drop-shadow(0 0 12px rgba(180,108,255,0.35));
    animation: arcadePanelGlow 7s ease-in-out infinite;
  }
  @keyframes arcadePanelGlow {
    0%, 100% {
      filter:
        drop-shadow(0 0 5px rgba(255,61,166,0.5))
        drop-shadow(0 0 10px rgba(180,108,255,0.3));
    }
    50% {
      filter:
        drop-shadow(0 0 9px rgba(255,61,166,0.75))
        drop-shadow(0 0 18px rgba(180,108,255,0.55));
    }
  }
  /* Legacy decorative classes kept as no-ops in case they're still
     referenced elsewhere. */
  .arcade-instructions-line {
    display: none;
    width: 38px; height: 2px;
    background: repeating-linear-gradient(
      90deg,
      #5a2a1a 0 3px, transparent 3px 5px,
      #5a2a1a 5px 7px, transparent 7px 11px,
      #5a2a1a 11px 14px, transparent 14px 17px,
      #5a2a1a 17px 22px, transparent 22px 24px,
      #5a2a1a 24px 28px, transparent 28px 31px,
      #5a2a1a 31px 36px, transparent 36px 38px
    );
  }
  .arcade-instructions-line.short { width: 24px; }

  /* Invisible click hotspot positioned over the coin slot in the
     enchanted panel image. Percentages so it scales with the panel
     as the viewport changes. Click triggers the existing coin-drop
     animation and is also the target of the home-screen "INSERT COIN"
     hero blink (which calls door.click()). */
  .arcade-coin-door {
    position: absolute;
    left: 82%;
    top: 14%;
    width: 16%;
    height: 76%;
    background: transparent;
    border: none;
    box-shadow: none;
    cursor: pointer;
    transition: transform 0.08s ease-out;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .arcade-coin-door:active { transform: translateY(1px); }
  .arcade-coin-img {
    display: block;
    width: 100%; height: 100%;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: none;
  }
  /* Flash effect when a coin drops — a brief gold glow over the
     plate. Replaces the old slit-pseudo flash. */
  .arcade-coin-door.arcade-coin-flash {
    filter: drop-shadow(0 0 8px rgba(255,206,79,0.95)) brightness(1.3);
  }
  /* Refuse-shake keyframes live further down (kept once, not duplicated). */
  /* Coin-drop easter egg. A coin spawns above the slot, falls in, briefly
     flashes the slot, then disappears. Element is created on click and
     removed when its animation ends. */
  .arcade-coin-fly {
    position: absolute;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #fff5b4 0%, #ffce4f 45%, #b08418 90%);
    border: 2px solid #000;
    box-shadow: 0 0 6px rgba(255,206,79,0.6);
    z-index: 5;
    pointer-events: none;
    animation: coinDrop 0.65s cubic-bezier(0.55, 0, 0.7, 0.85) forwards;
  }
  @keyframes coinDrop {
    0%   { transform: translate(-50%, -90px) rotate(0deg) scale(1);    opacity: 1; }
    65%  { transform: translate(-50%, -2px)  rotate(540deg) scale(0.6);opacity: 1; }
    100% { transform: translate(-50%, 6px)   rotate(720deg) scale(0.2);opacity: 0; }
  }
  /* Old slit-pseudo flash removed — image-driven flash now lives on
     .arcade-coin-door.arcade-coin-flash above (drop-shadow + brightness). */
  /* Floating "−1 🪙" pop that drifts up out of the slot when a coin is
     deposited. Each click creates a fresh element so rapid taps stack. */
  .arcade-coin-pop {
    position: absolute;
    left: 50%; top: -6px;
    transform: translate(-50%, 0);
    font-family: var(--px); font-size: 11px;
    color: var(--gold);
    text-shadow: 1px 1px 0 #000, 0 0 6px rgba(255,206,79,0.6);
    pointer-events: none;
    z-index: 6;
    animation: coinPopFloat 0.85s ease-out forwards;
  }
  @keyframes coinPopFloat {
    0%   { transform: translate(-50%, 0)    scale(0.7); opacity: 0; }
    20%  { transform: translate(-50%, -10px) scale(1.1); opacity: 1; }
    100% { transform: translate(-50%, -52px) scale(0.9); opacity: 0; }
  }
  /* Door refusal shake — when the player has 0 coins. */
  .arcade-coin-door.arcade-coin-refuse {
    animation: coinRefuseShake 0.32s steps(4) 1;
  }
  @keyframes coinRefuseShake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-3px); }
    50% { transform: translateX(3px); }
    75% { transform: translateX(-2px); }
  }

  /* Tab transition — inner screen slides while the cabinet outline stays. */
  .arcade-screen-wrap > .screen.tab-slide-in-right {
    animation: tabSlideInFromRight 220ms ease-out;
  }
  .arcade-screen-wrap > .screen.tab-slide-in-left {
    animation: tabSlideInFromLeft 220ms ease-out;
  }
  .arcade-screen-wrap > .screen.tab-slide-out-left {
    animation: tabSlideOutLeft 180ms ease-in forwards;
  }
  .arcade-screen-wrap > .screen.tab-slide-out-right {
    animation: tabSlideOutRight 180ms ease-in forwards;
  }
  /* Pure horizontal translation, fully offscreen at the slide ends.
     The previous 40% offsets caused a visible flash because both
     slide-out's end (-40%) and slide-in's start (+40%) were still
     partially visible inside the wrap: when the new content's
     element jumped between those positions, you saw 60% of content
     flip from one side to the other. Pushing both ends to 100%
     means the seam jump happens entirely off-screen, behind the
     wrap's overflow:hidden clip. */
  @keyframes tabSlideInFromRight {
    0%   { transform: translateX(100%); }
    100% { transform: translateX(0);    }
  }
  @keyframes tabSlideInFromLeft {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(0);     }
  }
  @keyframes tabSlideOutLeft {
    0%   { transform: translateX(0);     }
    100% { transform: translateX(-100%); }
  }
  @keyframes tabSlideOutRight {
    0%   { transform: translateX(0);    }
    100% { transform: translateX(100%); }
  }

  /* Phase 5 — Abandon CRT-power-off: animates the WHOLE app, not an
     overlay. The visible game element flashes, collapses, then fades —
     and the body's dark background shows through behind it. */
  #app.app-power-off {
    animation: appPowerOff 520ms cubic-bezier(0.6, 0, 0.4, 1) forwards;
    transform-origin: center center;
  }
  @keyframes appPowerOff {
    0%   { filter: brightness(1) contrast(1);     transform: scale(1);                     opacity: 1; }
    14%  { filter: brightness(2.8) contrast(1.4); transform: scaleX(1.04) scaleY(1.04);    opacity: 1; }
    30%  { filter: brightness(0.9);               transform: scaleX(1) scaleY(0.95);       opacity: 1; }
    50%  { filter: brightness(2.2);               transform: scaleX(1) scaleY(0.07);       opacity: 1; }
    70%  { filter: brightness(0.4);               transform: scaleX(0.6) scaleY(0.01);     opacity: 1; }
    100% { filter: brightness(0);                 transform: scaleX(0.04) scaleY(0);       opacity: 0; }
  }
  /* Snap back in once the new view has been rendered behind the off
     state — short fade-up so the next screen doesn't feel jarring. */
  #app.app-power-on-after {
    animation: appPowerOnAfter 280ms ease-out;
  }
  @keyframes appPowerOnAfter {
    0%   { opacity: 0; transform: scale(0.97); filter: brightness(0.5); }
    100% { opacity: 1; transform: scale(1);    filter: brightness(1); }
  }

  /* Phase 5 — Zoom into the cabinet's CRT screen when entering a run.
     Quick brightness blink, then smooth scale-up that hides the cabinet
     body so only the inner screen is visible by the end. Origin is
     computed live in zoomIntoArcadeScreen() to anchor on the real
     CRT bezel center (handles iPhone Safari's collapsing URL bar). */
  #app.app-arcade-zoom {
    animation: arcadeZoomScreen 850ms cubic-bezier(0.55, 0.05, 0.4, 1) forwards;
    transform-origin: 50% 38%;
  }
  @keyframes arcadeZoomScreen {
    0%   { transform: scale(1);    filter: brightness(1); }
    8%   { transform: scale(1.01); filter: brightness(2.6); }
    16%  { transform: scale(1.01); filter: brightness(0.6); }
    24%  { transform: scale(1.01); filter: brightness(1); }
    100% { transform: scale(2.6);  filter: brightness(1); opacity: 0; }
  }
  #app.app-arcade-zoom .arcade-marquee,
  #app.app-arcade-zoom > #arcadeShell > .top-bar,
  #app.app-arcade-zoom nav.tabs,
  #app.app-arcade-zoom .arcade-controls,
  #app.app-arcade-zoom .arcade-coin-door {
    animation: arcadePeripheralFade 600ms ease-out 250ms forwards;
  }
  @keyframes arcadePeripheralFade {
    0%   { opacity: 1; }
    100% { opacity: 0; }
  }

  /* Phase 5 — CRT power-on flicker. Played once when the quest screen
     opens after the loading screen finishes. Mimics an old TV: a thin
     bright horizontal line snaps open into the full image, with a brief
     overexposed flash and a final settle. Animation stays under 700ms
     so it doesn't stall the player. */
  .screen.crt-power-on {
    animation: crtPowerOn 600ms cubic-bezier(0.2, 0.85, 0.25, 1) forwards;
    transform-origin: center center;
  }
  @keyframes crtPowerOn {
    0% {
      transform: scaleX(0.85) scaleY(0.005);
      filter: brightness(2.4) contrast(1.4);
      opacity: 0.2;
    }
    18% {
      transform: scaleX(1.02) scaleY(0.02);
      filter: brightness(2.6) contrast(1.4);
      opacity: 0.85;
    }
    35% {
      transform: scaleX(1.04) scaleY(1.05);
      filter: brightness(1.9) contrast(1.2);
      opacity: 1;
    }
    55% {
      transform: scale(1);
      filter: brightness(1.4) contrast(1.05);
    }
    72% {
      filter: brightness(1.0) contrast(1.0);
    }
    78% { filter: brightness(1.6) contrast(1.1); } /* final blink */
    84% { filter: brightness(0.92) contrast(1.0); }
    100% {
      transform: scale(1);
      filter: brightness(1.0) contrast(1.0);
      opacity: 1;
    }
  }

  /* Themed rename modal — neon-green frame, marquee header, pixel input. */
  .name-modal {
    background: linear-gradient(180deg, #1f1235 0%, #150b25 100%);
    border: 3px solid #000;
    box-shadow:
      inset 0 0 0 2px #b46cff,
      6px 6px 0 #000,
      0 0 22px rgba(180,108,255,0.4);
    padding: 0;
    overflow: hidden;
    max-width: 360px;
    width: 92%;
  }
  .name-modal-marquee {
    text-align: center;
    font-family: var(--px); font-size: 10px;
    color: #1a0a3d;
    letter-spacing: 4px;
    padding: 10px 8px;
    background: linear-gradient(180deg, #d4a3ff 0%, #b46cff 100%);
    border-bottom: 2px solid #000;
    box-shadow:
      inset 0 -3px 0 rgba(0,0,0,0.18),
      inset 0 2px 0 rgba(255,255,255,0.4);
    text-shadow: 0 1px 0 rgba(255,255,255,0.4);
  }
  .name-modal-body { padding: 18px 18px 16px; }
  .name-modal-label {
    font-family: var(--px); font-size: 10px;
    color: #b46cff; letter-spacing: 2px;
    display: block; margin-bottom: 8px;
  }
  .name-modal #nameModalInput {
    width: 100%;
    padding: 12px 14px;
    background: #0a0518;
    color: #e8ffe9;
    font-family: var(--px); font-size: 14px;
    letter-spacing: 1px;
    border: 2px solid #000;
    box-shadow: inset 0 0 0 2px #b46cff, inset 0 0 12px rgba(180,108,255,0.18);
    outline: none;
    text-align: center;
    text-shadow: 0 0 6px rgba(180,108,255,0.5);
  }
  .name-modal #nameModalInput::placeholder {
    color: rgba(180,108,255,0.4);
  }
  .name-modal #nameModalInput:focus {
    box-shadow: inset 0 0 0 2px #d4a3ff, inset 0 0 18px rgba(127,255,186,0.25);
  }
  .name-modal-hint {
    font-family: var(--term); font-size: 13px;
    color: var(--ink-faint);
    margin-top: 6px; text-align: center;
  }

  /* Chat typewriter — blinking caret while a host/tag message is typing in. */
  .chat-msg.chat-typing .chat-msg-body::after {
    content: '▌';
    color: var(--neon);
    margin-left: 2px;
    animation: chatCaretBlink 0.6s steps(2) infinite;
  }
  @keyframes chatCaretBlink {
    50% { opacity: 0; }
  }

  /* Profile name row — name + pencil edit button. */
  .profile-name-row {
    display: inline-flex; align-items: center; gap: 8px;
    justify-content: center;
  }
  .profile-name {
    overflow: hidden; text-overflow: ellipsis; max-width: 220px;
    white-space: nowrap;
  }
  .profile-name-edit {
    font-family: var(--px); font-size: 11px;
    background: var(--card-2);
    color: var(--neon-3);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    padding: 4px 8px;
    cursor: pointer;
    transition: transform .06s;
    line-height: 1;
  }
  .profile-name-edit:hover { background: var(--card); }
  .profile-name-edit:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
  .name-edit-ic {
    width: 14px; height: 14px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }

  /* Custom scrollbar — pixel-thick, neon-green thumb in a dark track,
     matches the arcade cabinet glow. WebKit + Firefox both supported. */
  * {
    scrollbar-width: thin;
    scrollbar-color: #b46cff #150b25;
  }
  ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  ::-webkit-scrollbar-track {
    background: #0a0518;
    border-left: 2px solid #000;
    box-shadow: inset 1px 0 0 #150b25;
  }
  ::-webkit-scrollbar-thumb {
    background: linear-gradient(180deg, #d4a3ff 0%, #b46cff 50%, #5a2a99 100%);
    border: 2px solid #000;
    box-shadow:
      inset 0 0 4px rgba(255,255,255,0.35),
      0 0 6px rgba(180,108,255,0.45);
  }
  ::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(180deg, #dfb8ff 0%, #a458ff 50%, #4a1f7d 100%);
    box-shadow:
      inset 0 0 4px rgba(255,255,255,0.5),
      0 0 10px rgba(180,108,255,0.7);
  }
  ::-webkit-scrollbar-corner {
    background: #0a0518;
  }

  /* Phase 5 — Reconnect-to-room card on home screen. Persisted from
     create/join, rendered when the saved room is still alive. */
  .reconnect-card {
    margin: 18px auto 14px;
    max-width: 460px;
    background: var(--card);
    border: 3px solid var(--neon-3);
    box-shadow: 5px 5px 0 #000;
    padding: 12px 14px;
    animation: rcPulse 2.4s ease-in-out infinite;
  }
  @keyframes rcPulse {
    0%, 100% { box-shadow: 5px 5px 0 #000; }
    50%      { box-shadow: 5px 5px 0 #000, 0 0 16px rgba(123,255,168,0.5); }
  }
  .reconnect-card .rc-head {
    display: flex; align-items: center; gap: 8px;
    border-bottom: 2px dashed var(--line);
    padding-bottom: 8px; margin-bottom: 10px;
  }
  .reconnect-card .rc-ic { font-size: 22px; }
  .reconnect-card .rc-label {
    font-family: var(--px); font-size: 10px;
    color: var(--neon-3); letter-spacing: 2px;
  }
  .reconnect-card .rc-body { text-align: center; padding: 4px 0 10px; }
  .reconnect-card .rc-code {
    font-family: var(--px); font-size: 22px; color: var(--ink);
    letter-spacing: 6px; text-shadow: 3px 3px 0 #000;
    margin-bottom: 4px;
  }
  .reconnect-card .rc-meta {
    font-family: var(--term); font-size: 14px; color: var(--ink-dim);
  }
  .reconnect-card .rc-actions {
    display: flex; gap: 8px;
  }
  /* Resume-run card — same chassis as reconnect, gold accent instead of cyan */
  .resume-card {
    margin: 18px auto 14px;
    max-width: 460px;
    background: var(--card);
    border: 3px solid var(--gold);
    box-shadow: 5px 5px 0 #000;
    padding: 12px 14px;
  }
  .resume-card .rc-head {
    display: flex; align-items: center; gap: 8px;
    border-bottom: 2px dashed var(--line);
    padding-bottom: 8px; margin-bottom: 10px;
  }
  .resume-card .rc-ic { font-size: 16px; color: var(--gold); }
  .resume-card .rc-label {
    font-family: var(--px); font-size: 10px;
    color: var(--gold); letter-spacing: 2px;
  }
  .resume-card .rc-age {
    font-family: var(--term); font-size: 12px; color: var(--ink-faint);
    margin-left: auto;
  }
  .resume-card .rc-body { text-align: center; padding: 4px 0 10px; }
  .resume-card .rc-boss {
    font-family: var(--px); font-size: 13px; color: var(--ink);
    letter-spacing: 1px; margin-bottom: 4px;
    text-shadow: 2px 2px 0 #000;
  }
  .resume-card .rc-meta {
    font-family: var(--term); font-size: 13px; color: var(--ink-dim);
  }
  .resume-card .rc-actions {
    display: flex; gap: 8px;
  }
  .resume-card .rc-actions .btn { flex: 1; }
  .reconnect-card .rc-actions .btn { flex: 1; }

  /* Player chip */
  .player-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 10px 6px 6px;
    background: var(--card-2); border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    font-family: var(--px); font-size: 9px;
  }
  .player-chip .av {
    width: 22px; height: 22px;
    background: var(--neon); border: 2px solid #000;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--px); font-size: 9px; color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }

  /* ---------- Toggle (traitor on/off) ---------- */
  .toggle-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 14px;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    margin-top: 14px;
  }
  .toggle-row .info { flex: 1; padding-right: 10px; }
  .toggle-row .info h4 { font-size: 10px; color: var(--gold); margin-bottom: 4px; }
  .toggle-row .info p { font-family: var(--term); font-size: 15px; color: var(--ink-dim); }
  .toggle {
    position: relative; width: 56px; height: 28px;
    background: #000; border: 2px solid #000;
    box-shadow: inset 1px 1px 0 rgba(255,255,255,0.05);
    cursor: pointer; flex-shrink: 0;
  }
  .toggle .knob {
    position: absolute; top: 2px; left: 2px;
    width: 20px; height: 20px;
    background: var(--ink-faint);
    border: 2px solid #000;
    transition: left .12s steps(3), background .12s;
  }
  .toggle.on { background: var(--neon-3); }
  .toggle.on .knob { left: 30px; background: var(--gold); }

  /* ---------- Settings cog button ---------- */
  .cog-btn {
    background: var(--card);
    border: 2px solid var(--line);
    box-shadow: 3px 3px 0 #000;
    width: 30px; height: 30px;
    box-sizing: border-box;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; font-size: 16px;
    margin-right: 6px;
    padding: 0;
  }
  .cog-btn .topbar-ic { width: 22px; height: 22px; }
  /* Music toggle — same chassis as the cog, with a pixel-art note
     icon inside and an optional 3-bar animated soundwave overlay
     in the bottom-right corner that only animates while the music
     is actually audible. The icon swaps between setting_sound_on.png and
     setting_sound_off.png based on the audible state. */
  .music-btn {
    position: relative;
    overflow: visible;
    padding: 0;
  }
  .music-btn-img {
    width: 28px; height: 28px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: block;
  }
  .music-waves {
    /* Sits at the base of the music button — three small bars
       hugging the bottom edge of the 32×32 chassis, so the waves
       read as sound radiating up from the bottom of the note. */
    position: absolute;
    bottom: 2px;
    left: 50%;
    transform: translateX(-50%);
    display: none;
    align-items: flex-end;
    gap: 2px;
    height: 12px;
    pointer-events: none;
  }
  .music-btn.playing .music-waves { display: flex; }
  .music-waves span {
    /* No border — at this scale a 1px border on each side ate the
       whole bar, leaving only the black outline visible. We keep a
       single drop-shadow pixel for the chunky pixel-art feel. */
    display: inline-block;
    width: 3px;
    background: var(--neon);
    box-shadow: 1px 1px 0 #000;
    animation: musicWave 0.7s ease-in-out infinite;
  }
  .music-waves span:nth-child(1) { animation-delay: 0s; }
  .music-waves span:nth-child(2) { animation-delay: 0.18s; }
  .music-waves span:nth-child(3) { animation-delay: 0.36s; }
  @keyframes musicWave {
    0%, 100% { height: 3px; }
    50%      { height: 11px; }
  }

  /* SFX top-bar toggle — same chassis as music-btn, swaps in a lightning
     glyph corner badge instead of soundwaves so the two buttons read
     differently at a glance. */
  .sfx-btn { position: relative; overflow: visible; padding: 0; }
  .sfx-bolt {
    position: absolute;
    bottom: -2px;
    right: -2px;
    font-size: 12px;
    line-height: 1;
    text-shadow: 1px 1px 0 #000;
    color: var(--gold);
    pointer-events: none;
    opacity: 0;
    transition: opacity .15s ease;
  }
  .sfx-btn.playing .sfx-bolt { opacity: 1; }

  /* ---------- Modal ---------- */
  .modal-bg {
    position: fixed; inset: 0; background: rgba(0,0,0,0.75);
    z-index: 80; display: flex; align-items: center; justify-content: center;
    padding: 18px; animation: fadeUp .2s ease;
  }

  /* Dev-only settings block — gold-tinted card inside the Settings
     modal exposing dev tools (Ideas tab, Dev Menu) without polluting
     the regular settings flow for end-users. */
  .dev-settings-block {
    margin-top: 18px;
    padding: 12px;
    border: 2px dashed var(--gold);
    background: rgba(245, 194, 66, 0.08);
    display: flex; flex-direction: column; gap: 8px;
  }
  .dev-settings-h {
    font-family: var(--px); font-size: 9px; letter-spacing: 1.5px;
    color: var(--gold);
    margin-bottom: 4px;
  }
  .dev-settings-block .btn {
    width: 100%;
    text-align: left;
    justify-content: flex-start;
    font-size: 11px;
  }
  /* Dev mode floating badge — sits in the top-left corner on every screen
     when dev mode is active. Click → opens the dev menu. Type the unlock
     code anywhere on the page to toggle it. */
  .dev-badge {
    position: fixed;
    top: 8px; left: 8px;
    z-index: 90;
    background: var(--gold);
    color: #2a1500;
    border: 2px solid #000;
    box-shadow: 3px 3px 0 #000;
    padding: 6px 10px;
    font-family: var(--px); font-size: 10px; letter-spacing: 1px;
    cursor: pointer;
    animation: devBadgePulse 2s ease-in-out infinite;
  }
  .dev-badge:active {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 #000;
  }
  @keyframes devBadgePulse {
    0%, 100% { box-shadow: 3px 3px 0 #000, 0 0 0 rgba(245,194,66,0); }
    50%      { box-shadow: 3px 3px 0 #000, 0 0 12px rgba(245,194,66,0.6); }
  }
  /* Dev menu modal sections */
  .dev-menu-section {
    border-top: 2px dashed var(--line);
    padding: 10px 0 4px;
    display: flex; flex-direction: column; gap: 6px;
  }
  .dev-menu-section:first-of-type { border-top: none; padding-top: 0; }
  .dev-menu-h {
    font-family: var(--px); font-size: 9px; letter-spacing: 2px;
    color: var(--neon-3); margin-bottom: 4px;
  }
  .dev-menu-section .btn {
    width: 100%;
    justify-content: flex-start;
    text-align: left;
    font-size: 12px;
  }
  .modal {
    width: 100%; max-width: 420px;
    background: var(--bg-2); border: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-2), 6px 6px 0 #000;
    padding: 18px;
    max-height: 80vh; overflow-y: auto;
  }
  .modal h3 { font-size: 13px; color: var(--gold); margin-bottom: 12px; text-shadow: 2px 2px 0 #000; }
  .modal .warn {
    font-family: var(--term); font-size: 15px; color: var(--danger);
    background: rgba(255,87,100,0.08); border: 2px solid var(--danger);
    padding: 10px; margin-bottom: 12px;
  }
  .modal label {
    display: block; font-family: var(--px); font-size: 8px;
    color: var(--neon-3); margin-bottom: 6px; letter-spacing: 1px;
  }

  /* ---------- Streak fire ---------- */
  .streak-card {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 16px;
    background: linear-gradient(90deg, #2a0f0f, #1a0a1a);
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 4px 4px 0 #000;
    margin-bottom: 14px;
  }
  .streak-card .fire {
    font-size: 38px; text-shadow: 0 0 12px #ff5764, 3px 3px 0 #000;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    animation: streakBob 2.4s ease-in-out infinite;
  }
  .streak-fire-img {
    width: 100%; height: 100%; object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    animation: streakPulse 1.6s ease-in-out infinite;
  }
  @keyframes streakBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
  }
  @keyframes streakPulse {
    0%, 100% { filter: drop-shadow(0 0 6px rgba(255,87,100,0.55)) drop-shadow(0 0 12px rgba(255,140,74,0.25)); transform: scale(1); }
    50%      { filter: drop-shadow(0 0 12px rgba(255,87,100,0.85)) drop-shadow(0 0 22px rgba(255,140,74,0.5)); transform: scale(1.08); }
  }
  @keyframes flicker {
    0% { transform: scale(1) rotate(-2deg); filter: hue-rotate(0deg); }
    100% { transform: scale(1.06) rotate(2deg); filter: hue-rotate(8deg); }
  }
  .streak-card .info h4 { font-family: var(--px); font-size: 11px; color: var(--gold); }
  .streak-card .info p { font-family: var(--term); font-size: 15px; color: var(--ink-dim); margin-top: 4px; }

  /* ---------- Stats grid ---------- */
  .stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 12px 0 18px; }
  .stat-cell {
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5), 3px 3px 0 #000;
    padding: 10px 8px; text-align: center;
  }
  .stat-cell .v { font-family: var(--px); font-size: 14px; color: var(--neon-3); }
  .stat-cell .l { font-family: var(--px); font-size: 7px; color: var(--ink-faint); margin-top: 6px; letter-spacing: 1px; }

  /* ---------- Tutorial card (first-run home screen) ---------- */
  /* Prominent first-time player offer to take the 3-step tutorial.
     Surfaces only when profile.runs === 0 AND !profile.tutorialDone,
     so existing players never see it. Sits above the mode grid so
     it's the first thing a new player reads on the home screen. */
  .tutorial-card {
    background: linear-gradient(135deg, rgba(245,194,66,0.18), rgba(0,230,195,0.18));
    border: 3px solid var(--gold);
    box-shadow: 4px 4px 0 #000, 0 0 20px rgba(245,194,66,0.35);
    padding: 16px;
    margin-bottom: 18px;
    text-align: center;
    animation: tutCardPulse 2s ease-in-out infinite;
  }
  @keyframes tutCardPulse {
    0%, 100% { box-shadow: 4px 4px 0 #000, 0 0 18px rgba(245,194,66,0.30); }
    50%      { box-shadow: 4px 4px 0 #000, 0 0 32px rgba(245,194,66,0.55); }
  }
  .tutorial-tag {
    font-family: var(--px); font-size: 8px;
    color: var(--neon-3);
    letter-spacing: 2px;
    margin-bottom: 6px;
  }
  .tutorial-title {
    font-family: var(--px); font-size: 16px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000, 0 0 10px var(--gold);
    letter-spacing: 3px;
    margin-bottom: 10px;
  }
  .tutorial-body {
    font-family: var(--term); font-size: 14px;
    color: var(--ink);
    line-height: 1.45;
    margin-bottom: 14px;
  }
  .tutorial-actions {
    display: flex; flex-direction: column; gap: 8px; align-items: center;
  }
  .btn.tutorial-start {
    width: 100%;
    max-width: 320px;
    font-size: 12px;
    letter-spacing: 2px;
    padding: 12px 18px;
  }
  .tutorial-skip {
    background: none;
    border: none;
    color: var(--ink-faint);
    font-family: var(--term);
    font-size: 12px;
    font-style: italic;
    text-decoration: underline;
    cursor: pointer;
    padding: 2px;
  }
  .tutorial-skip:hover { color: var(--ink-dim); }

  /* ---------- Welcome bubble ---------- */
  .welcome-bubble {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 12px 14px; margin-bottom: 16px;
    background: #0d061a; border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon), 3px 3px 0 #000;
  }
  .welcome-bubble .av {
    width: 38px; height: 38px; flex-shrink: 0;
    background: var(--neon); border: 2px solid #000;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4);
  }
  .welcome-bubble .welcome-content {
    flex: 1; min-width: 0;
    overflow: hidden;
  }
  .welcome-bubble .welcome-tag {
    font-family: var(--px); font-size: 8px;
    color: var(--neon); letter-spacing: 2px;
    margin-bottom: 4px;
    text-shadow: 1px 1px 0 #000;
  }
  .welcome-bubble .text {
    font-family: var(--term); font-size: 17px; color: var(--ink);
    line-height: 1.3;
    will-change: transform, opacity;
  }
  .welcome-bubble .text.slide-out {
    animation: welcomeSlideOut 0.32s cubic-bezier(.4,0,.6,1) forwards;
  }
  .welcome-bubble .text.slide-in {
    animation: welcomeSlideIn 0.36s cubic-bezier(.2,.8,.2,1) forwards;
  }
  @keyframes welcomeSlideOut {
    0%   { transform: translateY(0); opacity: 1; filter: blur(0); }
    100% { transform: translateY(22px); opacity: 0; filter: blur(2px); }
  }
  @keyframes welcomeSlideIn {
    0%   { transform: translateY(-22px); opacity: 0; filter: blur(2px); }
    60%  { filter: blur(0); }
    100% { transform: translateY(0); opacity: 1; filter: blur(0); }
  }

  /* ---------- Timer ring (SVG) ----------
     Sticky-positioned so it stays visible while scrolling step list. */
  .timer-ring-wrap {
    display: flex; align-items: center; gap: 14px;
    padding: 12px 14px;
    background: #000; border: 3px solid var(--neon-3);
    box-shadow: 4px 4px 0 #000;
    margin-bottom: 16px;
    position: sticky;
    /* Bumped from 60 to 156 so it stacks under the sticky boss-card
       (which sits at top:60px and is ~88px tall including padding +
       border + offset shadow). z-index < boss-card so the boss HP
       always reads on top if there's any vertical overlap. */
    top: 156px;
    z-index: 8;
  }
  .timer-ring-wrap.warn { border-color: var(--danger); animation: pulse 0.5s steps(2) infinite; }
  /* Coop: I finished, timer is paused/done — switch to gold so it visually
     reads "stopped & locked in" instead of the cyan "running" state. */
  .timer-ring-wrap.done {
    border-color: var(--gold) !important;
    animation: none !important;
  }
  .timer-ring-wrap.done .clock { color: var(--gold); text-shadow: 0 0 8px var(--gold); }
  .timer-ring-wrap.done #timerRing { stroke: var(--gold) !important; }
  .timer-ring-wrap svg { display: block; }
  .timer-ring-wrap .clock {
    font-family: var(--px); font-size: 20px;
    color: var(--neon-3); text-shadow: 0 0 8px var(--neon-3);
    font-variant-numeric: tabular-nums;
  }
  .timer-ring-wrap.warn .clock { color: var(--danger); text-shadow: 0 0 8px var(--danger); }
  .timer-ring-wrap .lbl { font-family: var(--px); font-size: 8px; color: var(--ink-faint); letter-spacing: 1px; }
  /* Per-second clock-tick mute toggle — sits at the right edge of the
     timer-ring-wrap. Pixel-button styling matches the rest of the UI. */
  .timer-tick-btn {
    margin-left: auto;
    background: transparent;
    border: 0;
    color: var(--ink);
    width: 44px; height: 44px;
    font-size: 16px; line-height: 1;
    cursor: pointer;
    box-shadow: none;
    padding: 0;
    display: flex; align-items: center; justify-content: center;
    transition: transform .06s;
  }
  .timer-tick-btn:active { transform: translate(2px, 2px); }
  .timer-tick-btn .btn-ic { width: 36px; height: 36px; margin: 0; }

  /* ---------- HP color states ---------- */
  .hp-fill.mid {
    background: repeating-linear-gradient(90deg, #ff8c4a 0 8px, var(--gold) 8px 16px);
  }
  .hp-fill.low {
    background: repeating-linear-gradient(90deg, var(--neon-3) 0 8px, #1ee2bf 8px 16px);
  }
  .hp-fill.gone { background: var(--ink-faint); }

  /* ---------- Role reveal card ---------- */
  .role-flip-stage {
    perspective: 1000px;
    height: 280px; margin: 18px 0;
  }
  .role-flip {
    position: relative; width: 100%; height: 100%;
    transform-style: preserve-3d;
    transition: transform .5s steps(8);
    cursor: pointer;
  }
  .role-flip.flipped { transform: rotateY(180deg); }
  .role-face {
    position: absolute; inset: 0;
    backface-visibility: hidden;
    border: 4px solid #000;
    box-shadow: inset 0 0 0 3px var(--neon-2), 6px 6px 0 #000;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: 22px; text-align: center;
  }
  .role-face.back { transform: rotateY(180deg); }
  .role-face.front {
    background:
      repeating-linear-gradient(45deg, #14091f 0 12px, #1a0f2b 12px 24px);
  }
  .role-face.front .q {
    font-family: var(--px); font-size: 60px; color: var(--gold);
    text-shadow: 4px 4px 0 #000, 0 0 12px var(--gold);
    animation: bob 1.2s ease-in-out infinite;
  }
  .role-face.front .lbl {
    font-family: var(--px); font-size: 10px; color: var(--ink); margin-top: 14px; line-height: 1.6;
  }
  .role-face.back.loyal { background: linear-gradient(160deg, #00e6c3, #1e6bd8); }
  .role-face.back.traitor { background: linear-gradient(160deg, #ff3da6, #5b1320); }
  .role-face.back .ic { font-size: 70px; text-shadow: 4px 4px 0 #000; }
  .role-face.back .role-name {
    font-family: var(--px); font-size: 14px; color:var(--ink); margin-top: 12px;
    text-shadow: 3px 3px 0 #000;
  }
  .role-face.back .desc {
    font-family: var(--term); font-size: 16px; color:var(--ink); margin-top: 10px;
    text-shadow: 2px 2px 0 rgba(0,0,0,0.6);
  }

  /* Role list */
  .role-queue { display: flex; flex-direction: column; gap: 8px; margin: 14px 0; }
  .role-queue .row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px; background: var(--card); border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
  }
  .role-queue .row.done { box-shadow: 2px 2px 0 var(--neon-3); }
  .role-queue .nm { display: flex; align-items: center; gap: 10px; font-family: var(--px); font-size: 9px; }

  /* ---------- Vote progress bar ---------- */
  .vote-progress {
    height: 14px; background: #000; border: 2px solid #000;
    margin: 12px 0 16px; box-shadow: inset 1px 1px 0 rgba(255,255,255,0.05);
  }
  .vote-progress .fill {
    height: 100%; background: repeating-linear-gradient(90deg, var(--neon-3) 0 8px, #1ee2bf 8px 16px);
    transition: width .2s steps(6);
  }

  /* ---------- Past proof viewer (collapsed completed steps) ---------- */
  .past-proof {
    margin-top: 8px;
  }
  .past-proof-row {
    display: grid; gap: 6px;
  }
  .past-proof-row.cols-1 { grid-template-columns: 1fr; }
  .past-proof-row.cols-2 { grid-template-columns: 1fr 1fr; }
  .past-proof-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
  .past-proof-thumb {
    aspect-ratio: 1;
    border: 2px solid var(--neon-3);
    overflow: hidden;
    box-shadow: 2px 2px 0 #000;
  }
  .past-proof-thumb img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
  }

  /* ---------- Consequence wheel — redesigned loss screen ---------- */
  .wheel-screen {
    padding-top: 8px;
  }
  .wheel-fail-hero {
    text-align: center; margin-bottom: 14px;
    animation: fadeUp .35s ease both;
  }
  .wheel-fail-skull img {
    width: 64px; height: 64px;
    image-rendering: pixelated;
    filter: drop-shadow(0 0 12px rgba(255, 64, 80, 0.55));
    animation: failSkullShake .18s steps(2) 3, failSkullFloat 2.2s ease-in-out infinite;
  }
  @keyframes failSkullShake {
    0% { transform: translateX(-3px); } 50% { transform: translateX(3px); } 100% { transform: translateX(0); }
  }
  @keyframes failSkullFloat {
    0%,100% { transform: translateY(0); }
    50%     { transform: translateY(-4px); }
  }
  .wheel-fail-title {
    font-family: var(--px); font-size: 26px; letter-spacing: 4px;
    color: var(--danger);
    text-shadow: 0 0 10px rgba(255, 64, 80, 0.6);
    margin: 8px 0 4px;
  }
  .wheel-fail-sub {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim);
  }
  .wheel-promise-card {
    border-color: var(--danger);
    background: rgba(255, 87, 100, 0.10);
    margin: 0 0 18px;
  }
  .wheel-promise-card h3 {
    color: var(--danger);
    font-size: 11px; letter-spacing: 2px;
    margin-bottom: 6px;
  }
  .wheel-promise-card p {
    color: var(--ink); font-size: 15px; line-height: 1.4;
  }
  .wheel-promise-foot {
    margin-top: 8px;
    font-family: var(--px); font-size: 8px; letter-spacing: 1.5px;
    color: var(--ink-faint);
  }

  .wheel-stage { display: flex; flex-direction: column; align-items: center; padding: 6px 0; }
  .wheel-wrap {
    position: relative; width: 360px; height: 360px;
    max-width: 92vw; max-height: 92vw;
  }
  /* Outer rim with bulbs — static layer behind the spinning wheel */
  .wheel-rim {
    position: absolute; inset: 0;
    pointer-events: none;
    z-index: 1;
  }
  .wheel-bulb {
    filter: drop-shadow(0 0 4px currentColor);
    animation: bulbBlink 1.2s ease-in-out infinite;
  }
  .wheel-bulb-0 { animation-delay: 0s; }
  .wheel-bulb-1 { animation-delay: 0.3s; }
  .wheel-bulb-2 { animation-delay: 0.6s; }
  .wheel-bulb-3 { animation-delay: 0.9s; }
  .wheel-rim.spinning .wheel-bulb { animation-duration: 0.4s; }
  @keyframes bulbBlink {
    0%, 100% { opacity: 0.4; }
    50%      { opacity: 1; }
  }

  .wheel {
    position: relative;
    width: 100%; height: 100%;
    transform-origin: 50% 50%;
    transition: transform 4s cubic-bezier(.18,.85,.2,1);
    z-index: 2;
    filter: drop-shadow(4px 4px 0 #000);
  }
  .wheel-pointer {
    position: absolute; left: 50%; top: 2px;
    width: 0; height: 0;
    border-left: 18px solid transparent;
    border-right: 18px solid transparent;
    border-top: 32px solid var(--gold);
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.8));
    transform: translateX(-50%);
    z-index: 5;
  }
  .wheel-pointer::after {
    content: '';
    position: absolute;
    left: 50%; top: -32px;
    transform: translateX(-50%);
    border-left: 12px solid transparent;
    border-right: 12px solid transparent;
    border-top: 22px solid #2a1500;
  }
  .wheel-spin-btn {
    font-size: 14px;
    letter-spacing: 3px;
    padding: 14px 28px;
    box-shadow: 4px 4px 0 #000, 0 0 18px rgba(245, 194, 66, 0.4);
    animation: spinBtnPulse 1.6s ease-in-out infinite;
  }
  /* Static hub overlay — replaces the in-SVG SPIN text that used to
     rotate with the wheel. Sized so the label reads clearly at any
     wheel diameter and the tap target is finger-friendly (~76px). */
  .wheel-hub {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    width: 76px; height: 76px;
    border-radius: 50%;
    background: #0a0518;
    border: 3px solid var(--gold);
    box-shadow: 0 0 0 3px #000, 0 0 18px rgba(245, 194, 66, 0.55);
    color: var(--gold);
    font-family: var(--px);
    font-size: 13px;
    letter-spacing: 2px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 4;          /* above the rotating wheel (z:2) and rim (z:1) */
    padding: 0;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform .08s ease;
  }
  .wheel-hub:hover { transform: translate(-50%, -50%) scale(1.04); }
  .wheel-hub:active { transform: translate(-50%, -50%) scale(0.96); }
  .wheel-hub:disabled,
  .wheel-hub.spent { cursor: default; box-shadow: 0 0 0 3px #000; }
  @keyframes spinBtnPulse {
    0%, 100% { box-shadow: 4px 4px 0 #000, 0 0 18px rgba(245, 194, 66, 0.4); }
    50%      { box-shadow: 4px 4px 0 #000, 0 0 28px rgba(245, 194, 66, 0.75); }
  }

  /* Rarity legend below the wheel */
  .wheel-tier-legend {
    display: flex; gap: 6px; flex-wrap: wrap; justify-content: center;
    margin-top: 14px;
  }
  .wheel-tier-pill {
    font-family: var(--px); font-size: 8px; letter-spacing: 1px;
    padding: 3px 8px;
    border: 2px solid #000;
    color: #2a1500;
  }
  .wheel-tier-pill[data-tier="common"]    { background: #ff5cb0; }
  .wheel-tier-pill[data-tier="uncommon"]  { background: #f5c242; }
  .wheel-tier-pill[data-tier="rare"]      { background: #7b5cff; color:var(--ink); }
  .wheel-tier-pill[data-tier="legendary"] { background: #4adcff; }

  /* Result card after spin lands */
  .wheel-result {
    margin-top: 18px; padding: 14px 16px;
    background: #0a0518; border: 3px solid var(--neon);
    box-shadow: 4px 4px 0 #000;
    text-align: center;
    line-height: 1.5;
    max-width: 360px;
    animation: fadeUp .35s ease both;
    position: relative;
  }
  .wheel-result-tier {
    position: absolute; top: -14px; left: 50%;
    transform: translateX(-50%);
    font-family: var(--px); font-size: 9px; letter-spacing: 2px;
    color: #2a1500;
    padding: 4px 10px;
    border: 2px solid #000;
  }
  .wheel-result-ic { font-size: 40px; line-height: 1; margin: 6px 0; }
  .wheel-result-name {
    font-family: var(--px); font-size: 14px; letter-spacing: 2px;
    color: var(--gold);
  }
  .wheel-result-sub {
    color: var(--ink-dim); font-size: 11px;
  }
  .wheel-result-desc {
    font-family: var(--term); font-size: 15px;
    color: var(--ink);
    margin-top: 10px;
  }
  .wheel-result-quip {
    font-family: var(--term); font-size: 13px;
    color: var(--ink-dim);
    font-style: italic;
    margin-top: 8px;
  }

  /* ---------- Confetti ---------- */
  #confetti {
    position: fixed; inset: 0; pointer-events: none; z-index: 200;
  }

  /* ---------- Recap card ---------- */
  .recap-card {
    background: linear-gradient(160deg, #2a1247, #45125f);
    border: 4px solid #000;
    box-shadow: inset 0 0 0 3px var(--gold), 6px 6px 0 #000;
    padding: 22px 18px;
    margin: 8px 0 16px;
    text-align: center;
    position: relative; overflow: hidden;
  }
  .recap-card::before {
    content: ''; position: absolute; inset: 0;
    background: repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 2px, transparent 2px 5px);
    pointer-events: none;
  }
  .recap-card .badge {
    font-family: var(--px); font-size: 9px; color: var(--gold); letter-spacing: 2px;
    text-shadow: 2px 2px 0 #000;
  }
  .recap-card .boss-ic { font-size: 70px; text-shadow: 4px 4px 0 #000; margin: 10px 0; }
  .recap-card .boss-name {
    font-family: var(--px); font-size: 14px; color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 4px 4px 0 #000;
  }
  .recap-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 14px 0; }
  .recap-stats .cell {
    background: rgba(0,0,0,0.5); border: 2px solid #000; padding: 10px 8px;
  }
  .recap-stats .cell .v { font-family: var(--px); font-size: 13px; color:var(--ink); text-shadow: 2px 2px 0 #000; }
  .recap-stats .cell .l { font-family: var(--px); font-size: 7px; color: var(--neon-3); margin-top: 6px; letter-spacing: 1px; }
  .recap-quote {
    font-family: var(--term); font-size: 17px; color: var(--ink);
    background: rgba(0,0,0,0.6); border: 2px solid var(--neon-3);
    padding: 10px 12px; margin-top: 8px; line-height: 1.4;
  }
  .recap-brand {
    font-family: var(--px); font-size: 10px; margin-top: 14px;
    color: var(--neon); text-shadow: 1px 1px 0 #000;
    letter-spacing: 2px;
  }
  .recap-roast {
    margin-top: 10px; padding: 10px 12px;
    background: var(--card-2); border: 2px dashed var(--line);
    text-align: left;
    display: flex; flex-direction: column; gap: 4px;
  }
  .recap-roast .roast-tag {
    font-family: var(--px); font-size: 9px;
    letter-spacing: 2px; color: var(--ink-faint);
  }
  .recap-roast .roast-line {
    font-family: var(--term); font-size: 16px;
    color: var(--ink); line-height: 1.35;
  }
  .recap-roast.roast-speedrun { border-color: var(--gold); }
  .recap-roast.roast-speedrun .roast-tag { color: var(--gold); }
  .recap-roast.roast-fast     { border-color: var(--neon-3); }
  .recap-roast.roast-fast     .roast-tag { color: var(--neon-3); }
  .recap-roast.roast-slow     { border-color: var(--neon-2); }
  .recap-roast.roast-slow     .roast-tag { color: var(--neon-2); }
  .recap-roast.roast-buzzer   { border-color: var(--danger); }
  .recap-roast.roast-buzzer   .roast-tag { color: var(--danger); }

  /* ---------- Boss reveal — typewriter ---------- */
  /* JS-driven sequence flips opacity and types text per character.
     The CSS just provides a smooth fade and a blinking caret. */
  .boss-fade {
    opacity: 0;
    transition: opacity 0.25s ease;
  }
  .typing-active::after {
    content: '▌';
    color: var(--neon);
    animation: blink 0.5s steps(2) infinite;
    margin-left: 2px;
  }
  .skip-hint {
    position: fixed;
    bottom: 22px; left: 50%;
    transform: translateX(-50%);
    z-index: 11;
    pointer-events: none;
    font-family: var(--px); font-size: 9px;
    color: var(--neon-3);
    text-shadow: 1px 1px 0 #000;
    letter-spacing: 1.5px;
    background: rgba(0,0,0,0.85);
    padding: 8px 14px;
    border: 2px solid var(--neon-3);
    box-shadow: 3px 3px 0 #000;
    animation: blink 1.4s steps(2) infinite;
    transition: opacity .25s;
  }
  .skip-hint.gone { opacity: 0; }

  /* ---------- Twist Card popup (mid-quest surprise) ---------- */
  .twist-card-bg {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.85);
    z-index: 110;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    animation: twistBgFade 0.25s ease;
  }
  @keyframes twistBgFade {
    from { background: rgba(0, 0, 0, 0); }
    to   { background: rgba(0, 0, 0, 0.85); }
  }
  .twist-card {
    background: linear-gradient(160deg, #ff3da6 0%, #7b5cff 60%, #00e6c3 100%);
    border: 5px solid #000;
    box-shadow: inset 0 0 0 3px var(--gold), 8px 8px 0 #000, 0 0 40px rgba(255,61,166,0.6);
    padding: 26px 22px;
    max-width: 360px; width: 100%;
    text-align: center;
    animation: twistEntry 0.7s cubic-bezier(.18,.85,.2,1);
    position: relative;
  }
  @keyframes twistEntry {
    0%   { transform: scale(0.2) rotate(-180deg); opacity: 0; }
    60%  { transform: scale(1.12) rotate(20deg); opacity: 1; }
    80%  { transform: scale(0.94) rotate(-10deg); opacity: 1; }
    100% { transform: scale(1) rotate(0deg); opacity: 1; }
  }
  .twist-card .label {
    font-family: var(--px); font-size: 9px; color: var(--gold);
    letter-spacing: 2px; text-shadow: 2px 2px 0 #000;
    margin-bottom: 12px;
    animation: blink 0.55s steps(2) infinite;
  }
  .twist-card .ic {
    font-size: 72px; line-height: 1;
    text-shadow: 4px 4px 0 #000;
    margin-bottom: 12px;
    animation: twistIconBob 1.2s ease-in-out infinite;
  }
  @keyframes twistIconBob {
    0%, 100% { transform: translateY(0) rotate(-3deg); }
    50%      { transform: translateY(-6px) rotate(3deg); }
  }
  .twist-card h3 {
    font-family: var(--px); font-size: 15px; color:var(--ink);
    text-shadow: 3px 3px 0 #000;
    margin-bottom: 14px;
    letter-spacing: 1.5px;
  }
  .twist-card p {
    font-family: var(--term); font-size: 17px; color:var(--ink);
    text-shadow: 2px 2px 0 rgba(0,0,0,0.7);
    line-height: 1.4;
    margin-bottom: 22px;
  }
  .twist-card .accept {
    background: var(--gold); color: #2a1500;
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 4px 4px 0 #000;
    font-family: var(--px); font-size: 11px;
    padding: 12px 24px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    transition: transform .06s;
  }
  .twist-card .accept:active { transform: translate(2px, 2px); }
  .twist-card .twist-actions {
    display: flex; flex-direction: column; gap: 10px;
    align-items: stretch;
  }
  .twist-card .twist-pass {
    background: var(--neon-2);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
    font-size: 10px;
    padding: 10px 18px;
  }
  .twist-card .twist-pass:hover { background: #9c7eff; }
  .twist-pass-line {
    font-family: var(--term); font-size: 16px;
    color:var(--ink);
    background: rgba(0,0,0,0.55);
    border: 2px solid var(--neon-2);
    padding: 10px 14px;
    margin-bottom: 14px;
    font-weight: 700;
    text-shadow: 2px 2px 0 #000, 0 0 6px rgba(123,92,255,0.7);
    line-height: 1.4;
  }
  .twist-pass-note {
    font-family: var(--px); font-size: 9px;
    color: var(--gold); letter-spacing: 1px;
    margin-bottom: 10px;
    text-shadow: 1px 1px 0 #000;
  }
  /* Footer summary on a received-pass twist — names the sender and the
     specific twist that landed on you, so it reads as "X has been
     passed on to you by Y" right under the rule text. */
  .twist-pass-summary {
    font-family: var(--term); font-size: 14px;
    color: var(--ink);
    background: rgba(0,0,0,0.30);
    border: 2px dashed var(--gold);
    padding: 8px 12px;
    margin-top: 6px;
    margin-bottom: 12px;
    text-shadow: 1px 1px 0 #000;
    line-height: 1.4;
  }
  .twist-pass-summary strong { color: var(--gold); }
  .twist-passed-confirm {
    font-family: var(--term); font-size: 15px;
    color: var(--gold);
    background: rgba(255,206,79,0.10);
    border: 2px solid var(--gold);
    padding: 10px 12px;
    margin: 10px 0 14px;
    text-shadow: 1px 1px 0 #000;
  }
  /* Active twist banner — sticky reminder during the rest of the quest */
  .active-twist-banner {
    background: linear-gradient(90deg, var(--neon), var(--neon-2));
    color:var(--ink); text-shadow: 1px 1px 0 #000;
    border: 3px solid #000;
    box-shadow: 4px 4px 0 #000;
    padding: 10px 14px;
    margin-bottom: 14px;
    font-family: var(--term); font-size: 15px;
    line-height: 1.3;
  }
  .active-twist-banner .label {
    font-family: var(--px); font-size: 9px; color: var(--gold);
    letter-spacing: 1.5px; margin-bottom: 4px;
    display: block;
  }

  /* ---------- Fact popup (persists until tapped) ---------- */
  .fact-popup {
    position: fixed;
    bottom: 96px;
    left: 50%;
    transform: translateX(-50%);
    max-width: 420px;
    width: calc(100% - 36px);
    z-index: 60;
    background: linear-gradient(160deg, #1a1535, #0f0820);
    border: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 4px 4px 0 #000;
    padding: 14px 16px;
    cursor: pointer;
    animation: slideUpFact .25s ease;
  }
  @keyframes slideUpFact {
    from { transform: translate(-50%, 20px); opacity: 0; }
    to   { transform: translate(-50%, 0);    opacity: 1; }
  }
  .fact-popup .label {
    font-family: var(--px); font-size: 9px; color: var(--neon-3);
    letter-spacing: 1.5px; margin-bottom: 8px;
  }
  .fact-popup .text {
    font-family: var(--term); font-size: 16px; color: var(--ink);
    line-height: 1.4;
  }
  .fact-popup .tap-hint {
    font-family: var(--px); font-size: 7px; color: var(--ink-faint);
    letter-spacing: 1px; margin-top: 8px; text-align: right;
    animation: blink 1.4s steps(2) infinite;
  }
  /* Unhinged variant — pink accents, gremlin-themed */
  .fact-popup.unhinged {
    background: linear-gradient(160deg, #2a0848, #1a0530);
    box-shadow: inset 0 0 0 2px var(--neon), 4px 4px 0 #000, 0 0 18px rgba(255,61,166,0.35);
    animation: slideUpFact .25s ease, unhingedFactPulse 3s steps(8) infinite;
  }
  @keyframes unhingedFactPulse {
    0%, 100% { box-shadow: inset 0 0 0 2px var(--neon), 4px 4px 0 #000, 0 0 18px rgba(255,61,166,0.3); }
    50%      { box-shadow: inset 0 0 0 2px var(--neon-2), 4px 4px 0 #000, 0 0 22px rgba(123,92,255,0.45); }
  }
  .fact-popup.unhinged .label {
    color: var(--neon);
    text-shadow: 1px 1px 0 var(--neon-2), 2px 2px 0 #000;
  }
  .fact-popup.unhinged .text {
    color: var(--ink);
    font-style: italic;
  }
  .fact-popup.unhinged .tap-hint {
    color: var(--neon-2);
    text-transform: lowercase;
  }

  /* ---------- Help popup (persists until tapped) ---------- */
  .help-box {
    position: fixed; inset: 0;
    z-index: 95;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, 0.78);
    padding: 18px;
    cursor: pointer;
    animation: fadeUp .15s ease;
  }
  .help-box-inner {
    background: var(--bg-1);
    border: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 6px 6px 0 #000;
    padding: 22px;
    max-width: 420px;
    width: 100%;
    cursor: default;
    pointer-events: none; /* let the wrap handle the tap */
  }
  .help-box-label {
    font-family: var(--px); font-size: 11px; color: var(--neon-3);
    letter-spacing: 1.5px; margin-bottom: 14px;
  }
  .help-box-text {
    font-family: var(--term); font-size: 19px; color: var(--ink);
    line-height: 1.4; margin-bottom: 14px;
  }
  .help-box-quip {
    font-family: var(--term); font-size: 16px; color: var(--ink-dim);
    line-height: 1.4; margin-bottom: 16px;
    font-style: italic;
  }
  .help-box-tap {
    font-family: var(--px); font-size: 8px; color: var(--ink-faint);
    letter-spacing: 1.5px; text-align: center;
    animation: blink 1.4s steps(2) infinite;
  }
  /* Unhinged variant */
  .help-box.unhinged .help-box-inner {
    box-shadow: inset 0 0 0 2px var(--neon), 6px 6px 0 #000, 0 0 24px rgba(255,61,166,0.3);
  }
  .help-box.unhinged .help-box-label {
    color: var(--neon);
    text-shadow: 1px 1px 0 var(--neon-2), 2px 2px 0 #000;
    text-transform: lowercase;
  }
  .help-box.unhinged .help-box-text {
    text-transform: lowercase;
    font-style: italic;
  }
  .help-box.unhinged .help-box-quip {
    color: var(--neon);
    font-style: italic;
  }
  .help-box.unhinged .help-box-tap {
    color: var(--neon-2);
    text-transform: lowercase;
  }

  /* ---------- Photo gallery (recap) ---------- */
  .photo-gallery {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 14px;
  }
  .photo-gallery .gphoto {
    position: relative;
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 3px 3px 0 #000;
    overflow: hidden;
    aspect-ratio: 1;
    background: var(--bg-1);
    cursor: pointer;
    transition: transform .06s;
  }
  .photo-gallery .gphoto:active { transform: translate(2px, 2px); }
  .photo-gallery .gphoto.failed {
    box-shadow: inset 0 0 0 2px var(--danger), 3px 3px 0 #000;
    filter: saturate(0.6);
  }
  .photo-gallery .gphoto img {
    width: 100%; height: 100%; object-fit: cover;
    image-rendering: auto;
    filter: contrast(1.05) saturate(1.1);
  }
  .photo-gallery .gphoto .tag {
    position: absolute; left: 4px; top: 4px;
    background: #000; color: var(--gold);
    font-family: var(--px); font-size: 8px;
    padding: 3px 6px;
    border: 2px solid var(--gold);
    letter-spacing: 1px;
  }
  .photo-gallery .gphoto .verdict {
    position: absolute; right: 4px; bottom: 4px;
    font-family: var(--px); font-size: 9px;
    padding: 3px 6px;
    border: 2px solid #000;
    color:var(--ink); text-shadow: 1px 1px 0 #000;
  }
  .photo-gallery .gphoto .verdict.pass { background: var(--neon-3); color: #000; text-shadow: none; }
  .photo-gallery .gphoto .verdict.fail { background: var(--danger); }

  /* Photo modal viewer */
  .photo-modal-bg {
    position: fixed; inset: 0; background: rgba(0,0,0,0.92);
    z-index: 110; display: flex; align-items: center; justify-content: center;
    padding: 18px;
  }
  .photo-modal-bg img {
    max-width: 100%; max-height: 80vh;
    border: 4px solid #000;
    box-shadow: 6px 6px 0 var(--gold);
    image-rendering: auto;
  }
  .photo-modal-bg .close {
    position: absolute; top: 18px; right: 18px;
    background: var(--neon); border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    color:var(--ink); text-shadow: 1px 1px 0 #000;
    font-family: var(--px); font-size: 14px;
    width: 40px; height: 40px;
    cursor: pointer;
    z-index: 5;
  }
  .photo-modal-bg .nav {
    position: absolute;
    top: 50%; transform: translateY(-50%);
    background: var(--neon-2); border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    color:var(--ink); text-shadow: 2px 2px 0 #000;
    font-size: 28px;
    width: 52px; height: 52px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    line-height: 1;
    z-index: 5;
    padding: 0;
  }
  .photo-modal-bg .nav.prev { left: 14px; }
  .photo-modal-bg .nav.next { right: 14px; }
  .photo-modal-bg .nav:disabled { opacity: 0.3; cursor: not-allowed; }
  .photo-modal-bg .counter {
    font-family: var(--px); font-size: 11px; color: var(--gold);
    letter-spacing: 2px;
    text-shadow: 2px 2px 0 #000;
  }
  .photo-modal-bg .swipe-hint {
    font-family: var(--px); font-size: 8px; color: var(--ink-faint);
    margin-top: 6px; letter-spacing: 1.5px;
    animation: blink 1.4s steps(2) infinite;
  }
  .photo-modal-bg .modal-inner {
    text-align: center; max-width: 100%;
    animation: pop .25s steps(4) both;
  }

  /* ---------- Share / Export modal ---------- */
  .share-modal-bg {
    position: fixed; inset: 0; background: rgba(0,0,0,0.94);
    z-index: 130; display: flex; align-items: center; justify-content: center;
    padding: 16px; overflow-y: auto;
  }
  .share-modal {
    width: 100%; max-width: 420px;
    background: var(--bg-1);
    border: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-2), 6px 6px 0 #000;
    padding: 18px;
    text-align: center;
    animation: pop .25s steps(4) both;
    margin: auto;
  }
  .share-modal h3 {
    font-family: var(--px); font-size: 12px;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 #000;
    letter-spacing: 1.5px;
    margin-bottom: 12px;
  }
  .share-modal .preview-wrap {
    width: 100%;
    aspect-ratio: 9 / 16;
    background: #000;
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 3px 3px 0 #000;
    overflow: hidden;
    margin-bottom: 14px;
    position: relative;
  }
  .share-modal .preview-wrap img,
  .share-modal .preview-wrap canvas {
    width: 100%; height: 100%;
    display: block;
    image-rendering: auto;
  }
  .share-modal .preview-loading {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--neon-3);
    font-family: var(--px); font-size: 10px;
    letter-spacing: 2px;
    animation: blink 1s steps(2) infinite;
  }
  .share-modal .opts {
    display: flex; flex-direction: column; gap: 8px;
    margin-bottom: 14px;
    text-align: left;
  }
  .share-modal .opts label {
    display: flex; align-items: center; gap: 10px;
    font-family: var(--px); font-size: 9px;
    color: var(--ink-dim);
    cursor: pointer;
    padding: 6px 8px;
    background: rgba(255,255,255,0.03);
    border: 2px solid rgba(255,255,255,0.06);
  }
  .share-modal .opts label.on {
    color: var(--ink);
    border-color: var(--neon-3);
    background: rgba(0,230,195,0.08);
  }
  .share-modal .opts input[type=checkbox] {
    appearance: none;
    width: 16px; height: 16px;
    background: var(--bg-0);
    border: 2px solid var(--ink-faint);
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
  }
  .share-modal .opts input[type=checkbox]:checked {
    background: var(--neon-3);
    border-color: var(--neon-3);
  }
  .share-modal .opts input[type=checkbox]:checked::after {
    content: '✓';
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: #000; font-size: 11px; font-weight: bold;
  }
  .share-modal .actions {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  }
  .share-modal .actions .full { grid-column: 1 / -1; }
  .share-modal .close-x {
    position: absolute; top: 12px; right: 12px;
    background: var(--neon); border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    color:var(--ink); text-shadow: 1px 1px 0 #000;
    font-family: var(--px); font-size: 12px;
    width: 36px; height: 36px;
    cursor: pointer;
    z-index: 5;
  }

  /* ---------- AR Finisher modal ---------- */
  /* Fullscreen camera + gyro-anchored boss + HP/timer HUD + tap-to-
     attack. Lives above the self-timer camera modal in the z stack
     because both can technically exist (player Cancels AR mid-fight
     and immediately taps Capture on the photo path). */
  .ar-finisher-modal {
    position: fixed; inset: 0;
    z-index: 140;
    background: #000;
    overflow: hidden;
    animation: fadeUp .15s ease;
  }
  .ar-video {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
  }
  /* Soft scrim so the HUD text reads against any background the
     player's camera happens to be pointed at. */
  .ar-scrim {
    position: absolute; inset: 0;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.55) 0%, transparent 22%, transparent 78%, rgba(0,0,0,0.65) 100%);
    pointer-events: none;
  }
  .ar-overlay {
    position: absolute; inset: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: space-between;
    padding: 28px 18px 24px;
    pointer-events: none;
  }
  .ar-overlay > * { pointer-events: auto; }
  .ar-hud {
    width: 100%; max-width: 420px;
    text-align: center;
  }
  .ar-boss-name {
    font-family: var(--px); font-size: 13px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000, 0 0 8px rgba(255,206,79,0.5);
    letter-spacing: 2px;
    margin-bottom: 10px;
  }
  .ar-hpbar {
    height: 16px;
    background: #0a0518;
    border: 3px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.08);
    overflow: hidden;
  }
  .ar-hpfill {
    height: 100%; width: 100%;
    background: linear-gradient(90deg, var(--danger) 0%, var(--neon) 55%, var(--gold) 100%);
    transition: width .18s ease;
  }
  .ar-hpnum {
    font-family: var(--px); font-size: 9px;
    color:var(--ink);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 1px;
    margin-top: 6px;
  }
  .ar-timer {
    font-family: var(--px); font-size: 28px;
    color:var(--ink);
    text-shadow: 3px 3px 0 #000, 0 0 14px var(--neon-3);
    letter-spacing: 3px;
  }
  .ar-boss-stage {
    flex: 1;
    display: flex; align-items: center; justify-content: center;
    width: 100%;
    /* So translate3d on the sprite has parent context to use for compositing. */
    perspective: 600px;
  }
  /* Gyro anchor — carries the inline `transform: translate(...)` written
     by the orientation handler. The sprite inside owns the bob /
     phase-shake / hit-flash / death animations, which also touch
     transform; without this two-layer split, the phase animations
     overwrite the gyro position and the boss appears stuck on screen. */
  .ar-boss-anchor {
    display: inline-block;
    will-change: transform;
  }
  .ar-boss-sprite {
    width: 200px; height: 200px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    cursor: pointer;
    filter: drop-shadow(0 6px 18px rgba(0,0,0,0.75));
    /* The bob animation lives on the inner element; the outer transform
       carries the gyro position. We compose them via two layers later
       if we want the bob to be perfectly orthogonal — for the MVP the
       bob can ride along with the gyro translate without issues. */
    animation: arBossBob 2.6s ease-in-out infinite;
    user-select: none;
    -webkit-user-drag: none;
  }
  .ar-boss-emoji {
    font-size: 140px;
    line-height: 1;
    text-shadow: 4px 4px 0 #000, 0 0 12px rgba(255,255,255,0.2);
    display: flex; align-items: center; justify-content: center;
    width: 160px; height: 160px;
  }
  @keyframes arBossBob {
    0%, 100% { translate: 0 0; }
    50%      { translate: 0 -10px; }
  }
  /* Hit flash — restarts each tap via class-remove + reflow + class-add. */
  .ar-boss-sprite.ar-hit {
    animation: arBossBob 2.6s ease-in-out infinite, arHitFlash .18s ease;
  }
  @keyframes arHitFlash {
    0%   { filter: drop-shadow(0 6px 18px rgba(0,0,0,0.75)); }
    50%  { filter: brightness(2.3) drop-shadow(0 0 20px #fff); }
    100% { filter: drop-shadow(0 6px 18px rgba(0,0,0,0.75)); }
  }
  .ar-tap-hint {
    font-family: var(--px); font-size: 9px;
    color:var(--ink);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 2px;
    text-align: center;
  }
  .ar-cancel {
    position: absolute; top: 18px; right: 18px;
    width: 44px; height: 44px;
    background: rgba(0,0,0,0.65);
    color:var(--ink);
    border: 2px solid #fff;
    border-radius: 0;
    font-size: 22px;
    cursor: pointer;
    z-index: 2;
  }
  /* Damage popup — anchored at the tap coords, floats up + fades out. */
  .ar-dmg-pop {
    position: fixed;
    transform: translate(-50%, -50%);
    font-family: var(--px); font-size: 18px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 1px;
    pointer-events: none;
    z-index: 200;
    animation: arDmgFloat .8s ease-out forwards;
  }
  .ar-dmg-pop.crit {
    color: var(--neon);
    font-size: 26px;
  }
  /* Slam damage popup — visually distinct from taps and crits. Huge
     font, gold/red glow, dramatic life cycle so the player can read
     the number through the screen-shake without it competing. */
  .ar-dmg-pop.slam {
    color: #ffce4f;
    font-size: 42px;
    text-shadow: 3px 3px 0 #000, 0 0 16px #ff5764, 0 0 32px #ffce4f;
    animation: arSlamDmgFloat 1.1s ease-out forwards;
  }
  @keyframes arDmgFloat {
    0%   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -160%) scale(1.4); }
  }
  @keyframes arSlamDmgFloat {
    0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.4); filter: hue-rotate(0deg); }
    20%  { opacity: 1; transform: translate(-50%, -70%) scale(1.6); filter: hue-rotate(-30deg) brightness(1.5); }
    100% { opacity: 0; transform: translate(-50%, -200%) scale(1.2); filter: hue-rotate(40deg); }
  }
  /* Shockwave ring — expanding circle from the slam impact point. */
  .ar-slam-shockwave {
    position: fixed;
    width: 60px; height: 60px;
    transform: translate(-50%, -50%);
    border: 4px solid var(--gold);
    border-radius: 50%;
    pointer-events: none;
    z-index: 6;
    box-shadow: 0 0 24px var(--gold), inset 0 0 16px var(--gold);
    animation: arSlamShockwave .55s ease-out forwards;
  }
  @keyframes arSlamShockwave {
    0%   { width: 60px;  height: 60px;  border-width: 4px; opacity: 1;    filter: brightness(2); }
    60%  {                                                  opacity: 0.85; }
    100% { width: 520px; height: 520px; border-width: 1px; opacity: 0;    filter: brightness(0.7); }
  }
  .ar-result {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--px); font-size: 30px;
    text-shadow: 4px 4px 0 #000, 0 0 16px currentColor;
    letter-spacing: 3px;
    animation: arResultPop .5s ease;
    text-align: center;
    line-height: 1.2;
    z-index: 3;
  }
  .ar-victory { color: var(--gold); }
  .ar-defeat  {
    color: var(--danger);
    /* Defeat banner = a proper opaque card now, so the text doesn't
       fight the live camera feed + boss sprite behind it. The full-
       screen darkening overlay comes from .ar-finisher-modal.ar-defeated
       below — together they pull all focus to the result. */
    background: rgba(10, 5, 24, 0.94);
    border: 4px solid var(--danger);
    box-shadow: 8px 8px 0 #000, 0 0 40px var(--danger), inset 0 0 24px rgba(255, 30, 60, 0.25);
    padding: 28px 36px 24px;
    width: min(86vw, 360px);
    text-align: center;
    z-index: 12;
    font-size: 14px;    /* the icon + title carry the visual weight */
  }
  .ar-defeat-icon {
    font-size: 56px;
    line-height: 1;
    margin-bottom: 6px;
    text-shadow: 3px 3px 0 #000, 0 0 24px var(--danger);
    filter: drop-shadow(0 0 12px var(--danger));
  }
  .ar-defeat-title {
    font-family: var(--px);
    font-size: 28px;
    letter-spacing: 4px;
    color:var(--ink);
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--danger);
    margin-bottom: 10px;
  }
  .ar-defeat .ar-result-sub {
    color: var(--ink-dim);
    font-family: var(--term);
    font-style: italic;
    font-size: 14px;
    letter-spacing: 0;
  }
  /* Full-screen darkening overlay when the player loses. Sits below
     the result banner (.ar-result has z-index: 12) but above the
     boss / scrim / heartbeat layers. The animation fades in over
     150ms so the cut isn't jarring. */
  .ar-finisher-modal.ar-defeated::after {
    content: '';
    position: absolute; inset: 0;
    background: rgba(0, 0, 0, 0.78);
    z-index: 10;
    pointer-events: none;
    animation: arDefeatedScrim .18s ease-out both;
  }
  @keyframes arDefeatedScrim {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
  @keyframes arResultPop {
    0%   { transform: translate(-50%, -50%) scale(0); }
    60%  { transform: translate(-50%, -50%) scale(1.2); }
    100% { transform: translate(-50%, -50%) scale(1); }
  }

  /* ── Player HP bar — sits inside .ar-hud under the boss bar. Teal so
     it doesn't read as the boss's HP. Bumps on each hit. ── */
  .ar-player-hp {
    margin-top: 14px;
    text-align: center;
  }
  .ar-player-hp-label {
    font-family: var(--px); font-size: 9px;
    color: var(--neon-3);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 2px;
    margin-bottom: 4px;
  }
  .ar-hpbar.small { height: 12px; }
  .ar-player-hpfill {
    height: 100%; width: 100%;
    background: linear-gradient(90deg, #2a8c8c 0%, var(--neon-3) 50%, #4adcff 100%);
    transition: width .18s ease;
  }
  .ar-player-hp.ar-player-hit {
    animation: arPlayerHit .35s ease;
  }
  @keyframes arPlayerHit {
    0%   { transform: translateX(0); filter: none; }
    20%  { transform: translateX(-6px); filter: brightness(1.6) hue-rotate(-20deg); }
    40%  { transform: translateX(5px); }
    60%  { transform: translateX(-3px); }
    100% { transform: translateX(0); }
  }
  .ar-player-dmg-pop {
    position: fixed;
    transform: translate(-50%, -50%);
    font-family: var(--px); font-size: 20px;
    color: var(--danger);
    text-shadow: 2px 2px 0 #000, 0 0 14px var(--danger);
    letter-spacing: 1px;
    pointer-events: none;
    z-index: 200;
    animation: arPlayerDmgFloat 1s ease-out forwards;
  }
  @keyframes arPlayerDmgFloat {
    0%   { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(2.2); }
  }

  /* ── Boss wind-up telegraph: red vignette around screen edges +
     sprite glow. The wind-up class is set on the modal during the
     ~1.5s wind-up window. ── */
  .ar-windup-vignette {
    position: absolute; inset: 0;
    pointer-events: none;
    z-index: 3;
    box-shadow: inset 0 0 0 0 rgba(255,40,80,0);
    transition: box-shadow .15s ease;
  }
  .ar-finisher-modal.ar-windup .ar-windup-vignette {
    box-shadow: inset 0 0 120px 40px rgba(255,30,80,0.65);
    animation: arWindupPulse .5s ease-in-out infinite;
  }
  @keyframes arWindupPulse {
    0%, 100% { box-shadow: inset 0 0 100px 30px rgba(255,30,80,0.55); }
    50%      { box-shadow: inset 0 0 140px 50px rgba(255,30,80,0.85); }
  }
  .ar-boss-sprite.ar-windup {
    filter: drop-shadow(0 0 24px rgba(255,30,80,0.95)) brightness(1.4) saturate(1.4) !important;
  }

  /* ── Dodge button — bottom-center, big finger target. Pulses while
     the dodge window is open. ── */
  .ar-dodge-btn {
    /* Position is JS-driven now (random per-spawn). The button gets
       `left`/`top` set inline before display; the pulse animation
       only scales, so no transform fight. */
    position: absolute;
    background: var(--neon-3);
    color: #002b27;
    border: 4px solid #000;
    box-shadow: 6px 6px 0 #000, 0 0 24px rgba(0,230,195,0.9);
    padding: 18px 28px;
    font-family: var(--px);
    font-size: 18px;
    letter-spacing: 3px;
    cursor: pointer;
    z-index: 8;
    display: flex; align-items: center; gap: 10px;
    text-shadow: 1px 1px 0 #fff;
    transform-origin: center center;
    animation: arDodgeBtnPulse .35s ease-in-out infinite,
               arDodgeBtnSpawn .22s ease-out;
  }
  .ar-dodge-icon { font-size: 26px; }
  @keyframes arDodgeBtnPulse {
    0%, 100% { transform: scale(1);    box-shadow: 6px 6px 0 #000, 0 0 18px rgba(0,230,195,0.7); }
    50%      { transform: scale(1.08); box-shadow: 6px 6px 0 #000, 0 0 32px rgba(0,230,195,1); }
  }
  /* Spawn animation — quick pop so the button reads as "appeared here
     just now" instead of being mistaken for a static UI element the
     player overlooked. */
  @keyframes arDodgeBtnSpawn {
    0%   { opacity: 0; transform: scale(0.4); }
    60%  { opacity: 1; transform: scale(1.18); }
    100% { opacity: 1; transform: scale(1); }
  }
  .ar-dodge-success {
    position: absolute;
    top: 40%; left: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--px); font-size: 22px;
    color: var(--neon-3);
    text-shadow: 3px 3px 0 #000, 0 0 16px var(--neon-3);
    letter-spacing: 3px;
    pointer-events: none;
    z-index: 7;
    animation: arDodgeSuccessFloat .8s ease both;
  }
  @keyframes arDodgeSuccessFloat {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
    25%  { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
    100% { opacity: 0; transform: translate(-50%, -90%) scale(1); }
  }

  /* ── Per-boss signature-move banners + states. ── */
  .ar-sig-banner {
    position: absolute;
    top: 30%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--px);
    font-size: 22px;
    letter-spacing: 3px;
    text-shadow: 3px 3px 0 #000, 0 0 14px currentColor;
    pointer-events: none;
    z-index: 7;
    animation: arSigBannerLife 1.1s ease both;
    text-align: center;
  }
  .ar-sig-teleport { color: var(--neon-3); }
  .ar-sig-harden   { color: var(--gold); }
  .ar-sig-multijab { color: var(--neon); }
  @keyframes arSigBannerLife {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
    20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
    70%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -90%) scale(0.95); }
  }
  /* Hardened — gold shimmer overlay on the sprite during the 2s
     damage-soak window. Pairs with the ◇ HARDENED ◇ banner. */
  .ar-boss-sprite.ar-hardened {
    filter: drop-shadow(0 0 30px var(--gold)) drop-shadow(0 6px 26px rgba(245,194,66,0.9)) saturate(1.4) brightness(1.2) !important;
    animation: arBossBob 1.2s ease-in-out infinite, arHardenedShimmer 0.6s ease-in-out infinite;
  }
  @keyframes arHardenedShimmer {
    0%, 100% { filter: drop-shadow(0 0 30px var(--gold)) drop-shadow(0 6px 26px rgba(245,194,66,0.9)) saturate(1.4) brightness(1.2); }
    50%      { filter: drop-shadow(0 0 50px #fff) drop-shadow(0 6px 26px rgba(245,194,66,1)) saturate(1.6) brightness(1.5); }
  }
  /* Damage popup variant when the hit landed during harden — small,
     dim, with a deflected look so the player feels the soak. */
  .ar-dmg-pop.hardened {
    color: var(--gold);
    font-size: 14px;
    opacity: 0.85;
    text-shadow: 2px 2px 0 #000;
  }
  /* Stagger popup — inverse of harden. Big and gold-bright. */
  .ar-dmg-pop.stagger {
    color: #ffce4f;
    font-size: 38px;
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--gold), 0 0 28px #ff8c4a;
  }

  /* ── Ability effect banners + per-effect tints ── */
  .ar-ability-banner {
    position: absolute;
    top: 32%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--px);
    font-size: 18px;
    letter-spacing: 3px;
    text-shadow: 3px 3px 0 #000, 0 0 14px currentColor;
    pointer-events: none;
    z-index: 7;
    animation: arSigBannerLife 1s ease both;
    text-align: center;
  }
  .ar-ability-banner.ar-effect-damage   { color: var(--neon); }
  .ar-ability-banner.ar-effect-gamble   { color: var(--neon); }
  .ar-ability-banner.ar-effect-heal     { color: var(--neon-3); }
  .ar-ability-banner.ar-effect-time     { color: var(--gold); }
  .ar-ability-banner.ar-effect-shield   { color: var(--neon-3); }
  .ar-ability-banner.ar-effect-stagger  { color: var(--gold); }
  .ar-ability-banner.ar-effect-focus    { color: var(--gold); }

  /* Boss sprite while STAGGERED (player just applied a weakpoint
     buff). Inverse of .ar-hardened — bright cyan/teal glow, slight
     scale-down so it reads as exposed. */
  .ar-boss-sprite.ar-staggered {
    filter: drop-shadow(0 0 30px var(--neon-3)) drop-shadow(0 6px 26px rgba(0,230,195,0.9)) saturate(1.3) brightness(1.1) !important;
    animation: arBossBob 1.2s ease-in-out infinite, arStaggeredShimmer 0.6s ease-in-out infinite;
  }
  @keyframes arStaggeredShimmer {
    0%, 100% { filter: drop-shadow(0 0 30px var(--neon-3)) drop-shadow(0 6px 26px rgba(0,230,195,0.9)) saturate(1.3) brightness(1.1); }
    50%      { filter: drop-shadow(0 0 50px #fff) drop-shadow(0 6px 26px rgba(0,230,195,1)) saturate(1.6) brightness(1.5); }
  }

  /* Heal floater — green-teal '+24 HP' bounce up the screen. */
  .ar-heal-pop {
    position: fixed;
    transform: translate(-50%, -50%);
    font-family: var(--px); font-size: 28px;
    color: var(--neon-3);
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--neon-3);
    letter-spacing: 1px;
    pointer-events: none;
    z-index: 200;
    animation: arSlamDmgFloat 1.1s ease-out forwards;
  }

  /* Timer flash when a TIME ability adds seconds. */
  .ar-timer.ar-timer-bonus {
    animation: arTimerBonus .8s ease;
  }
  @keyframes arTimerBonus {
    0%   { transform: scale(1);    text-shadow: 3px 3px 0 #000, 0 0 14px var(--neon-3); color:var(--ink); }
    30%  { transform: scale(1.25); text-shadow: 3px 3px 0 #000, 0 0 32px var(--gold);   color: var(--gold); }
    100% { transform: scale(1);    text-shadow: 3px 3px 0 #000, 0 0 14px var(--neon-3); color:var(--ink); }
  }

  /* Status badges (shield charges, focus charges) — bottom of HUD,
     tiny chips that read at a glance. */
  .ar-status-badge {
    display: inline-block;
    margin-top: 6px;
    margin-right: 6px;
    padding: 4px 8px;
    background: rgba(10, 5, 24, 0.85);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    font-family: var(--px);
    font-size: 10px;
    letter-spacing: 1px;
  }
  .ar-shield-badge { color: var(--neon-3); border-color: var(--neon-3); box-shadow: 2px 2px 0 #000, 0 0 8px rgba(0,230,195,0.5); }
  .ar-focus-badge  { color: var(--gold);   border-color: var(--gold);   box-shadow: 2px 2px 0 #000, 0 0 8px rgba(245,194,66,0.5); }

  /* ── Combo chip — pulses up from the side when chain >= 2.
       Each tier-N class escalates the visual: tier-1 is muted, tier-8
       is the full GODLIKE rainbow. ── */
  .ar-combo-chip {
    position: absolute;
    top: 100px;
    right: 16px;
    background: rgba(10, 5, 24, 0.85);
    border: 3px solid var(--gold);
    box-shadow: 0 0 14px rgba(245,194,66,0.55), 3px 3px 0 #000;
    padding: 6px 10px;
    min-width: 90px;
    text-align: center;
    font-family: var(--px);
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
    z-index: 5;
  }
  .ar-combo-x {
    display: block;
    font-size: 22px;
    line-height: 1;
    letter-spacing: 1px;
  }
  .ar-combo-label {
    display: block;
    font-size: 7px;
    margin-top: 4px;
    letter-spacing: 1px;
    color: var(--neon-3);
  }
  .ar-combo-chip.arComboBump { animation: arComboBump .25s ease; }
  @keyframes arComboBump {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.25); filter: brightness(1.4); }
    100% { transform: scale(1); }
  }
  /* Tier escalation. Each tier swaps border color, glow color, text
     color so the chip is a glanceable read of how deep the chain is. */
  .ar-combo-chip.tier-2 { border-color: var(--gold);   box-shadow: 0 0 14px rgba(245,194,66,0.55), 3px 3px 0 #000; color: var(--gold); }
  .ar-combo-chip.tier-3 { border-color: var(--neon-3); box-shadow: 0 0 18px rgba(0,230,195,0.65),   3px 3px 0 #000; color: var(--neon-3); }
  .ar-combo-chip.tier-3 .ar-combo-x { font-size: 24px; }
  .ar-combo-chip.tier-4 { border-color: var(--neon);   box-shadow: 0 0 22px rgba(255,61,166,0.7),   3px 3px 0 #000; color: var(--neon); }
  .ar-combo-chip.tier-4 .ar-combo-x { font-size: 26px; }
  .ar-combo-chip.tier-5 { border-color: #ff5764;       box-shadow: 0 0 26px rgba(255,87,100,0.8),   3px 3px 0 #000; color: #ff8c4a; }
  .ar-combo-chip.tier-5 .ar-combo-x { font-size: 28px; }
  .ar-combo-chip.tier-5 { animation: arComboTier5Pulse 1.0s ease-in-out infinite; }
  @keyframes arComboTier5Pulse {
    0%, 100% { box-shadow: 0 0 22px rgba(255,87,100,0.7), 3px 3px 0 #000; }
    50%      { box-shadow: 0 0 36px rgba(255,87,100,1), 3px 3px 0 #000; }
  }
  .ar-combo-chip.tier-6 { border-color: #ffce4f;       background: rgba(80,30,5,0.85); color: var(--gold); }
  .ar-combo-chip.tier-6 .ar-combo-x { font-size: 32px; }
  .ar-combo-chip.tier-6 { animation: arComboTier6Pulse .7s ease-in-out infinite; }
  @keyframes arComboTier6Pulse {
    0%, 100% { box-shadow: 0 0 28px var(--gold), 3px 3px 0 #000; filter: hue-rotate(0deg); }
    50%      { box-shadow: 0 0 50px var(--gold), 3px 3px 0 #000; filter: hue-rotate(20deg); }
  }
  .ar-combo-chip.tier-7 {
    background: rgba(20, 0, 30, 0.9);
    border-color: var(--neon);
    color:var(--ink);
    text-shadow: 2px 2px 0 #000, 0 0 8px var(--neon);
  }
  .ar-combo-chip.tier-7 .ar-combo-x { font-size: 36px; }
  .ar-combo-chip.tier-7 { animation: arComboTier7Pulse .5s ease-in-out infinite; }
  @keyframes arComboTier7Pulse {
    0%, 50%, 100% { box-shadow: 0 0 30px var(--neon), 0 0 60px var(--neon), 3px 3px 0 #000; filter: hue-rotate(0deg) brightness(1); }
    25%           { box-shadow: 0 0 50px var(--neon-3), 0 0 80px var(--neon-3), 3px 3px 0 #000; filter: hue-rotate(60deg) brightness(1.3); }
    75%           { box-shadow: 0 0 50px var(--gold), 0 0 80px var(--gold), 3px 3px 0 #000; filter: hue-rotate(-60deg) brightness(1.3); }
  }
  /* GODLIKE — chip rainbows + the screen border glows. The dream tier. */
  .ar-combo-chip.tier-8 {
    background: rgba(0, 0, 0, 0.85);
    border-color: #fff;
    color:var(--ink);
    text-shadow: 2px 2px 0 #000, 0 0 12px #fff, 0 0 24px #ff3da6;
    animation: arComboGodlike .25s linear infinite;
  }
  .ar-combo-chip.tier-8 .ar-combo-x { font-size: 40px; }
  @keyframes arComboGodlike {
    0%   { box-shadow: 0 0 30px #ff3da6, 0 0 60px #ff3da6, 3px 3px 0 #000; filter: hue-rotate(0deg) brightness(1.4); }
    25%  { box-shadow: 0 0 30px #ffce4f, 0 0 60px #ffce4f, 3px 3px 0 #000; filter: hue-rotate(72deg) brightness(1.4); }
    50%  { box-shadow: 0 0 30px #00e6c3, 0 0 60px #00e6c3, 3px 3px 0 #000; filter: hue-rotate(144deg) brightness(1.4); }
    75%  { box-shadow: 0 0 30px #7b5cff, 0 0 60px #7b5cff, 3px 3px 0 #000; filter: hue-rotate(216deg) brightness(1.4); }
    100% { box-shadow: 0 0 30px #ff5764, 0 0 60px #ff5764, 3px 3px 0 #000; filter: hue-rotate(288deg) brightness(1.4); }
  }

  /* ── Tier-up banner — fires on each new tier crossing. ── */
  .ar-combo-tierup {
    position: absolute;
    top: 35%; left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    pointer-events: none;
    z-index: 9;
    animation: arComboTierUpLife 1.1s ease both;
    color: var(--gold);
    text-shadow: 3px 3px 0 #000, 0 0 14px currentColor;
  }
  .ar-combo-tierup-x {
    font-family: var(--px);
    font-size: 40px;
    letter-spacing: 2px;
    line-height: 1;
  }
  .ar-combo-tierup-name {
    font-family: var(--px);
    font-size: 14px;
    letter-spacing: 4px;
    margin-top: 6px;
  }
  .ar-combo-tierup.tier-3 { color: var(--neon-3); }
  .ar-combo-tierup.tier-4 { color: var(--neon); }
  .ar-combo-tierup.tier-5 { color: #ff8c4a; }
  .ar-combo-tierup.tier-5 .ar-combo-tierup-x { font-size: 46px; }
  .ar-combo-tierup.tier-6 { color: var(--gold); }
  .ar-combo-tierup.tier-6 .ar-combo-tierup-x { font-size: 52px; }
  .ar-combo-tierup.tier-7 { color:var(--ink); }
  .ar-combo-tierup.tier-7 .ar-combo-tierup-x { font-size: 60px; animation: arComboGodlike .35s linear infinite; }
  .ar-combo-tierup.tier-8 {
    color:var(--ink);
    animation: arComboTierUpLifeGod 1.6s ease both;
  }
  .ar-combo-tierup.tier-8 .ar-combo-tierup-x {
    font-size: 78px;
    animation: arComboGodlike .25s linear infinite;
  }
  @keyframes arComboTierUpLife {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
    20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.3); }
    70%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -90%) scale(0.95); }
  }
  @keyframes arComboTierUpLifeGod {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.3); }
    15%  { opacity: 1; transform: translate(-50%, -50%) scale(1.5); }
    25%  { transform: translate(-50%, -50%) scale(1.1); }
    70%  { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
    100% { opacity: 0; transform: translate(-50%, -90%) scale(1); }
  }

  /* ── Phase damage — tint sprite + screen as boss HP drops. ── */
  .ar-boss-sprite.ar-phase-2 { filter: drop-shadow(0 6px 18px rgba(0,0,0,0.75)) hue-rotate(-12deg) saturate(1.1); }
  .ar-boss-sprite.ar-phase-3 { filter: drop-shadow(0 6px 22px rgba(255,87,100,0.6)) hue-rotate(-22deg) saturate(1.3) brightness(0.95); animation: arBossBob 1.8s ease-in-out infinite, arPhaseShake .4s steps(2) infinite; }
  .ar-boss-sprite.ar-phase-4 { filter: drop-shadow(0 6px 26px rgba(255,61,166,0.8)) hue-rotate(-30deg) saturate(1.5) brightness(1.1); animation: arBossBob 1.2s ease-in-out infinite, arPhaseShake .22s steps(2) infinite; }
  /* Juke flash — bright pop on each ENRAGE reposition so the move
     reads as intentional dashing instead of "did it stutter?" */
  .ar-boss-sprite.ar-juke {
    animation: arBossBob 1.2s ease-in-out infinite,
               arPhaseShake .22s steps(2) infinite,
               arBossJuke .35s ease-out;
  }
  @keyframes arBossJuke {
    0%   { filter: drop-shadow(0 6px 26px rgba(255,61,166,0.8)) hue-rotate(-30deg) saturate(1.5) brightness(1.1); }
    30%  { filter: drop-shadow(0 0 32px #fff) brightness(3) saturate(0); opacity: 0.6; }
    100% { filter: drop-shadow(0 6px 26px rgba(255,61,166,0.8)) hue-rotate(-30deg) saturate(1.5) brightness(1.1); opacity: 1; }
  }
  @keyframes arPhaseShake {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(3px); }
  }
  .ar-finisher-modal.ar-tint-2 .ar-scrim { background: linear-gradient(180deg, rgba(80,10,30,0.45) 0%, rgba(0,0,0,0.45) 22%, transparent 50%, rgba(60,10,30,0.5) 100%); }
  .ar-finisher-modal.ar-tint-3 .ar-scrim { background: linear-gradient(180deg, rgba(140,20,40,0.55) 0%, rgba(0,0,0,0.5) 18%, transparent 45%, rgba(120,20,40,0.6) 100%); }
  .ar-finisher-modal.ar-tint-4 .ar-scrim {
    background: linear-gradient(180deg, rgba(200,30,60,0.6) 0%, rgba(20,0,8,0.5) 14%, transparent 40%, rgba(200,30,60,0.7) 100%);
    animation: arEnragePulse 1.2s ease-in-out infinite;
  }
  @keyframes arEnragePulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.78; }
  }
  .ar-enrage-banner {
    position: absolute;
    top: 38%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--px);
    font-size: 26px;
    color: var(--danger);
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--danger);
    letter-spacing: 4px;
    pointer-events: none;
    z-index: 6;
    animation: arEnrageBannerLife 1.1s ease both;
  }
  @keyframes arEnrageBannerLife {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
    20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
    70%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(0.95); }
  }

  /* ── Slam button — bottom-of-screen indicator, cooldown bar. ── */
  .ar-slam-btn {
    width: 100%;
    max-width: 360px;
    position: relative;
    background: rgba(10, 5, 24, 0.8);
    border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    padding: 10px 14px;
    text-align: center;
    overflow: hidden;
    font-family: var(--px);
    color: var(--ink-dim);
    letter-spacing: 2px;
    font-size: 10px;
    user-select: none;
  }
  .ar-slam-fill {
    position: absolute; inset: 0;
    background: linear-gradient(90deg, rgba(123,92,255,0.6) 0%, rgba(255,206,79,0.6) 100%);
    transition: width .1s linear;
    z-index: 0;
  }
  .ar-slam-label {
    position: relative;
    z-index: 1;
  }
  .ar-slam-btn.ready {
    border-color: var(--gold);
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
    box-shadow: 3px 3px 0 #000, 0 0 16px rgba(245,194,66,0.55);
    animation: arSlamReadyPulse 1s ease-in-out infinite;
  }
  @keyframes arSlamReadyPulse {
    0%, 100% { box-shadow: 3px 3px 0 #000, 0 0 14px rgba(245,194,66,0.45); }
    50%      { box-shadow: 3px 3px 0 #000, 0 0 26px rgba(245,194,66,0.85); }
  }

  /* ── Slam flash + screen-shake on big moments. The flash hits hard
     up front, then bleeds out warmer (gold tinge) so it reads as an
     explosion rather than a debug overlay. ── */
  .ar-finisher-modal.ar-slam-flash::after {
    content: '';
    position: absolute; inset: 0;
    background: rgba(255,255,255,0.85);
    pointer-events: none;
    animation: arSlamFlash .42s ease-out forwards;
    z-index: 4;
  }
  @keyframes arSlamFlash {
    0%   { opacity: 1; background: rgba(255,255,255,0.95); }
    25%  { opacity: 0.85; background: rgba(255,230,160,0.65); }
    100% { opacity: 0; background: rgba(255,180,80,0); }
  }
  .ar-finisher-modal.ar-screen-shake .ar-video,
  .ar-finisher-modal.ar-screen-shake .ar-scrim,
  .ar-finisher-modal.ar-screen-shake .ar-overlay {
    animation: arScreenShake .45s ease-out;
  }
  @keyframes arScreenShake {
    0%   { transform: translate(0, 0); }
    15%  { transform: translate(-8px, 6px); }
    30%  { transform: translate(7px, -5px); }
    45%  { transform: translate(-5px, 4px); }
    60%  { transform: translate(4px, -3px); }
    75%  { transform: translate(-3px, 2px); }
    100% { transform: translate(0, 0); }
  }

  /* ── Death particles + sprite shatter. ── */
  .ar-particle {
    position: fixed;
    width: 10px; height: 10px;
    z-index: 250;
    pointer-events: none;
    border: 1px solid #000;
    transform: translate(-50%, -50%);
    animation: arParticleFly 1.1s cubic-bezier(.22,.85,.4,1) forwards;
  }
  @keyframes arParticleFly {
    0%   { transform: translate(-50%, -50%) scale(1) rotate(0deg); opacity: 1; }
    100% { transform: translate(calc(-50% + var(--tx, 0)), calc(-50% + var(--ty, 0))) scale(0.4) rotate(360deg); opacity: 0; }
  }
  .ar-boss-sprite.ar-die {
    animation: arBossDie .9s ease-in forwards;
  }
  @keyframes arBossDie {
    0%   { opacity: 1; filter: brightness(1) drop-shadow(0 0 0 transparent); transform: scale(1) rotate(0); }
    40%  { opacity: 1; filter: brightness(2.5) drop-shadow(0 0 24px #fff); transform: scale(1.18) rotate(-4deg); }
    100% { opacity: 0; filter: brightness(0.4) blur(2px); transform: scale(0.3) rotate(28deg); }
  }
  .ar-result-sub {
    display: block;
    margin-top: 8px;
    font-size: 12px;
    color: var(--neon-3);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 2px;
  }

  /* ── Heartbeat vignette — atmospheric red pulse that intensifies
       with each phase. Lives behind the scrim, in front of the video. */
  .ar-heartbeat {
    position: absolute; inset: 0;
    pointer-events: none;
    z-index: 2;
    box-shadow: inset 0 0 80px 30px rgba(255, 30, 60, 0);
    animation: arHeartbeat 1.8s ease-in-out infinite;
  }
  @keyframes arHeartbeat {
    0%, 100% { box-shadow: inset 0 0 60px 10px rgba(255, 30, 60, 0.06); }
    20%      { box-shadow: inset 0 0 90px 30px rgba(255, 30, 60, 0.14); }
    35%      { box-shadow: inset 0 0 60px 10px rgba(255, 30, 60, 0.06); }
    50%      { box-shadow: inset 0 0 80px 24px rgba(255, 30, 60, 0.12); }
  }
  /* Phase-driven heartbeat tempo — gets faster + more red as boss HP drops. */
  .ar-finisher-modal.ar-tint-2 .ar-heartbeat { animation-duration: 1.4s; }
  .ar-finisher-modal.ar-tint-3 .ar-heartbeat { animation-duration: 1.0s; }
  .ar-finisher-modal.ar-tint-4 .ar-heartbeat { animation-duration: 0.7s; }

  /* ── Rage meter (in the HUD strip). ── */
  .ar-rage {
    margin-top: 12px;
    text-align: center;
  }
  .ar-rage-label {
    font-family: var(--px); font-size: 9px;
    color: var(--danger);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 2px;
    margin-bottom: 4px;
  }
  .ar-rage-bar {
    height: 10px;
    background: #0a0518;
    border: 2px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.6);
    overflow: hidden;
  }
  .ar-rage-fill {
    height: 100%; width: 0%;
    background: linear-gradient(90deg, #ff5764 0%, var(--danger) 50%, #ffce4f 100%);
    transition: width .25s ease;
  }
  /* The big floating RAGE button — only visible at full meter. */
  .ar-rage-btn {
    position: absolute;
    top: 36%; left: 50%;
    transform: translateX(-50%);
    width: 84%;
    max-width: 360px;
    padding: 18px 0;
    border: 4px solid #000;
    background: var(--danger);
    color:var(--ink);
    font-family: var(--px); font-size: 16px;
    letter-spacing: 3px;
    text-shadow: 2px 2px 0 #000;
    box-shadow: 6px 6px 0 #000, 0 0 28px var(--danger);
    cursor: pointer;
    z-index: 7;
    overflow: hidden;
    animation: arRageBtnPulse .6s ease-in-out infinite;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
  }
  .ar-rage-btn-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0%;
    background: linear-gradient(90deg, rgba(255,206,79,0.7), rgba(255,255,255,0.4));
    pointer-events: none;
    transition: none;
  }
  .ar-rage-btn-label { position: relative; z-index: 2; }
  @keyframes arRageBtnPulse {
    0%, 100% { box-shadow: 6px 6px 0 #000, 0 0 24px var(--danger); }
    50%      { box-shadow: 6px 6px 0 #000, 0 0 44px var(--danger); }
  }
  .ar-rage-btn.charging {
    animation: none;
    box-shadow: 6px 6px 0 #000, 0 0 60px var(--gold), 0 0 100px var(--danger);
  }

  /* ── Ability slots — stack of square buttons top-left. ── */
  .ar-abilities {
    position: absolute;
    top: 100px;
    left: 16px;
    display: flex; flex-direction: column; gap: 10px;
    z-index: 5;
  }
  .ar-ability {
    position: relative;
    width: 54px; height: 54px;
    background: rgba(10, 5, 24, 0.85);
    border: 3px solid var(--neon);
    box-shadow: 0 0 12px rgba(255,61,166,0.55), 3px 3px 0 #000;
    cursor: pointer;
    padding: 0;
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    transition: filter .12s ease;
  }
  .ar-ability:active { transform: translate(1px, 1px); }
  .ar-ability.on-cd  { filter: grayscale(1) brightness(0.55); cursor: default; }
  .ar-ability-ic {
    width: 36px; height: 36px;
    object-fit: contain;
    image-rendering: pixelated;
    font-size: 24px;
    line-height: 36px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
  }
  .ar-ability-cd {
    position: absolute;
    left: 0; bottom: 0; right: 0;
    background: rgba(10, 5, 24, 0.7);
    height: 0%;
    transition: height .15s linear;
    pointer-events: none;
  }

  /* ── Counter-attack prompt under the DODGED floater. ── */
  .ar-counter-prompt {
    margin-top: 8px;
    font-family: var(--px); font-size: 12px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000, 0 0 10px var(--gold);
    letter-spacing: 3px;
    animation: arCounterPulse .25s ease-in-out infinite alternate;
  }
  @keyframes arCounterPulse {
    0%   { transform: scale(1); }
    100% { transform: scale(1.08); }
  }

  /* ── Tap-burst particles ── */
  .ar-tap-particle {
    position: fixed;
    width: 6px; height: 6px;
    pointer-events: none;
    border: 1px solid #000;
    transform: translate(-50%, -50%);
    z-index: 199;
    animation: arTapBurst .55s ease-out forwards;
  }
  @keyframes arTapBurst {
    0%   { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
    100% { transform: translate(calc(-50% + var(--tx, 0)), calc(-50% + var(--ty, 0))) scale(0.3); opacity: 0; }
  }

  /* ── Boss-attack-type telegraph hues (jab = yellow, slam = pink, crash = deep red). ── */
  .ar-finisher-modal.ar-windup.ar-atk-jab   .ar-windup-vignette { box-shadow: inset 0 0 100px 30px rgba(255,206,79,0.7); }
  .ar-finisher-modal.ar-windup.ar-atk-slam  .ar-windup-vignette { box-shadow: inset 0 0 120px 40px rgba(255,30,80,0.7); }
  .ar-finisher-modal.ar-windup.ar-atk-crash .ar-windup-vignette { box-shadow: inset 0 0 140px 60px rgba(200,10,40,0.9); animation: arWindupCrashPulse .4s ease-in-out infinite; }
  @keyframes arWindupCrashPulse {
    0%, 100% { box-shadow: inset 0 0 140px 60px rgba(200,10,40,0.85); }
    50%      { box-shadow: inset 0 0 180px 80px rgba(255,30,60,1); }
  }
  /* Attack-type announcement label near the top of the screen. */
  .ar-atk-label {
    position: absolute;
    top: 160px; left: 50%;
    transform: translateX(-50%);
    font-family: var(--px);
    font-size: 18px;
    letter-spacing: 3px;
    pointer-events: none;
    z-index: 5;
    animation: arAtkLabelLife .9s ease both;
    text-shadow: 3px 3px 0 #000;
  }
  .ar-atk-label.ar-atk-jab   { color: var(--gold); }
  .ar-atk-label.ar-atk-slam  { color: var(--neon); }
  .ar-atk-label.ar-atk-crash { color: var(--danger); font-size: 22px; }
  @keyframes arAtkLabelLife {
    0%   { opacity: 0; transform: translate(-50%, -20px) scale(0.6); }
    20%  { opacity: 1; transform: translate(-50%, 0)     scale(1.15); }
    70%  { opacity: 1; transform: translate(-50%, 0)     scale(1); }
    100% { opacity: 0; transform: translate(-50%, -20px) scale(0.95); }
  }

  /* ── Counter / rage / ability damage popups ── */
  .ar-dmg-pop.counter {
    color: var(--gold);
    font-size: 30px;
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--gold);
  }
  .ar-dmg-pop.rage {
    color:var(--ink);
    font-size: 56px;
    text-shadow: 4px 4px 0 #000, 0 0 24px var(--danger), 0 0 48px #ffce4f;
    animation: arSlamDmgFloat 1.3s ease-out forwards;
  }
  .ar-dmg-pop.ability {
    color: var(--neon-3);
    font-size: 36px;
    text-shadow: 3px 3px 0 #000, 0 0 18px var(--neon-3);
  }

  /* Ability shockwave variant — different colour from slam so they're
     readable as different events on overlapping fires. */
  .ar-slam-shockwave.ability {
    border-color: var(--neon);
    box-shadow: 0 0 24px var(--neon), inset 0 0 16px var(--neon);
  }

  /* ── Victory rank / stats / death quote ── */
  .ar-rank {
    font-family: var(--px);
    font-size: 96px;
    line-height: 1;
    letter-spacing: 2px;
    margin-bottom: 8px;
    animation: arRankPop .6s ease both;
  }
  @keyframes arRankPop {
    0%   { opacity: 0; transform: scale(0.2) rotate(-12deg); }
    60%  { opacity: 1; transform: scale(1.35) rotate(4deg); }
    100% { opacity: 1; transform: scale(1)    rotate(0deg); }
  }
  .ar-victory-title {
    font-family: var(--px);
    font-size: 22px;
    color: var(--gold);
    text-shadow: 3px 3px 0 #000, 0 0 16px var(--gold);
    letter-spacing: 3px;
    margin-bottom: 16px;
  }
  .ar-stats {
    display: flex; flex-direction: column; gap: 6px;
    align-items: stretch;
    max-width: 320px;
    margin: 0 auto 14px;
    text-align: left;
  }
  .ar-stat {
    display: flex; justify-content: space-between;
    font-family: var(--px); font-size: 10px;
    letter-spacing: 1px;
    background: rgba(10, 5, 24, 0.75);
    border: 2px solid #000;
    padding: 6px 10px;
  }
  .ar-stat .l { color: var(--ink-dim); }
  .ar-stat .v { color: var(--ink); }
  .ar-stat.bonus {
    border-color: var(--gold);
    box-shadow: 0 0 10px rgba(245,194,66,0.4);
  }
  .ar-stat.bonus .l, .ar-stat.bonus .v { color: var(--gold); text-shadow: 1px 1px 0 #000; }
  .ar-death-quote {
    font-family: var(--term);
    font-size: 14px;
    color: var(--ink-faint);
    font-style: italic;
    margin-top: 12px;
    line-height: 1.4;
    max-width: 320px;
    margin-left: auto; margin-right: auto;
  }

  /* ── Final-step AR-only stage card. Sits in place of the photo
       capture stage, so the player sees ONE primary path (the AR
       button) instead of the photo + AR pair the user flagged. ── */
  .ar-only-stage {
    background: linear-gradient(135deg, rgba(40, 5, 20, 0.85), rgba(70, 10, 40, 0.85));
    border: 3px solid var(--gold);
    box-shadow: 4px 4px 0 #000, inset 0 0 24px rgba(255, 61, 166, 0.15);
    padding: 14px;
    text-align: center;
    margin-bottom: 10px;
  }
  .ar-only-tag {
    font-family: var(--px); font-size: 11px;
    color: var(--gold);
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 3px;
    margin-bottom: 8px;
  }
  .ar-only-body {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim);
    line-height: 1.5;
  }
  .ar-photo-opt {
    color: var(--ink-faint);
    text-decoration: underline;
    cursor: pointer;
  }
  .ar-photo-opt:hover { color: var(--ink-dim); }
  .ar-back-to-fight {
    margin-top: 10px;
    width: 100%;
    font-size: 10px;
    letter-spacing: 2px;
  }

  /* AR Finisher launcher (on the step card, not inside the AR modal). */
  .ar-finisher-btn {
    margin-top: 12px;
    font-size: 12px;
    letter-spacing: 2px;
    padding: 14px 18px;
    width: 100%;
    box-shadow: 4px 4px 0 #000, 0 0 18px rgba(245, 194, 66, 0.45);
    animation: arBtnPulse 1.6s ease-in-out infinite;
  }
  @keyframes arBtnPulse {
    0%, 100% { box-shadow: 4px 4px 0 #000, 0 0 16px rgba(245, 194, 66, 0.4); }
    50%      { box-shadow: 4px 4px 0 #000, 0 0 28px rgba(245, 194, 66, 0.8); }
  }
  .ar-finisher-hint {
    font-family: var(--term);
    font-size: 12px;
    color: var(--ink-faint);
    text-align: center;
    margin-top: 4px;
    line-height: 1.4;
  }

  /* ---------- In-app self-timer camera ---------- */
  .camera-modal {
    position: fixed; inset: 0;
    z-index: 120;
    background: #000;
    display: flex; flex-direction: column;
    animation: fadeUp .15s ease;
  }
  .camera-video {
    flex: 1;
    width: 100%;
    object-fit: cover;
    display: block;
    background: #000;
  }
  .camera-overlay {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
  }
  .camera-countdown {
    font-family: var(--px); font-size: 130px;
    color: var(--gold);
    text-shadow: 4px 4px 0 #000, 0 0 24px rgba(255,206,79,0.55);
    animation: pulseCountdown 1s steps(2) infinite;
    line-height: 1;
  }
  @keyframes pulseCountdown {
    0%   { transform: scale(1); }
    100% { transform: scale(1.15); }
  }
  .camera-flash {
    position: absolute; inset: 0;
    background: white;
    opacity: 0;
    pointer-events: none;
  }
  .camera-flash.fire {
    animation: cameraFlash 0.4s ease-out;
  }
  @keyframes cameraFlash {
    0%   { opacity: 0; }
    20%  { opacity: 0.85; }
    100% { opacity: 0; }
  }
  .camera-topbar {
    position: absolute; top: 0; left: 0; right: 0;
    padding: 14px 16px;
    background: linear-gradient(180deg, rgba(0,0,0,0.7), transparent);
    display: flex; justify-content: space-between; align-items: center;
    z-index: 2;
  }
  .camera-topbar .label {
    font-family: var(--px); font-size: 9px; color: var(--neon-3);
    text-shadow: 2px 2px 0 #000; letter-spacing: 1.5px;
  }
  .camera-topbar .closeX {
    background: var(--neon); border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    color:var(--ink); text-shadow: 1px 1px 0 #000;
    font-family: var(--px); font-size: 12px;
    width: 36px; height: 36px;
    cursor: pointer;
  }
  .camera-flash-btn {
    background: var(--card); border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    color: var(--ink);
    width: 36px; height: 36px;
    cursor: pointer;
    font-size: 18px;
    line-height: 1;
    display: none; /* shown only when torch is supported */
    align-items: center; justify-content: center;
    padding: 0;
  }
  .camera-flash-btn.on {
    background: var(--gold);
    color: #2a1500;
  }
  .camera-zoom {
    position: absolute;
    bottom: 96px;
    left: 50%;
    transform: translateX(-50%);
    display: flex; gap: 6px;
    background: rgba(0, 0, 0, 0.7);
    padding: 6px;
    border: 2px solid #000;
    box-shadow: 3px 3px 0 #000;
    z-index: 2;
  }
  .camera-zoom .zbtn {
    background: rgba(0, 0, 0, 0.4); color:var(--ink);
    border: 2px solid var(--neon-3);
    padding: 6px 12px;
    font-family: var(--px); font-size: 9px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
    letter-spacing: 1px;
  }
  .camera-zoom .zbtn.on {
    background: var(--neon-3);
    color: #000;
    text-shadow: none;
  }
  .camera-controls {
    position: absolute; bottom: 24px; left: 0; right: 0;
    display: flex; gap: 10px; padding: 0 16px;
    z-index: 2;
  }
  .camera-controls .btn { flex: 1; padding: 14px 8px; font-size: 10px; }
  .camera-duration {
    position: absolute; top: 64px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 8px;
    z-index: 2;
  }
  .camera-duration .chip {
    padding: 6px 10px;
    font-family: var(--px); font-size: 9px;
    background: rgba(0,0,0,0.6); color:var(--ink);
    border: 2px solid #000; cursor: pointer;
  }
  .camera-duration .chip.on {
    background: var(--neon-3); color: #000;
  }

  /* ---------- Photo input ---------- */
  .photo-input { display: none; }
  .photo-stage img.snap {
    width: 100%; height: 100%; object-fit: cover; image-rendering: auto;
    filter: contrast(1.05) saturate(1.1);
  }
  .photo-judge {
    margin-top: 8px; padding: 10px 12px;
    border: 3px solid #000;
    background: var(--card);
    box-shadow: 3px 3px 0 #000;
    font-family: var(--term); font-size: 16px;
    line-height: 1.3;
  }
  .photo-judge.pass { box-shadow: 3px 3px 0 var(--neon-3); border-left: 6px solid var(--neon-3); }
  .photo-judge.fail { box-shadow: 3px 3px 0 var(--danger); border-left: 6px solid var(--danger); }
  /* Per-step escape hatch — its own pixel-art treatment: a dashed,
     muted "secondary action" look so it's findable but never competes
     with the solid Submit / Capture buttons or invites casual skips. */
  .step-skip-btn {
    display: block; width: 100%;
    margin-top: 10px;
    padding: 9px 10px;
    background: rgba(0, 0, 0, 0.22);
    border: 2px dashed var(--ink-faint);
    border-radius: 0;
    color: var(--ink-dim);
    font-family: var(--px); font-size: 9px; letter-spacing: 1.5px;
    text-align: center; cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
  }
  .step-skip-btn:hover { color: var(--ink); border-color: var(--ink-dim); }
  .step-skip-btn:active { transform: translate(0, 1px); background: rgba(0, 0, 0, 0.4); }
  /* Skip-step confirm modal. */
  .skip-modal-ic {
    font-family: var(--px); font-size: 24px;
    color: var(--ink-dim); letter-spacing: 3px;
    margin-bottom: 6px;
  }
  .photo-judge .verdict { font-family: var(--px); font-size: 10px; margin-bottom: 6px; }
  .photo-judge.pass .verdict { color: var(--neon-3); }
  .photo-judge.fail .verdict { color: var(--danger); }

  /* ---------- Motion-proof stage ---------- */
  /* Sensor-based step verification UI. Lives in the step card next to
     the photo-stage classes so the eye lines them up as the same kind
     of "do something real to advance" affordance. */
  .motion-stage {
    background: var(--card);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5),
                inset  2px  2px 0 rgba(255,255,255,0.06),
                4px 4px 0 #000;
    padding: 16px 14px 14px;
    text-align: center;
    margin-top: 10px;
  }
  .motion-label {
    font-family: var(--px); font-size: 10px;
    color: var(--gold);
    letter-spacing: 2px;
    margin-bottom: 12px;
  }
  .motion-bar {
    height: 14px;
    background: #0a0518;
    border: 2px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.6);
    overflow: hidden;
  }
  .motion-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--neon-3) 0%, var(--neon) 60%, var(--gold) 100%);
    transition: width .18s ease;
    width: 0%;
  }
  .motion-count {
    font-family: var(--px); font-size: 14px;
    color: var(--ink);
    margin: 10px 0 6px;
    letter-spacing: 1px;
  }
  .motion-hint {
    font-family: var(--term);
    font-size: 13px;
    color: var(--ink-dim);
    line-height: 1.45;
  }

  /* ---------- Geo-gate stage ---------- */
  /* "Walk N meters from where you started before this step's proof
     unlocks" UI. Pixel-paired with .motion-stage so the eye reads them
     as the same family of "the phone is verifying you actually did the
     thing" surfaces. Bar fills as the player covers ground. */
  .geo-stage {
    background: var(--card);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5),
                inset  2px  2px 0 rgba(255,255,255,0.06),
                4px 4px 0 #000;
    padding: 16px 14px 14px;
    text-align: center;
    margin-top: 10px;
  }
  .geo-label {
    font-family: var(--px); font-size: 10px;
    color: var(--neon-3);
    letter-spacing: 2px;
    margin-bottom: 12px;
  }
  .geo-bar {
    height: 14px;
    background: #0a0518;
    border: 2px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.6);
    overflow: hidden;
  }
  .geo-bar-fill {
    height: 100%;
    /* Distinct palette from motion-bar so the player can tell at a
       glance which kind of "do the thing" surface they're looking at —
       blue-ish for "go somewhere," warm for "move the phone." */
    background: linear-gradient(90deg, #4adcff 0%, var(--neon-3) 55%, var(--gold) 100%);
    transition: width .25s ease;
    width: 0%;
  }
  .geo-distance {
    font-family: var(--px); font-size: 14px;
    color: var(--ink);
    margin: 10px 0 2px;
    letter-spacing: 1px;
  }
  .geo-meta {
    font-family: var(--px); font-size: 8px;
    color: var(--ink-faint);
    margin-bottom: 8px;
    letter-spacing: 1px;
    min-height: 12px;
  }
  .geo-hint {
    font-family: var(--term);
    font-size: 13px;
    color: var(--ink-dim);
    line-height: 1.45;
  }
  .geo-skip-hint {
    display: inline-block;
    margin-top: 4px;
    font-size: 11px;
    color: var(--ink-faint);
    font-style: italic;
  }
  /* ---------- Walk-gate compass + POI line ---------- */
  .geo-compass {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 10px 0 6px;
    padding: 10px 8px;
    background: rgba(74, 220, 255, 0.05);
    border: 2px solid rgba(74, 220, 255, 0.25);
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4);
  }
  .geo-compass-ring {
    flex: 0 0 64px;
    width: 64px; height: 64px;
    border: 3px solid #000;
    border-radius: 50%;
    background: radial-gradient(circle, #061122 0%, #02060f 100%);
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.6),
                inset -2px -2px 0 rgba(74,220,255,0.18);
    display: flex; align-items: center; justify-content: center;
    position: relative;
  }
  .geo-compass-ring::before {
    content: 'N';
    position: absolute;
    top: 2px; left: 50%;
    transform: translateX(-50%);
    font-family: var(--px); font-size: 8px;
    color: #ff5b5b;
    letter-spacing: 1px;
  }
  .geo-compass-arrow {
    font-size: 30px;
    color: var(--gold);
    text-shadow: 0 0 8px var(--gold), 0 0 14px rgba(255,209,102,0.4);
    transition: transform .25s ease-out;
    transform-origin: 50% 50%;
    line-height: 1;
    user-select: none;
  }
  .geo-compass-arrow.no-heading {
    opacity: 0.4;
    color: var(--ink-dim);
    text-shadow: none;
  }
  .geo-poi-line {
    flex: 1 1 auto;
    text-align: left;
    min-width: 0;
  }
  .geo-poi-name {
    font-family: var(--px); font-size: 12px;
    color: var(--ink);
    letter-spacing: 1px;
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .geo-poi-open {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 5px;
    font-family: var(--px); font-size: 8px;
    letter-spacing: 1px;
    background: #16321a;
    color: #6fe278;
    border: 1px solid #000;
    vertical-align: middle;
  }
  .geo-poi-open.unknown {
    background: #312716;
    color: #ffd166;
  }
  .geo-poi-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
  }
  .geo-poi-dist {
    font-family: var(--px); font-size: 13px;
    color: var(--gold);
    letter-spacing: 1px;
  }
  .btn.xs {
    padding: 5px 10px;
    font-size: 10px;
    letter-spacing: 1px;
  }
  .geo-compass-loading {
    font-family: var(--px); font-size: 10px;
    color: var(--ink-faint);
    letter-spacing: 1px;
    margin: 10px 0 4px;
    opacity: 0.7;
    animation: geoScan 1.4s ease-in-out infinite;
  }
  @keyframes geoScan {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 0.85; }
  }
  /* ---------- Walk-gate map overlay ---------- */
  .geo-map-overlay {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.85);
    display: flex; align-items: center; justify-content: center;
    z-index: 9000;
    padding: 16px;
    animation: gmFade 0.18s ease-out;
  }
  @keyframes gmFade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  .geo-map-card {
    background: var(--card);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.5),
                inset  2px  2px 0 rgba(255,255,255,0.06),
                6px 6px 0 #000;
    padding: 12px;
    max-width: 360px;
    width: 100%;
  }
  .geo-map-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 10px;
  }
  .geo-map-title {
    font-family: var(--px); font-size: 11px;
    color: var(--neon-3);
    letter-spacing: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1 1 auto;
    min-width: 0;
    padding-right: 10px;
  }
  .geo-map-close {
    background: #1a0a0a;
    color: var(--ink);
    border: 2px solid #000;
    font-family: var(--px); font-size: 12px;
    padding: 4px 10px;
    cursor: pointer;
    box-shadow: 2px 2px 0 #000;
  }
  .geo-map-close:active {
    transform: translate(1px, 1px);
    box-shadow: 1px 1px 0 #000;
  }
  .geo-map-canvas {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    max-width: 320px;
    margin: 0 auto;
    border: 2px solid #000;
    image-rendering: pixelated;
    background: #0a0518;
  }
  .geo-map-legend {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    margin-top: 10px;
    font-family: var(--px); font-size: 9px;
    color: var(--ink-dim);
    letter-spacing: 1px;
  }
  .geo-map-legend .dot {
    display: inline-block;
    width: 8px; height: 8px;
    margin-right: 4px;
    vertical-align: middle;
    border: 1px solid #000;
  }
  .geo-map-legend .dot.user  { background: #4adcff; }
  .geo-map-legend .dot.poi   { background: #ffd166; }
  .geo-map-legend .dot.start { background: #888; }

  /* ---------- Avatar (header + profile) ---------- */
  .avatar {
    position: relative;
    width: 36px; height: 36px;
    background: var(--card);
    border: 2px solid #000;
    overflow: hidden;
    cursor: pointer;
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; line-height: 1;
    user-select: none;
    transition: transform .06s;
  }
  .avatar:active { transform: translate(1px, 1px); }
  .avatar img {
    width: 100%; height: 100%; object-fit: cover;
    image-rendering: auto;
  }
  /* When the avatar slot falls back to the System AI face (no user
     photo set), keep crisp pixel scaling and contain-fit so the
     painted portrait isn't cropped or blurred. */
  .avatar .system-av-img {
    width: 100%; height: 100%;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
  }
  /* Default avatar — silhouette of a person on a faded arcade-purple
     gradient that smoothly blends into the cabinet palette. The stock
     "👤" emoji is hidden (font-size: 0); the silhouette and backdrop
     are drawn entirely via CSS so any avatar size renders the same. */
  .avatar .placeholder {
    display: block;
    width: 100%; height: 100%;
    font-size: 0; color: transparent;
    background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ccircle cx='32' cy='24' r='10' fill='%23000' fill-opacity='0.78'/%3E%3Cpath d='M 12 64 Q 12 40 32 40 Q 52 40 52 64 Z' fill='%23000' fill-opacity='0.78'/%3E%3C/svg%3E") center/72% no-repeat,
      radial-gradient(ellipse at 50% 28%, rgba(180,108,255,0.22) 0%, rgba(180,108,255,0) 65%),
      linear-gradient(180deg, #2a1740 0%, #150b25 60%, #0a0518 100%);
    image-rendering: auto;
  }
  .avatar.lg  { width: 96px;  height: 96px;  font-size: 38px; border-width: 3px; }
  .avatar.xl  { width: 140px; height: 140px; font-size: 56px; border-width: 4px; }

  /* Frame variants — applied as outer rings via box-shadow so the photo stays clean */
  .avatar.frame-none {}
  .avatar.frame-gold {
    box-shadow: 0 0 0 2px var(--gold), 0 0 0 4px #000;
  }
  .avatar.frame-pink {
    box-shadow: 0 0 0 2px var(--neon), 0 0 0 4px #000, 0 0 10px rgba(255,61,166,0.55);
  }
  .avatar.frame-teal {
    box-shadow: 0 0 0 2px var(--neon-3), 0 0 0 4px #000, 0 0 10px rgba(0,230,195,0.5);
  }
  .avatar.frame-fire {
    box-shadow: 0 0 0 2px #ff5764, 0 0 0 4px #000, 0 0 12px 2px #ff8c4a;
    animation: avatarFire 0.32s steps(2) infinite;
  }
  @keyframes avatarFire {
    0%   { box-shadow: 0 0 0 2px #ff5764, 0 0 0 4px #000, 0 0 12px 2px #ff8c4a; }
    100% { box-shadow: 0 0 0 2px var(--gold), 0 0 0 4px #000, 0 0 16px 3px #ff5764; }
  }
  .avatar.frame-rainbow {
    animation: avatarRainbow 1.4s steps(6) infinite;
  }
  @keyframes avatarRainbow {
    0%   { box-shadow: 0 0 0 3px #ff3da6, 0 0 0 5px #000; }
    16%  { box-shadow: 0 0 0 3px #ffce4f, 0 0 0 5px #000; }
    33%  { box-shadow: 0 0 0 3px #00e6c3, 0 0 0 5px #000; }
    50%  { box-shadow: 0 0 0 3px #1e6bd8, 0 0 0 5px #000; }
    66%  { box-shadow: 0 0 0 3px #7b5cff, 0 0 0 5px #000; }
    83%  { box-shadow: 0 0 0 3px #ff5764, 0 0 0 5px #000; }
    100% { box-shadow: 0 0 0 3px #ff3da6, 0 0 0 5px #000; }
  }
  .avatar.frame-crown {
    box-shadow: 0 0 0 2px var(--gold), 0 0 0 4px #000;
    overflow: visible;
  }
  .avatar.frame-crown::before {
    content: '👑';
    position: absolute;
    top: -14px; left: 50%; transform: translateX(-50%);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
    z-index: 2;
  }
  .avatar.frame-crown.lg::before { top: -22px; font-size: 30px; }
  .avatar.frame-crown.xl::before { top: -32px; font-size: 44px; }
  .avatar.frame-goblin {
    box-shadow: 0 0 0 2px #6b3a14, 0 0 0 4px #000;
    overflow: visible;
  }
  .avatar.frame-goblin::before {
    content: '🛋️';
    position: absolute;
    bottom: -8px; right: -8px;
    font-size: 14px;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
  }
  .avatar.frame-goblin.lg::before { font-size: 24px; bottom: -10px; right: -10px; }
  .avatar.frame-goblin.xl::before { font-size: 32px; bottom: -12px; right: -12px; }
  .avatar.frame-wraith {
    box-shadow: 0 0 0 2px var(--neon-3), 0 0 0 4px #000;
    overflow: visible;
  }
  .avatar.frame-wraith::before {
    content: '🔍';
    position: absolute;
    bottom: -6px; left: -6px;
    font-size: 14px;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
  }
  .avatar.frame-wraith.lg::before { font-size: 22px; bottom: -8px; left: -8px; }
  .avatar.frame-wraith.xl::before { font-size: 30px; bottom: -10px; left: -10px; }

  /* ── Common rarity frames — pixel-art image overlay ── */
  /* Frame image fills the slot's bounds (inset:0) so the painted decoration
     never spills past whatever ancestor card it's mounted in. The avatar
     content (img / emoji) is pushed inward via padding so it lands inside
     the frame's painted inner cutout (~62% of the frame canvas) instead of
     bleeding past the cutout's edges. */
  .avatar[class*="frame-img-"] {
    overflow: visible;
    box-shadow: none !important;
    border: 0 !important;
    animation: none !important;
    /* Soft purple radial-gradient stage behind the chibi. The painted frame
       overlay (::after, z-index:3) covers the outer ring, so this gradient
       only shows through inside the frame's cutout — giving the avatar a
       small spotlight backdrop instead of sitting on the raw cell color.
       Anchored to bottom-center; sized 20px shorter than the slot so the
       top of the slot stays transparent. */
    background:
      radial-gradient(ellipse at center,
        rgba(180, 108, 255, 0.35) 0%,
        rgba(80, 40, 130, 0.4) 55%,
        rgba(20, 10, 35, 0.55) 100%) center / 100% calc(100% - 40px) no-repeat !important;
    box-sizing: border-box;
    padding: 0;
  }
  /* Make the inner photo / pixel-art portrait fully fill the frame's painted
     inner cutout instead of sitting in a grey box. cover > contain because
     the frames are square and we want no empty halo around the image. */
  .avatar[class*="frame-img-"] > img {
    width: 100%; height: 100%; object-fit: cover; display: block;
  }
  /* Painted chibi avatar inside any framed avatar slot. Originally
     designed to "peek up" from the bottom (width 60% / height 50% /
     bottom 16%) which read as "half cut off" to testers #3 and #4 in
     the header where the slot is only 36px tall. Bumped to fill ~85%
     of the cell so the whole character is visible without losing the
     intentional bottom anchor. Larger callsites (lg/xl) still feel
     framed because .avatar.lg / .avatar.xl scale the cell, not these. */
  .avatar img.chibi-inner {
    position: absolute;
    left: 50%;
    bottom: 4%;
    transform: translateX(-50%);
    width: 86%;
    height: 86%;
    object-fit: contain;
    object-position: bottom center;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    pointer-events: none;
    z-index: 2;
  }
  /* Chibi picker modal — list of all 12 painted avatars to choose from */
  .chibi-picker-bg {
    position: fixed; inset: 0; background: rgba(10,5,24,0.82);
    display: flex; align-items: center; justify-content: center;
    z-index: 200; padding: 18px;
  }
  .chibi-picker {
    background: var(--card); border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 6px 6px 0 #000;
    padding: 18px; max-width: 380px; width: 100%;
    text-align: center;
  }
  .chibi-picker h3 { font-family: var(--px); font-size: 12px; color: var(--neon-3); margin-bottom: 12px; letter-spacing: 1px; }
  .chibi-picker .grid {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
    margin: 8px 0 14px;
  }
  .chibi-picker .pick {
    width: 60px; height: 60px;
    background: var(--bg-1); border: 2px solid #000;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: transform .06s;
    overflow: hidden;
  }
  .chibi-picker .pick:active { transform: translate(2px, 2px); }
  .chibi-picker .pick.sel { border-color: var(--neon-3); box-shadow: inset 0 0 0 2px var(--neon-3); }
  .chibi-picker .pick img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
  .avatar[class*="frame-img-"]::before { content: none !important; }
  .avatar[class*="frame-img-"]::after {
    content: ''; position: absolute; inset: 0;
    background-size: 100% 100%; background-repeat: no-repeat;
    image-rendering: pixelated; image-rendering: crisp-edges;
    pointer-events: none; z-index: 3;
  }
  .avatar[class*="frame-img-"] > img { border-radius: 0; }
  .avatar.frame-img-silver::after    { background-image: url('../img/frame_silver.png?v=6'); }
  .avatar.frame-img-bronze::after    { background-image: url('../img/frame_bronze.png?v=6'); }
  .avatar.frame-img-mint::after      { background-image: url('../img/frame_mint.png?v=6'); }
  .avatar.frame-img-lavender::after  { background-image: url('../img/frame_lavender.png?v=6'); }
  .avatar.frame-img-crown::after     { background-image: url('../img/frame_crown.png?v=6'); }
  .avatar.frame-img-goblin::after    { background-image: url('../img/frame_goblin.png?v=6'); }
  .avatar.frame-img-wraith::after    { background-image: url('../img/frame_wraith.png?v=6'); }
  .avatar.frame-img-honey::after     { background-image: url('../img/frame_honey.png?v=6'); }
  .avatar.frame-img-glass::after     { background-image: url('../img/frame_glass.png?v=6'); }
  .avatar.frame-img-fire::after      { background-image: url('../img/frame_fire.png?v=6'); }
  .avatar.frame-img-ghostly::after   { background-image: url('../img/frame_ghostly.png?v=6'); }
  .avatar.frame-img-ruby::after      { background-image: url('../img/frame_ruby.png?v=6'); }
  .avatar.frame-img-static::after    { background-image: url('../img/frame_static.png?v=6'); }
  .avatar.frame-img-rainbow::after   { background-image: url('../img/frame_rainbow.png?v=6'); }
  .avatar.frame-img-aurora::after    { background-image: url('../img/frame_aurora.png?v=6'); }
  .avatar.frame-img-mercury::after   { background-image: url('../img/frame_mercury.png?v=6'); }
  .avatar.frame-img-void::after      { background-image: url('../img/frame_void.png?v=6'); }
  /* Legendary frames animate via the --frame-anim CSS variable so all
     visible instances on the page share the same frame index without
     each one needing its own setInterval. */
  .avatar.frame-img-gremlin::after   { background-image: var(--frame-gremlin-anim, url('../img/frame_gremlin.png?v=6')); }
  .avatar.frame-img-eldritch::after  { background-image: var(--frame-eldritch-anim, url('../img/frame_eldritch.png?v=6')); }
  .avatar.frame-img-arcadeking::after { background-image: var(--frame-arcadeking-anim, url('../img/frame_arcadeking.png?v=6')); }
  .avatar.frame-img-shattered::after  { background-image: var(--frame-shattered-anim, url('../img/frame_shattered.png?v=6')); }
  .avatar.frame-img-vetshalo::after   { background-image: var(--frame-vetshalo-anim, url('../img/frame_vetshalo.png?v=6')); }
  /* Inner-cutout padding stays proportional regardless of slot size. */

  /* Legacy CSS-only fallback for the same IDs (used if the avatar is rendered
     before the image-frame class is applied). Keeping the ring color so the
     equipped state still reads in older paths. */
  .avatar.frame-silver   { box-shadow: 0 0 0 2px #c0c4cc, 0 0 0 4px #000; }
  .avatar.frame-bronze   { box-shadow: 0 0 0 2px #b07a3a, 0 0 0 4px #000; }
  .avatar.frame-mint     { box-shadow: 0 0 0 2px #88e2b8, 0 0 0 4px #000; }
  .avatar.frame-lavender { box-shadow: 0 0 0 2px #b89ce6, 0 0 0 4px #000; }

  /* ── Uncommon — soft glow ── */
  .avatar.frame-honey {
    box-shadow: 0 0 0 2px #ffce4f, 0 0 0 4px #000, 0 0 12px rgba(255,206,79,0.55);
    animation: avatarHoney 1.6s steps(8) infinite;
  }
  @keyframes avatarHoney {
    0%, 100% { box-shadow: 0 0 0 2px #ffce4f, 0 0 0 4px #000, 0 0 12px rgba(255,206,79,0.5); }
    50%      { box-shadow: 0 0 0 2px #ffe27f, 0 0 0 4px #000, 0 0 18px rgba(255,206,79,0.75); }
  }
  .avatar.frame-glass {
    box-shadow: 0 0 0 2px rgba(255,255,255,0.85), 0 0 0 4px #000, 0 0 14px rgba(180,220,255,0.45);
    backdrop-filter: blur(1px);
  }

  /* ── Rare — animated ── */
  .avatar.frame-ghostly {
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px #000, 0 0 14px rgba(255,255,255,0.45);
    animation: avatarGhostly 1.8s steps(8) infinite;
    opacity: 0.97;
  }
  @keyframes avatarGhostly {
    0%, 100% { box-shadow: 0 0 0 2px #fff, 0 0 0 4px #000, 0 0 12px rgba(255,255,255,0.4); opacity: 1; }
    50%      { box-shadow: 0 0 0 2px #cce0ff, 0 0 0 4px #000, 0 0 22px rgba(204,224,255,0.7); opacity: 0.78; }
  }
  .avatar.frame-ruby {
    box-shadow: 0 0 0 2px #d83154, 0 0 0 4px #000, 0 0 16px rgba(216,49,84,0.55);
    animation: avatarRuby 1.2s steps(6) infinite;
  }
  @keyframes avatarRuby {
    0%, 100% { box-shadow: 0 0 0 2px #d83154, 0 0 0 4px #000, 0 0 14px rgba(216,49,84,0.5); }
    50%      { box-shadow: 0 0 0 2px #ff5b86, 0 0 0 4px #000, 0 0 24px rgba(255,91,134,0.85); }
  }
  .avatar.frame-static {
    box-shadow: 0 0 0 2px #00e6c3, 0 0 0 4px #000, 0 0 10px rgba(0,230,195,0.4);
    animation: avatarStatic 0.18s steps(2) infinite;
    overflow: visible;
  }
  @keyframes avatarStatic {
    0%   { box-shadow: 0 0 0 2px #00e6c3, 0 0 0 4px #000; filter: hue-rotate(0deg); }
    100% { box-shadow: 0 0 0 2px #7b5cff, 0 0 0 4px #000; filter: hue-rotate(20deg); }
  }

  /* ── Epic — multi-effect animated ── */
  .avatar.frame-aurora {
    animation: avatarAurora 3s steps(12) infinite;
  }
  @keyframes avatarAurora {
    0%   { box-shadow: 0 0 0 3px #00e6c3, 0 0 0 5px #000, 0 0 18px rgba(0,230,195,0.6); }
    25%  { box-shadow: 0 0 0 3px #7b5cff, 0 0 0 5px #000, 0 0 22px rgba(123,92,255,0.65); }
    50%  { box-shadow: 0 0 0 3px #ff3da6, 0 0 0 5px #000, 0 0 22px rgba(255,61,166,0.65); }
    75%  { box-shadow: 0 0 0 3px #00e6c3, 0 0 0 5px #000, 0 0 18px rgba(0,230,195,0.6); }
    100% { box-shadow: 0 0 0 3px #7b5cff, 0 0 0 5px #000, 0 0 18px rgba(123,92,255,0.6); }
  }
  .avatar.frame-mercury {
    box-shadow: 0 0 0 3px #d0d4dc, 0 0 0 5px #000, 0 0 18px rgba(200,210,230,0.6);
    animation: avatarMercury 2s steps(8) infinite;
    filter: contrast(1.05);
  }
  @keyframes avatarMercury {
    0%, 100% { box-shadow: 0 0 0 3px #d0d4dc, 0 0 0 5px #000, 0 0 18px rgba(200,210,230,0.55); filter: contrast(1.05) brightness(1.0); }
    50%      { box-shadow: 0 0 0 3px #ffffff, 0 0 0 5px #000, 0 0 26px rgba(255,255,255,0.75); filter: contrast(1.15) brightness(1.15); }
  }
  .avatar.frame-void {
    box-shadow: 0 0 0 3px #000, 0 0 0 5px #2a0848, 0 0 22px rgba(42,8,72,0.7);
    overflow: visible;
  }
  .avatar.frame-void::before {
    content: '✦';
    position: absolute;
    top: -10px; left: 50%; transform: translateX(-50%);
    font-size: 14px;
    color:var(--ink);
    text-shadow: 0 0 6px var(--neon-2), 1px 1px 0 #000;
    pointer-events: none;
    animation: voidStar 4s linear infinite;
  }
  @keyframes voidStar {
    0%   { transform: translateX(-50%) rotate(0deg); }
    100% { transform: translateX(-50%) rotate(360deg); }
  }
  .avatar.frame-void.lg::before { top: -16px; font-size: 22px; }
  .avatar.frame-void.xl::before { top: -22px; font-size: 32px; }

  /* ── Legendary — peak-tier stacked effects ── */
  .avatar.frame-gremlin {
    animation: avatarGremlin 1.6s steps(8) infinite;
    overflow: visible;
  }
  @keyframes avatarGremlin {
    0%, 100% { box-shadow:
      0 0 0 2px var(--neon), 0 0 0 4px #000,
      0 0 0 6px var(--neon-2), 0 0 0 8px #000,
      0 0 24px rgba(255,61,166,0.7); }
    50%      { box-shadow:
      0 0 0 2px var(--neon-2), 0 0 0 4px #000,
      0 0 0 6px var(--neon), 0 0 0 8px #000,
      0 0 32px rgba(123,92,255,0.85); }
  }
  .avatar.frame-gremlin::before {
    content: '🦇';
    position: absolute;
    top: -14px; left: 50%; transform: translateX(-50%);
    font-size: 16px;
    text-shadow: 1px 1px 0 #000, 0 0 6px rgba(255,61,166,0.6);
    pointer-events: none;
    animation: gremlinShake 0.6s steps(8) infinite;
    z-index: 2;
  }
  @keyframes gremlinShake {
    0%, 100% { transform: translateX(-50%) rotate(-6deg); }
    50%      { transform: translateX(-50%) rotate(6deg); }
  }
  .avatar.frame-gremlin.lg::before { top: -22px; font-size: 28px; }
  .avatar.frame-gremlin.xl::before { top: -32px; font-size: 40px; }
  .avatar.frame-eldritch {
    box-shadow: 0 0 0 3px var(--neon-2), 0 0 0 5px #000, 0 0 22px rgba(123,92,255,0.7);
    animation: avatarEldritch 3s steps(12) infinite;
    overflow: visible;
  }
  @keyframes avatarEldritch {
    0%, 100% { box-shadow: 0 0 0 3px var(--neon-2), 0 0 0 5px #000, 0 0 22px rgba(123,92,255,0.7); }
    50%      { box-shadow: 0 0 0 3px var(--neon),   0 0 0 5px #000, 0 0 30px rgba(255,61,166,0.8); }
  }
  .avatar.frame-eldritch::before {
    content: '👁️';
    position: absolute;
    top: -12px; left: 50%; transform: translateX(-50%);
    font-size: 18px;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
    animation: eldritchBlink 4s steps(20) infinite;
    z-index: 2;
  }
  @keyframes eldritchBlink {
    0%, 90%, 100% { opacity: 1; transform: translateX(-50%) scaleY(1); }
    93%           { opacity: 1; transform: translateX(-50%) scaleY(0.1); }
    96%           { opacity: 1; transform: translateX(-50%) scaleY(1); }
  }
  .avatar.frame-eldritch.lg::before { top: -20px; font-size: 28px; }
  .avatar.frame-eldritch.xl::before { top: -28px; font-size: 38px; }
  .avatar.frame-shattered {
    box-shadow: 0 0 0 2px var(--gold), 0 0 0 3px #000, 0 0 0 5px var(--danger), 0 0 0 7px #000, 0 0 24px rgba(255,206,79,0.6);
    overflow: visible;
    animation: avatarShattered 2.2s steps(10) infinite;
  }
  @keyframes avatarShattered {
    0%, 100% { filter: brightness(1) saturate(1); }
    33%      { filter: brightness(1.2) saturate(1.3); }
    66%      { filter: brightness(0.95) saturate(0.85); }
  }
  .avatar.frame-shattered::before {
    content: '💥';
    position: absolute;
    top: -10px; left: -10px;
    font-size: 16px;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
  }
  .avatar.frame-shattered.lg::before { top: -16px; left: -14px; font-size: 26px; }
  .avatar.frame-shattered.xl::before { top: -22px; left: -18px; font-size: 36px; }

  /* Frame rarity badge in profile picker */
  .frame-cell .rarity-badge {
    position: absolute;
    top: -6px; right: -6px;
    font-family: var(--px); font-size: 7px;
    padding: 3px 5px;
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    text-shadow: 1px 1px 0 #000;
    color:var(--ink);
    letter-spacing: 0.5px;
  }
  .rarity-badge.common    { background: #6b7280; }
  .rarity-badge.uncommon  { background: #10b981; }
  .rarity-badge.rare      { background: #3b82f6; }
  .rarity-badge.epic      { background: #a855f7; }
  .rarity-badge.legendary {
    background: linear-gradient(135deg, #ff3da6, #ffce4f, #7b5cff);
    background-size: 300% 300%;
    animation: legendaryShimmer 2.4s steps(12) infinite;
  }
  @keyframes legendaryShimmer {
    0%   { background-position: 0% 50%; }
    100% { background-position: 100% 50%; }
  }

  /* Title picker grid (profile) — sits next to the frame grid */
  .title-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
    padding: 8px 0;
  }
  .title-cell {
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    padding: 14px 10px; text-align: center;
    font-family: var(--px); font-size: 9px; color: var(--ink);
    letter-spacing: 0.5px; line-height: 1.4;
    cursor: pointer;
    transition: transform .06s;
    position: relative;
    word-break: break-word;
  }
  .title-cell:active { transform: translate(2px, 2px); }
  .title-cell.active {
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold);
    border-color: var(--gold);
    color: var(--gold);
  }
  .title-cell.locked { opacity: 0.45; cursor: not-allowed; filter: grayscale(0.6); }
  .title-cell .lock-tag {
    position: absolute; top: 4px; right: 4px;
    font-size: 11px;
  }

  /* Frame picker grid (modal + profile) */
  .frame-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
    padding: 8px 0;
  }
  .frame-cell {
    display: flex; flex-direction: column; align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 8px;
    background: var(--card); border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    cursor: pointer;
    transition: transform .06s;
    position: relative;
    min-height: 140px;
  }
  .frame-cell .avatar { width: 84px; height: 84px; margin-top: auto; }
  /* Smaller chibi in the frame-picker, lifted up so it sits inside the
     frame's painted cutout instead of clipping at the bottom edge. */
  .frame-cell .avatar img.chibi-inner { width: 50%; height: 50%; bottom: 18%; }
  .frame-cell:active { transform: translate(2px, 2px); }
  .frame-cell.active { box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 var(--gold); border-color: var(--gold); }
  .frame-cell.locked { opacity: 0.55; cursor: pointer; filter: grayscale(0.5); }
  .frame-cell.locked:hover { opacity: 0.85; filter: grayscale(0.2); }
  .frame-cell .price-tag {
    position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%);
    background: var(--card); border: 1px solid var(--gold);
    color: var(--gold); font-family: var(--px); font-size: 7.5px;
    padding: 2px 6px; letter-spacing: 0.5px;
    display: inline-flex; align-items: center; gap: 3px;
    white-space: nowrap;
    box-shadow: 1px 1px 0 #000;
  }
  .frame-cell .price-tag img { width: 9px; height: 9px; image-rendering: pixelated; }
  .frame-cell .lbl {
    font-family: var(--px); font-size: 7.5px;
    color: var(--ink); letter-spacing: 0.5px;
    text-align: center; line-height: 1.4;
    margin-top: 6px;
    /* Reserve space for two lines so labels like "GOBLIN TROPHY" don't
       push the avatar up while single-line labels leave it where it is.
       7.5px * 1.4 line-height * 2 lines ≈ 22px. */
    min-height: 22px;
  }
  .frame-cell.active .lbl { color: var(--gold); }
  .frame-cell .lock-tag {
    position: absolute; top: 4px; right: 4px;
    font-size: 11px;
  }

  /* ---------- Floating Action Button (chat) ---------- */
  .fab {
    position: fixed; right: 14px; bottom: 78px;
    width: 60px; height: 60px;
    background: var(--neon);
    border: 4px solid #000;
    box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255,61,166,0.6);
    display: flex; align-items: center; justify-content: center;
    font-size: 28px; cursor: pointer;
    z-index: 30;
    max-width: 480px;
    transition: transform .08s;
    animation: pulsePink 2s ease-in-out infinite;
  }
  body { position: relative; }
  /* Anchor FAB to the app column visually */
  @media (min-width: 480px) {
    .fab { right: calc(50% - 240px + 14px); }
  }
  .fab:active { transform: translate(2px, 2px); }
  /* Chat FAB — always-visible "ASK HOST" label so it reads as a button,
     not decoration. The label sits just left of the square FAB. */
  .chat-fab .fab-label {
    position: absolute;
    right: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    white-space: nowrap;
    background: var(--bg-1);
    border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    padding: 6px 9px;
    font-family: var(--px); font-size: 9px;
    color: var(--neon); letter-spacing: 1px;
    pointer-events: none;
  }
  /* Attention bounce after a failed step — layered on top of pulsePink
     (different property: transform vs box-shadow, so they don't fight). */
  @keyframes fabNudge {
    0%, 100% { transform: translateY(0); }
    20%      { transform: translateY(-13px); }
    40%      { transform: translateY(0); }
    62%      { transform: translateY(-7px); }
    82%      { transform: translateY(0); }
  }
  .fab.nudging { animation: pulsePink 2s ease-in-out infinite, fabNudge 1s ease-out 1; }
  /* One-time teaching tip flashed above the chat FAB on early fails. */
  .chat-fab-tip {
    position: fixed; z-index: 31;
    max-width: 210px;
    background: var(--bg-1);
    border: 3px solid #000;
    box-shadow: 4px 4px 0 #000;
    padding: 9px 11px;
    font-family: var(--term); font-size: 13px;
    color: var(--ink); line-height: 1.35;
    opacity: 0; transform: translateY(6px);
    transition: opacity 0.25s, transform 0.25s;
    pointer-events: none;
  }
  .chat-fab-tip.show { opacity: 1; transform: translateY(0); }
  /* Music toggle FAB — smaller, anchored to the LEFT side opposite the
     chat FAB so it doesn't fight the right-side stack. Quieter glow. */
  .fab.music-fab {
    right: auto; left: 14px;
    bottom: 78px;
    width: 46px; height: 46px;
    font-size: 22px;
    background: var(--card-2);
    box-shadow: 4px 4px 0 #000, 0 0 14px rgba(180,108,255,0.45);
    animation: none;
  }
  @media (min-width: 480px) {
    .fab.music-fab { left: calc(50% - 240px + 14px); right: auto; }
  }
  .fab .badge {
    position: absolute; top: -6px; right: -6px;
    background: var(--gold); color: #2a1500;
    border: 2px solid #000; padding: 2px 5px;
    font-family: var(--px); font-size: 8px;
    box-shadow: 2px 2px 0 #000;
  }
  /* Item drawer FAB sits LEFT of the chat FAB */
  .fab.item-fab {
    right: 84px;
    background: var(--gold);
    box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255,206,79,0.6);
    animation: pulseGold 2s ease-in-out infinite;
  }
  @keyframes pulseGold {
    0%, 100% { box-shadow: 4px 4px 0 #000, 0 0 14px rgba(255,206,79,0.5); }
    50%      { box-shadow: 4px 4px 0 #000, 0 0 22px rgba(255,206,79,0.85); }
  }
  @media (min-width: 480px) {
    .fab.item-fab { right: calc(50% - 240px + 84px); }
  }
  .fab.item-fab .badge {
    background: var(--neon-3);
    color: #000;
  }

  /* Item drawer (bottom sheet) */
  .item-drawer-bg {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.7);
    z-index: 110;
    display: flex; align-items: flex-end; justify-content: center;
    animation: fadeUp .15s ease;
  }
  .item-drawer {
    width: 100%; max-width: 480px;
    max-height: 75vh;
    background: var(--bg-1);
    border-top: 4px solid #000;
    box-shadow: inset 0 0 0 2px var(--gold), 0 -6px 0 #000;
    padding: 18px 16px 24px;
    overflow-y: auto;
    animation: slideUpFact .25s ease;
  }
  .item-drawer h3 {
    font-family: var(--px); font-size: 12px;
    color: var(--gold);
    letter-spacing: 1.5px;
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 #000;
    margin-bottom: 12px;
    text-align: center;
  }
  .item-drawer .empty {
    text-align: center;
    padding: 30px 14px;
    font-family: var(--term); font-size: 16px;
    color: var(--ink-faint);
  }
  .item-drawer .item-row {
    display: flex; align-items: center; gap: 12px;
    padding: 12px;
    background: #000;
    border: 3px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-3), 3px 3px 0 #000;
    margin-bottom: 10px;
    cursor: pointer;
    transition: transform .06s;
  }
  .item-drawer .item-row:active { transform: translate(2px, 2px); }
  .item-drawer .item-row .ic {
    flex-shrink: 0;
    font-size: 32px;
    text-shadow: 2px 2px 0 #000;
  }
  .item-drawer .item-row .meta { flex: 1; min-width: 0; }
  .item-drawer .item-row .meta .name {
    font-family: var(--px); font-size: 10px;
    color: var(--neon-3);
    letter-spacing: 1px;
    margin-bottom: 4px;
    text-shadow: 1px 1px 0 #000;
  }
  .item-drawer .item-row .meta .desc {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim);
    line-height: 1.3;
  }
  .item-drawer .item-row .qty {
    flex-shrink: 0;
    font-family: var(--px); font-size: 9px;
    color: var(--gold);
    background: #000;
    padding: 4px 8px;
    border: 2px solid var(--gold);
  }

  /* ---------- Chat sheet ---------- */
  .chat-bg {
    position: fixed; inset: 0;
    /* The chat sheet is bottom-anchored at 80vh, so the seam sits ~20vh from
       the top. The gradient reaches full opaque bg-1 (rgb 20,9,31) BEFORE
       the seam so the dim and the sheet meet at the exact same colour. */
    background: linear-gradient(
      to bottom,
      rgba(10, 6, 18, 0.65) 0%,
      rgba(20, 9, 31, 0.92) 16%,
      rgba(20, 9, 31, 1)    20%,
      rgba(20, 9, 31, 1)    100%
    );
    z-index: 90; display: flex; align-items: flex-end; justify-content: center;
    animation: fadeUp .15s ease;
  }
  .chat-sheet {
    width: 100%; max-width: 480px;
    background: var(--bg-1);
    border-top: 4px solid #000;
    box-shadow: inset 0 4px 0 var(--neon-2), 0 -8px 0 #000;
    height: 80vh;
    display: flex; flex-direction: column;
    animation: slideUp .25s ease;
  }
  @keyframes slideUp { from { transform: translateY(100%); } to { transform: none; } }
  .chat-head {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px;
    background: #0a0410;
    border-bottom: 3px solid #000;
  }
  .chat-head .av {
    width: 42px; height: 42px;
    background: var(--neon); border: 3px solid #000;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px; flex-shrink: 0;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4);
  }
  .chat-head .meta { flex: 1; }
  .chat-head .meta h3 {
    font-size: 12px; color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 #000;
    margin-bottom: 4px;
  }
  .chat-head .meta .status {
    font-family: var(--px); font-size: 8px; color: var(--neon-3);
    display: inline-flex; align-items: center; gap: 6px;
  }
  .chat-head .meta .status::before {
    content: ''; width: 8px; height: 8px; background: var(--neon-3);
    box-shadow: 0 0 6px var(--neon-3);
    animation: blink 1s steps(2) infinite;
  }
  .chat-head .closeX {
    background: var(--card); border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--px); font-size: 12px; cursor: pointer;
  }

  .chat-quick {
    display: flex; gap: 8px; padding: 10px 14px; overflow-x: auto;
    background: #0d061a; border-bottom: 3px solid #000;
    scrollbar-width: none;
  }
  .chat-quick::-webkit-scrollbar { display: none; }
  .chat-quick .q {
    flex-shrink: 0;
    padding: 7px 12px;
    font-family: var(--px); font-size: 9px;
    background: var(--card); border: 2px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 2px 2px 0 #000;
    color: var(--ink); cursor: pointer;
    transition: transform .06s;
  }
  .chat-quick .q:active { transform: translate(2px, 2px); }
  .chat-quick .q.danger { color: var(--gold); }

  .chat-thread {
    flex: 1; overflow-y: auto;
    padding: 14px;
    display: flex; flex-direction: column; gap: 10px;
    background:
      repeating-linear-gradient(0deg, rgba(255,255,255,0.015) 0 2px, transparent 2px 5px),
      var(--bg-1);
  }
  .chat-msg {
    max-width: 80%;
    padding: 10px 12px;
    font-family: var(--term); font-size: 17px;
    line-height: 1.3;
    border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    word-wrap: break-word;
    animation: pop .25s steps(4) both;
  }
  .chat-msg.host {
    align-self: flex-start;
    background: var(--card-2);
    color: var(--ink);
    border-left: 6px solid var(--neon);
  }
  .chat-msg.host .label {
    font-family: var(--px); font-size: 8px; color: var(--neon);
    margin-bottom: 6px; letter-spacing: 1.5px;
  }
  .chat-msg.user {
    align-self: flex-end;
    background: var(--neon-2);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
    border-right: 6px solid var(--gold);
  }
  .chat-msg.host.tag {
    background: rgba(0,230,195,0.08);
    border-left-color: var(--neon-3);
    font-family: var(--px); font-size: 9px;
    color: var(--neon-3); letter-spacing: 1px;
  }
  .chat-msg .typing {
    display: inline-flex; gap: 4px;
  }
  .chat-msg .typing span {
    width: 6px; height: 6px; background: var(--ink-faint);
    animation: blink 0.8s steps(2) infinite;
  }
  .chat-msg .typing span:nth-child(2) { animation-delay: 0.2s; }
  .chat-msg .typing span:nth-child(3) { animation-delay: 0.4s; }

  .chat-input-row {
    display: flex; gap: 8px; padding: 12px 14px;
    background: #0a0410; border-top: 3px solid #000;
  }
  .chat-input-row input {
    flex: 1; padding: 12px 14px;
    font-family: var(--term); font-size: 17px;
    background: var(--bg-1); color: var(--ink);
    border: 3px solid #000;
    box-shadow: inset 2px 2px 0 rgba(0,0,0,0.4);
    outline: none;
  }
  .chat-input-row button {
    background: var(--neon);
    color:var(--ink);
    border: 3px solid #000;
    box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 3px 3px 0 #000;
    font-family: var(--px); font-size: 11px;
    padding: 0 14px;
    cursor: pointer;
    text-shadow: 1px 1px 0 #000;
  }
  .chat-input-row button:active { transform: translate(2px, 2px); box-shadow: inset -2px -2px 0 rgba(0,0,0,0.4), 1px 1px 0 #000; }
  .chat-input-row button:disabled { opacity: 0.4; }

  /* ============================================================
     UNHINGED RUN — global theme override applied to <body> via the
     .unhinged-run class while a Gremlin run is active. Retunes the
     accent color from cyan/gold to pink/purple, rebrands the host
     bubble, and lowercases section titles for cursed-zine energy.
     ============================================================ */
  body.unhinged-run .top-bar .brand {
    color: var(--neon);
    text-shadow: 2px 2px 0 var(--neon-2), 4px 4px 0 rgba(0,0,0,0.6);
  }
  body.unhinged-run .step-head h2,
  body.unhinged-run .step-head .crumb {
    text-transform: lowercase;
  }
  body.unhinged-run .section-title {
    color: var(--neon);
    text-transform: lowercase;
    text-shadow: 1px 1px 0 var(--neon-2), 2px 2px 0 #000;
    letter-spacing: 1.5px;
  }
  body.unhinged-run .host-bubble {
    background: linear-gradient(160deg, #2a0848, #1a0530);
    border-color: var(--neon);
    box-shadow: inset 0 0 0 2px var(--neon), 4px 4px 0 #000;
  }
  body.unhinged-run .host-bubble .av {
    filter: drop-shadow(0 0 6px rgba(255,61,166,0.45));
    animation: unhingedShake 1s steps(8) infinite;
  }
  body.unhinged-run .host-bubble .text {
    color: var(--ink);
    font-style: italic;
  }
  body.unhinged-run .card h3 {
    color: var(--neon);
  }
  body.unhinged-run .step-banner,
  body.unhinged-run .step-banner-content {
    border-color: var(--neon) !important;
  }
  body.unhinged-run .reward-pill,
  body.unhinged-run .pill-sm {
    background: var(--neon);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }
  /* Photo proof tiles get a pink frame */
  body.unhinged-run .photo-gallery .gphoto {
    box-shadow: inset 0 0 0 2px var(--neon), 3px 3px 0 #000;
  }
  /* Recap card boss area glows pink */
  body.unhinged-run .recap-card {
    box-shadow: inset 0 0 0 2px var(--neon), 6px 6px 0 #000, 0 0 28px rgba(255,61,166,0.3);
  }
  body.unhinged-run .recap-card .badge {
    background: var(--neon);
    color:var(--ink);
    text-shadow: 1px 1px 0 #000;
  }
  body.unhinged-run .recap-card .boss-name {
    color: var(--neon);
    text-transform: lowercase;
    text-shadow: 2px 2px 0 var(--neon-2), 3px 3px 0 #000;
  }
  body.unhinged-run .recap-brand {
    color: var(--neon);
  }
  /* Toasts in unhinged mode get a pink underglow */
  body.unhinged-run #toast {
    box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255,61,166,0.4) !important;
    border-color: var(--neon) !important;
  }
  /* Boss reveal banner colors swap to pink/purple */
  body.unhinged-run .boss-banner {
    border-color: var(--neon) !important;
    box-shadow: inset 0 0 0 2px var(--neon), 6px 6px 0 #000 !important;
  }
  /* Step instr text leans italic + lowercase look */
  body.unhinged-run .step-instr {
    font-style: italic;
  }

  /* ============================================================
     MULTIPLAYER PHASE 1 — Party Lobby (added 2026-05-06)
     ============================================================ */
  .lobby-header {
    display: flex; align-items: center; gap: 12px; padding: 16px;
    border-bottom: 2px solid var(--line);
  }
  .lobby-header h2 { font-family: var(--px); font-size: 14px; color: var(--neon); flex: 1; text-align: center; }
  .lobby-header .back-btn {
    background: var(--card); color: var(--ink); border: 2px solid var(--line);
    padding: 8px 12px; font-family: var(--px); font-size: 9px; cursor: pointer;
    box-shadow: 3px 3px 0 #000;
  }
  .lobby-header .back-btn:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }

  .lobby-id-card {
    background: var(--card); border: 2px solid var(--line); margin: 16px;
    padding: 16px; box-shadow: 4px 4px 0 #000;
  }
  .lobby-id-card label {
    display: block; font-family: var(--px); font-size: 9px; color: var(--ink-dim);
    margin-bottom: 8px; margin-top: 12px;
  }
  .lobby-id-card label:first-child { margin-top: 0; }
  .lobby-id-card input[type="text"] {
    width: 100%; background: var(--bg-1); color: var(--ink);
    border: 2px solid var(--line); padding: 10px; font-family: var(--term);
    font-size: 20px; text-transform: uppercase;
  }
  .avatar-picker {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(40px, 1fr)); gap: 6px;
  }
  .avatar-pick {
    background: var(--bg-1); border: 2px solid var(--line); padding: 8px;
    font-size: 22px; cursor: pointer; aspect-ratio: 1;
    display: flex; align-items: center; justify-content: center;
  }
  .avatar-pick.sel { border-color: var(--neon); background: var(--card-2); box-shadow: inset 0 0 0 2px var(--neon-3); }

  .lobby-cta-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 0 16px;
  }
  .lobby-cta {
    background: var(--card); border: 3px solid var(--line);
    padding: 18px 14px; cursor: pointer; box-shadow: 5px 5px 0 #000;
    text-align: center; transition: transform 0.05s;
  }
  .lobby-cta:active { transform: translate(3px,3px); box-shadow: 2px 2px 0 #000; }
  .lobby-cta.create { border-color: var(--neon); }
  .lobby-cta.join { border-color: var(--neon-3); }
  .lobby-cta .ic { font-size: 38px; margin-bottom: 8px; }
  .mp-cta-ic { width: 80px; height: 80px; display: block; margin: 0 auto 8px; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; object-fit: contain; }
  .reconnect-card .rc-ic .mp-cta-ic { width: 32px; height: 32px; margin: 0; display: inline-block; vertical-align: middle; }
  .lobby-cta h3 { font-family: var(--px); font-size: 11px; margin-bottom: 6px; color: var(--ink); }
  .lobby-cta p { font-size: 14px; color: var(--ink-dim); margin-bottom: 10px; line-height: 1.2; }
  .lobby-cta input {
    width: 100%; background: var(--bg-1); color: var(--ink);
    border: 2px solid var(--line); padding: 8px; font-family: var(--px);
    font-size: 14px; text-align: center; text-transform: uppercase; letter-spacing: 4px;
  }

  .lobby-status {
    margin: 16px; padding: 12px; font-family: var(--term); font-size: 18px;
    color: var(--ink-dim); text-align: center; min-height: 22px;
  }
  .lobby-status.big { font-size: 22px; padding: 40px 16px; }
  .lobby-status.error { color: var(--danger); }

  /* Host preview that appears under the JOIN code input once the joiner
     types a 4-letter code. Deliberately small footprint — just enough to
     confirm "yes, this is the room I meant to join." */
  .join-preview { margin-top: 10px; min-height: 0; }
  .join-preview:empty { display: none; }
  .join-preview .jp-loading,
  .join-preview .jp-miss {
    font-family: var(--term); font-size: 12px; color: var(--ink-dim);
    padding: 8px 0; text-align: center;
  }
  .join-preview .jp-miss { color: var(--danger); }
  .join-preview .jp-card {
    display: flex; gap: 10px; align-items: center;
    padding: 8px; background: rgba(0,0,0,0.35);
    border: 2px solid var(--neon-3); box-shadow: 3px 3px 0 #000;
    animation: jpFadeIn .25s ease-out;
  }
  @keyframes jpFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .join-preview .jp-avatar {
    flex: 0 0 auto;
    width: 56px; height: 56px;
  }
  .join-preview .jp-avatar img,
  .join-preview .jp-avatar .chibi-inner {
    width: 100%; height: 100%; object-fit: cover;
  }
  .join-preview .jp-meta {
    flex: 1 1 auto; min-width: 0;
    font-family: var(--px); color: var(--ink);
  }
  .join-preview .jp-host {
    font-size: 9px; letter-spacing: 1px; color: var(--ink-dim);
    margin-bottom: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .join-preview .jp-host strong { color: var(--neon); font-size: 11px; }
  .join-preview .jp-row,
  .join-preview .jp-row2 {
    display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
    font-size: 8px; letter-spacing: 1px;
  }
  .join-preview .jp-row2 { margin-top: 4px; }
  .join-preview .jp-mode {
    padding: 2px 6px; background: var(--neon-3); color: #000;
    border: 1px solid #000;
  }
  .join-preview .jp-mode.pending { background: var(--ink-dim); color:var(--ink); }
  .join-preview .jp-mode.mode-coop       { background: #4ade80; }
  .join-preview .jp-mode.mode-compete    { background: var(--gold); }
  .join-preview .jp-mode.mode-chaos      { background: var(--neon); }
  .join-preview .jp-pc { color: var(--ink-dim); }
  .join-preview .jp-status { padding: 2px 6px; border: 1px solid #000; }
  .join-preview .jp-status.ok   { background: rgba(74, 222, 128, 0.25); color: #b8f5c9; }
  .join-preview .jp-status.busy { background: rgba(255, 91, 91, 0.25); color: #ffb8b8; }

  /* In-room lobby */
  .room-code-card {
    background: var(--card); border: 3px solid var(--neon); margin: 16px;
    padding: 18px; box-shadow: 5px 5px 0 #000; text-align: center;
  }
  .room-code-card label {
    font-family: var(--px); font-size: 9px; color: var(--ink-dim);
  }
  .room-code-big {
    font-family: var(--px); font-size: 48px; color: var(--neon);
    letter-spacing: 12px; margin: 12px 0; text-shadow: 0 0 8px var(--neon);
  }
  .copy-code {
    background: var(--neon-3); color: #000; border: 2px solid #000;
    padding: 8px 14px; font-family: var(--px); font-size: 10px; cursor: pointer;
    box-shadow: 3px 3px 0 #000;
  }
  .copy-code:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }
  .room-hint { font-size: 14px; color: var(--ink-dim); margin-top: 10px; }

  .players-card { background: var(--card); border: 2px solid var(--line); margin: 16px; padding: 14px; box-shadow: 4px 4px 0 #000; }
  .players-card h3 { font-family: var(--px); font-size: 11px; margin-bottom: 10px; }
  .players-grid {
    /* auto-fit so chips grow to fit names instead of cramming into 4 narrow cols.
       minmax(96px, 1fr) gives "Player One" room to sit on one line. */
    display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px;
  }
  .player-chip {
    background: var(--bg-1); border: 2px solid var(--line); padding: 8px 6px;
    text-align: center; position: relative; min-width: 0;
  }
  .player-chip.me { border-color: var(--neon-3); }
  .player-chip.host { border-color: var(--gold); }
  .player-chip.empty { opacity: 0.35; }
  /* Lobby player chip — overrides the legacy small-chip .av rule (line ~1539)
     which set a hard pink/neon background + 22px box. We want a clean
     emoji on the chip's own background. */
  .players-grid .player-chip .av {
    width: 44px;
    height: 44px;
    margin: 0 auto;
    background: transparent;
    border: none;
    box-shadow: none;
    text-shadow: none;
    font-size: 32px;
    display: flex; align-items: center; justify-content: center;
    line-height: 1;
    color: inherit;
    overflow: hidden;
    padding: 0;
  }
  .players-grid .player-chip .av .av-emoji {
    /* Native emoji glyphs ignore color:, but we use text-shadow as a soft
       per-player accent halo so each chip reads distinct at a glance. */
    text-shadow: 0 0 6px currentColor;
  }
  /* Empty slot placeholder — subtle pixel-glyph instead of the old "·". */
  .players-grid .player-chip.empty {
    border-style: dashed;
    border-color: var(--ink-faint);
    background: transparent;
  }
  .players-grid .player-chip.empty .av {
    font-family: var(--px);
    font-size: 16px;
    color: var(--ink-faint);
    text-shadow: none;
    opacity: 0.7;
  }
  .players-grid .player-chip.empty .nm {
    color: var(--ink-faint);
    font-size: 11px;
    letter-spacing: 1px;
  }
  .player-chip .nm {
    font-size: 14px;
    line-height: 1.15;
    margin-top: 4px;
    /* Only break truly unbreakable strings; clamp to two lines max with ellipsis. */
    overflow-wrap: break-word;
    word-break: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .player-chip .host-tag {
    position: absolute; top: -8px; right: -4px; background: var(--gold); color: #2a1500;
    font-family: var(--px); font-size: 7px; padding: 2px 4px; border: 1px solid #000;
  }

  /* Secret Traitor — modals shown at quest start (warning, role
     reveal) + accusation grid at recap. Heavy purple/black palette so
     the role reveal feels theatrical instead of UI. */
  .traitor-modal {
    background: linear-gradient(180deg, #1f0d3a 0%, #100620 100%);
    border: 3px solid #000;
    box-shadow:
      inset 0 0 0 2px var(--neon-2),
      6px 6px 0 #000,
      0 0 22px rgba(123,92,255,0.5);
    max-width: 360px;
    overflow: hidden;          /* clip the scaling icon so iOS doesn't flash the scrollbar */
  }
  .traitor-modal-villain {
    box-shadow:
      inset 0 0 0 2px var(--neon),
      6px 6px 0 #000,
      0 0 24px rgba(255,61,166,0.55);
  }
  .traitor-warn-ic, .traitor-reveal-ic {
    text-align: center;
    font-size: 56px;
    text-shadow: 3px 3px 0 #000;
    margin: 6px 0 6px;
    /* Opacity-only pulse — no transform, so iOS Safari doesn't see the
       scaled element overflow the modal and toggle a scrollbar. */
    animation: traitorIconPulse 1.6s ease-in-out infinite;
  }
  @keyframes traitorIconPulse {
    0%, 100% { opacity: 1;    filter: brightness(1); }
    50%      { opacity: 0.85; filter: brightness(1.2); }
  }
  /* Accusation pick grid. */
  .accusation-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
  .accusation-pick {
    display: flex; flex-direction: column; align-items: center;
    gap: 4px;
    padding: 12px 6px;
    background: var(--card-2);
    border: 2px solid #000;
    box-shadow: 3px 3px 0 #000;
    cursor: pointer;
    font-family: var(--term);
    color: var(--ink);
    transition: transform .06s, border-color .12s;
  }
  .accusation-pick:hover { border-color: var(--neon-2); }
  .accusation-pick:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
  .accusation-pick.chosen {
    border-color: var(--gold);
    background: rgba(255,206,79,0.12);
    box-shadow: 3px 3px 0 #000, 0 0 10px rgba(255,206,79,0.45);
  }
  .accusation-pick:disabled { cursor: not-allowed; opacity: 0.7; }
  .accusation-pick .acc-av { font-size: 28px; }
  .accusation-pick .acc-name { font-size: 13px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Recap traitor reveal panel — sits inside the recap card. */
  .traitor-recap {
    margin: 14px auto;
    padding: 12px 14px;
    background: linear-gradient(180deg, #2a0f43 0%, #1a0a2a 100%);
    border: 2px solid #000;
    box-shadow: inset 0 0 0 2px var(--neon-2), 4px 4px 0 #000;
    text-align: center;
  }
  .traitor-recap-head {
    font-family: var(--px); font-size: 9px;
    color: var(--neon-2); letter-spacing: 2px;
    margin-bottom: 6px;
  }
  .traitor-recap-name {
    font-family: var(--px); font-size: 14px;
    color: var(--gold);
    text-shadow: 2px 2px 0 var(--neon), 3px 3px 0 #000;
    display: flex; align-items: center; justify-content: center;
    gap: 8px;
  }
  .traitor-recap-av { font-size: 26px; }
  .traitor-recap-vote {
    margin-top: 10px;
    padding: 6px 10px;
    font-family: var(--term); font-size: 14px;
  }
  .traitor-recap-vote.correct { color: var(--neon-3); }
  .traitor-recap-vote.wrong { color: var(--danger); }
  .traitor-recap-betrays {
    margin-top: 6px;
    font-family: var(--term); font-size: 13px;
    color: var(--ink-faint);
  }

  /* Quest-screen BETRAY button (traitor only). Tucked into the action
     row alongside the reroll button so casual onlookers don't notice. */
  .betray-btn {
    background: linear-gradient(180deg, #2a0f43 0%, #1a0a2a 100%);
    color: var(--neon-2);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000, 0 0 6px rgba(123,92,255,0.4);
    padding: 6px 10px;
    font-family: var(--px); font-size: 9px; letter-spacing: 1px;
    cursor: pointer;
    transition: transform .06s;
  }
  .betray-btn:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
  .betray-btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* Floating "+Ns · 🦊 NAME" popup that flies up next to the timer
     when another coop player adds bonus time. */
  .coop-bonus-popup {
    position: absolute;
    transform: translate(-50%, 0);
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 10px;
    background: linear-gradient(180deg, #143a2c 0%, #0a1f17 100%);
    border: 2px solid var(--neon-3);
    box-shadow: 3px 3px 0 #000, 0 0 12px rgba(0,230,195,0.55);
    font-family: var(--term);
    color:var(--ink);
    z-index: 200;
    pointer-events: none;
    white-space: nowrap;
    animation: coopBonusFloat 2.4s ease-out forwards;
  }
  .coop-bonus-popup .coop-bonus-amt {
    font-family: var(--px); font-size: 12px; color: var(--neon-3);
    text-shadow: 1px 1px 0 #000;
  }
  .coop-bonus-popup .coop-bonus-av { font-size: 14px; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; flex-shrink: 0; }
  .coop-bonus-popup .coop-bonus-av .qmp-avatar-img { width: 100%; height: 100%; object-fit: contain; }
  .coop-bonus-popup .coop-bonus-nm { font-size: 14px; }
  @keyframes coopBonusFloat {
    0%   { opacity: 0; transform: translate(-50%, 4px); }
    14%  { opacity: 1; transform: translate(-50%, -4px); }
    72%  { opacity: 1; transform: translate(-50%, -28px); }
    100% { opacity: 0; transform: translate(-50%, -42px); }
  }

  /* Hold-to-reveal-role row sits between the photo wall button and
     the team progress strip on the quest screen — coop traitor mode only. */
  .traitor-quest-row {
    display: flex; gap: 8px; justify-content: center; align-items: center;
    margin: 8px 0;
  }
  .role-reveal-btn {
    flex: 1;
    background: linear-gradient(180deg, #2a0f43 0%, #1a0a2a 100%);
    color: var(--neon-2);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    padding: 8px 12px;
    font-family: var(--px); font-size: 9px; letter-spacing: 1px;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
  }
  .role-reveal-btn:active { cursor: grabbing; transform: translate(1px,1px); box-shadow: 1px 1px 0 #000; }

  /* Full-screen overlay shown WHILE the role-reveal button is held. */
  .role-overlay {
    position: fixed; inset: 0;
    z-index: 9000;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    pointer-events: none;
    animation: roleOverlayIn 220ms cubic-bezier(0.2, 0.85, 0.25, 1);
  }
  @keyframes roleOverlayIn {
    0%   { opacity: 0; transform: scale(0.92); }
    100% { opacity: 1; transform: scale(1); }
  }
  .role-overlay.traitor { background: radial-gradient(circle at center, rgba(255,61,166,0.6) 0%, rgba(0,0,0,0.95) 75%); }
  .role-overlay.party   { background: radial-gradient(circle at center, rgba(0,230,195,0.5) 0%, rgba(0,0,0,0.95) 75%); }
  .role-overlay-ic { font-size: 96px; text-shadow: 4px 4px 0 #000; margin-bottom: 12px; }
  .role-overlay-label {
    font-family: var(--px); font-size: 16px;
    color:var(--ink); text-shadow: 3px 3px 0 #000;
    letter-spacing: 2px; text-align: center; padding: 0 18px;
  }
  .role-overlay.traitor .role-overlay-label { color: var(--neon); }
  .role-overlay.party   .role-overlay-label { color: var(--neon-3); }
  .role-overlay-sub {
    font-family: var(--term); font-size: 16px;
    color: var(--ink); margin-top: 10px; text-align: center; padding: 0 18px;
    text-shadow: 2px 2px 0 #000;
  }

  /* Cinematic accusation reveal — full-screen takeover that animates
     the traitor's avatar in dramatically once everyone has voted. */
  .accusation-reveal {
    position: fixed; inset: 0;
    z-index: 9100;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    background: radial-gradient(circle at center, rgba(123,92,255,0.55) 0%, #0a0518 80%);
    animation: roleOverlayIn 360ms cubic-bezier(0.2, 0.85, 0.25, 1);
  }
  .accusation-reveal-pre {
    font-family: var(--px); font-size: 11px;
    color: var(--neon-2); letter-spacing: 4px;
    margin-bottom: 14px;
    text-shadow: 2px 2px 0 #000;
  }
  .accusation-reveal-av {
    font-size: 120px; text-shadow: 5px 5px 0 #000;
    animation: accReveal 1.4s cubic-bezier(0.2, 0.85, 0.25, 1) backwards;
  }
  @keyframes accReveal {
    0%   { transform: scale(0.2) rotate(-180deg); opacity: 0; }
    60%  { transform: scale(1.3)  rotate(20deg);  opacity: 1; }
    78%  { transform: scale(0.95) rotate(-8deg);  opacity: 1; }
    100% { transform: scale(1)    rotate(0);      opacity: 1; }
  }
  .accusation-reveal-name {
    font-family: var(--px); font-size: 22px;
    color: var(--gold);
    text-shadow: 3px 3px 0 var(--neon), 5px 5px 0 #000;
    margin-top: 18px;
    animation: accNameIn 0.4s ease-out 1s backwards;
  }
  @keyframes accNameIn {
    0%   { opacity: 0; transform: translateY(8px); }
    100% { opacity: 1; transform: translateY(0); }
  }
  .accusation-reveal-role {
    font-family: var(--term); font-size: 18px;
    color: var(--ink); margin-top: 12px;
    animation: accNameIn 0.4s ease-out 1.3s backwards;
    text-shadow: 2px 2px 0 #000;
  }
  .accusation-reveal-tally {
    font-family: var(--px); font-size: 9px;
    color: var(--ink-faint); letter-spacing: 1.5px;
    margin-top: 18px;
    animation: accNameIn 0.4s ease-out 1.6s backwards;
  }
  .accusation-bounty {
    font-family: var(--px); font-size: 10px;
    color: var(--gold); letter-spacing: 2px;
    margin-top: 14px;
    padding: 8px 14px;
    border: 2px solid var(--gold);
    background: rgba(255, 206, 79, 0.12);
    text-shadow: 2px 2px 0 #000;
    animation: accNameIn 0.4s ease-out 1.9s backwards;
  }
  .accusation-countdown { background: radial-gradient(circle at center, rgba(0,0,0,0.85) 0%, #0a0518 90%); }
  .accusation-countdown-label {
    font-family: var(--px); font-size: 11px;
    color: var(--neon-3); letter-spacing: 3px;
    margin-bottom: 18px;
    text-shadow: 2px 2px 0 #000;
  }
  .accusation-countdown-num {
    font-family: var(--px); font-size: 92px;
    color: var(--gold);
    text-shadow: 4px 4px 0 var(--neon-2), 6px 6px 0 #000;
    animation: accCountPulse 0.85s steps(8) both;
  }
  .accusation-countdown-num.pulse { animation: accCountPulse 0.85s steps(8) both; }
  @keyframes accCountPulse {
    0%   { transform: scale(0.6); opacity: 0; }
    25%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
  }

  /* Lobby Secret Traitor toggle (Co-op + 4+ players). Reuses the same
     visual language as .unhinged-toggle but with a purple/magenta
     accent so the two modes don't get confused. */
  .traitor-toggle {
    display: flex; align-items: center; gap: 12px;
    margin-top: 12px;
    padding: 10px 12px;
    background: var(--bg-1);
    border: 2px solid var(--line);
    box-shadow: 4px 4px 0 #000;
    cursor: pointer;
    transition: transform .06s, border-color .12s, background .12s;
  }
  .traitor-toggle:active { transform: translate(1px, 1px); }
  .traitor-toggle.on {
    background: linear-gradient(135deg, #2a0f43 0%, #45125f 100%);
    border-color: var(--neon-2);
    box-shadow: inset 0 0 0 2px rgba(123, 92, 255, 0.45), 4px 4px 0 #000, 0 0 16px rgba(123, 92, 255, 0.5);
  }
  .traitor-toggle .ic { font-size: 24px; flex-shrink: 0; }
  .traitor-toggle .meta { flex: 1; min-width: 0; }
  .traitor-toggle .meta h4 {
    font-family: var(--px); font-size: 11px;
    color: var(--ink); margin-bottom: 4px;
    letter-spacing: 1px;
  }
  .traitor-toggle.on .meta h4 { color: var(--neon-2); text-shadow: 0 0 6px rgba(123,92,255,0.6); }
  .traitor-toggle .meta p {
    font-family: var(--term); font-size: 13px;
    color: var(--ink-faint);
  }
  .traitor-toggle.on .meta p { color: var(--ink); }
  .traitor-toggle .switch {
    font-family: var(--px); font-size: 10px;
    padding: 6px 10px;
    background: var(--card-2);
    border: 2px solid var(--line);
    color: var(--ink-faint);
    flex-shrink: 0;
  }
  .traitor-toggle.on .switch {
    background: var(--neon-2);
    color:var(--ink);
    border-color: #000;
  }
  .traitor-toggle.guest-readonly {
    cursor: default; pointer-events: none;
    margin-top: 12px;
  }
  .traitor-toggle.guest-readonly:active { transform: none; }

  /* Drag-drop team picker (lobby, competitive 4+ even players). */
  .team-picker {
    margin-top: 12px;
    padding: 10px;
    background: var(--bg-1);
    border: 2px solid var(--line);
  }
  .team-picker-head {
    font-family: var(--px); font-size: 9px;
    color: var(--neon-3); letter-spacing: 1px;
    margin-bottom: 8px; text-align: center;
  }
  .team-picker-cols {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  }
  .team-col {
    border: 2px dashed var(--line);
    background: var(--card-2);
    padding: 8px;
    min-height: 100px;
    transition: border-color .12s, background .12s;
  }
  .team-col[data-team="A"] { border-color: rgba(0, 230, 195, 0.5); }
  .team-col[data-team="B"] { border-color: rgba(255, 61, 166, 0.5); }
  .team-col.drag-target {
    background: rgba(255, 255, 255, 0.06);
    border-style: solid;
  }
  .team-col-label {
    font-family: var(--px); font-size: 10px;
    color: var(--ink-dim); text-align: center;
    margin-bottom: 8px; letter-spacing: 1.5px;
  }
  .team-col[data-team="A"] .team-col-label { color: var(--neon-3); }
  .team-col[data-team="B"] .team-col-label { color: var(--neon); }
  .team-col-list { display: flex; flex-direction: column; gap: 4px; }
  .team-col-empty {
    color: var(--ink-faint); font-family: var(--term); font-size: 14px;
    text-align: center; padding: 12px 0;
  }
  .team-chip {
    display: flex; align-items: center; gap: 6px;
    padding: 5px 8px;
    background: var(--card);
    border: 2px solid #000;
    box-shadow: 2px 2px 0 #000;
    cursor: grab;
    user-select: none;
    transition: transform .08s;
  }
  .team-chip:active, .team-chip.dragging { cursor: grabbing; opacity: 0.6; }
  /* Highlight when another chip is hovering over this one — visual
     cue that dropping here will SWAP the two players' teams. */
  .team-chip.drag-swap-target {
    border-color: var(--gold);
    box-shadow: 2px 2px 0 #000, 0 0 10px rgba(255,206,79,0.6);
    transform: translateY(-1px);
  }
  .team-chip-av { font-size: 16px; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
  .team-chip-av .qmp-avatar-img { width: 100%; height: 100%; object-fit: contain; }
  .team-chip-name {
    font-family: var(--term); font-size: 13px; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  .mode-pick-card { background: var(--card); border: 2px solid var(--line); margin: 16px; padding: 14px; box-shadow: 4px 4px 0 #000; }
  .mode-pick-card h3 { font-family: var(--px); font-size: 11px; margin-bottom: 10px; }
  .mode-pick-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 14px; }
  .mode-pick { background: var(--bg-1); border: 2px solid var(--line); padding: 10px 4px; cursor: pointer; text-align: center; }
  .mode-pick.sel { border-color: var(--neon); box-shadow: inset 0 0 0 2px var(--neon-3); }
  .mode-pick .ic { font-size: 24px; line-height: 1; margin-bottom: 4px; }
  .mode-pick h4 { font-family: var(--px); font-size: 8px; margin: 6px 0 4px; }
  .mode-pick p { font-size: 12px; color: var(--ink-dim); line-height: 1.15; }
  .mode-pick.coop.sel { border-color: var(--neon-3); }
  .mode-pick.competitive.sel { border-color: var(--gold); }
  .mode-pick.chaos.sel { border-color: var(--danger); }
  .mode-pick.locked {
    opacity: 0.45;
    cursor: not-allowed;
    filter: grayscale(0.7);
  }
  .mode-pick.locked:active { transform: none; }

  .primary-btn {
    width: 100%; background: var(--neon); color:var(--ink); border: 3px solid #000;
    padding: 14px; font-family: var(--px); font-size: 12px; cursor: pointer;
    box-shadow: 5px 5px 0 #000;
  }
  .primary-btn:active { transform: translate(3px,3px); box-shadow: 2px 2px 0 #000; }
  .primary-btn.disabled { background: var(--card-2); color: var(--ink-faint); cursor: not-allowed; }
  .primary-btn.disabled:active { transform: none; box-shadow: 5px 5px 0 #000; }

  .guest-status { background: var(--card); border: 2px solid var(--line); margin: 16px; padding: 24px; text-align: center; box-shadow: 4px 4px 0 #000; }
  .guest-status .ic { font-size: 36px; margin-bottom: 10px; }
  .guest-status p { font-size: 18px; color: var(--ink-dim); }

  /* Phase 2c — Photo Wall (cross-player photo gallery) */
  .photo-wall-btn {
    width: 100%;
    background: var(--card-2); color: var(--ink);
    border: 2px solid var(--neon-3);
    padding: 10px; margin-bottom: 10px;
    font-family: var(--px); font-size: 10px; cursor: pointer;
    box-shadow: 3px 3px 0 #000;
  }
  .photo-wall-btn:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }
  .photo-wall-modal {
    position: fixed; inset: 0; z-index: 999;
    background: rgba(0,0,0,0.85);
    display: flex; align-items: flex-start; justify-content: center;
    padding: 24px 16px; overflow-y: auto;
  }
  .pw-content {
    background: var(--card); border: 3px solid var(--neon-3);
    box-shadow: 6px 6px 0 #000;
    max-width: 720px; width: 100%; padding: 14px;
  }
  .pw-header {
    display: flex; align-items: center; justify-content: space-between;
    border-bottom: 2px solid var(--line); padding-bottom: 10px; margin-bottom: 12px;
  }
  .pw-header h3 { font-family: var(--px); font-size: 12px; color: var(--neon-3); }
  .pw-close {
    background: var(--card-2); color: var(--ink);
    border: 2px solid var(--line); padding: 6px 10px;
    font-family: var(--px); font-size: 10px; cursor: pointer;
  }
  .pw-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px;
  }
  .pw-item {
    background: var(--bg-1); border: 2px solid var(--line);
    aspect-ratio: 1; position: relative; overflow: hidden;
  }
  .pw-item img { width: 100%; height: 100%; object-fit: cover; image-rendering: auto; }
  .pw-item .pw-meta {
    position: absolute; bottom: 0; left: 0; right: 0;
    background: rgba(0,0,0,0.75); color: var(--ink);
    font-size: 12px; padding: 4px 6px;
    line-height: 1.2;
  }
  .pw-empty {
    grid-column: 1 / -1;
    text-align: center; color: var(--ink-faint);
    padding: 30px; font-size: 16px;
  }
  .pw-item:active img { opacity: 0.7; }
  .pw-item .pw-caption {
    position: absolute; left: 0; right: 0;
    bottom: 22px;
    padding: 4px 6px;
    background: rgba(0,0,0,0.55);
    color: #ffe98a;
    font-family: var(--term); font-size: 12px; font-style: italic;
    line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }

  /* Filter chip rail above the photo grid. Horizontally scrolls when too
     many players are in the room — vertical stacking would push the grid
     below the fold. */
  .pw-filter-row {
    display: flex; gap: 6px;
    padding: 0 0 10px 0;
    margin-bottom: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .pw-filter-row::-webkit-scrollbar { height: 6px; }
  .pw-filter-row::-webkit-scrollbar-thumb { background: var(--neon-3); }
  .pw-filter-row .pw-chip {
    flex: 0 0 auto;
    background: var(--card); color: var(--ink);
    border: 2px solid var(--line);
    padding: 6px 10px;
    font-family: var(--px); font-size: 9px; letter-spacing: 1px;
    cursor: pointer;
    box-shadow: 2px 2px 0 #000;
    white-space: nowrap;
  }
  .pw-filter-row .pw-chip.on {
    background: var(--gold); color: #2a1500;
    border-color: #000;
    box-shadow: 2px 2px 0 #000, 0 0 8px rgba(245, 194, 66, 0.5);
  }
  .pw-filter-row .pw-chip.me { border-color: var(--neon); }

  /* Expanded single-photo viewer */
  .photo-expanded-modal {
    position: fixed; inset: 0; z-index: 1000;
    background: rgba(0,0,0,0.96);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 12px;
  }
  .pe-stage {
    flex: 1 1 auto;
    width: 100%;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
  }
  .pe-stage img {
    max-width: 100%; max-height: 100%;
    object-fit: contain;
    box-shadow: 6px 6px 0 #000;
    border: 3px solid var(--neon-3);
    image-rendering: auto;
  }
  .pe-meta {
    flex: 0 0 auto;
    text-align: center;
    background: var(--card); border: 2px solid var(--line);
    padding: 8px 14px; margin-top: 12px;
    box-shadow: 4px 4px 0 #000;
  }
  .pe-name { font-family: var(--px); font-size: 11px; color: var(--ink); }
  .pe-step { font-family: var(--term); font-size: 16px; color: var(--ink-dim); margin-top: 3px; }
  .pe-caption {
    font-family: var(--term); font-style: italic;
    color: #ffe98a; font-size: 16px; line-height: 1.3;
    margin-bottom: 8px;
    max-width: 540px;
  }
  .pe-caption-btn {
    margin-top: 8px;
    background: var(--card); color: var(--ink);
    border: 2px solid var(--neon-3);
    padding: 6px 12px;
    font-family: var(--px); font-size: 10px; letter-spacing: 1px;
    cursor: pointer; box-shadow: 2px 2px 0 #000;
  }
  .pe-caption-btn:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }
  .pe-close {
    position: absolute; top: 14px; right: 14px;
    background: var(--card); color: var(--ink);
    border: 2px solid var(--neon); padding: 8px 12px;
    font-family: var(--px); font-size: 12px; cursor: pointer;
    box-shadow: 3px 3px 0 #000;
  }
  .pe-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    background: var(--card); color: var(--ink);
    border: 2px solid var(--line); padding: 14px 16px;
    font-family: var(--px); font-size: 22px; cursor: pointer;
    box-shadow: 3px 3px 0 #000;
  }
  .pe-nav.prev { left: 12px; }
  .pe-nav.next { right: 12px; }
  .pe-nav:active { transform: translateY(-50%) translate(2px, 2px); box-shadow: 1px 1px 0 #000; }

  /* Phase 4 — Sabotage UI */
  .sab-fab {
    /* Stacked directly above the chat FAB (which sits at right:14px / bottom:78px,
       60×60). 78 + 60 + 10gap = 148. Same anchor logic on desktop. */
    position: fixed; right: 14px; bottom: 148px;
    width: 60px; height: 60px;
    background: var(--danger); color:var(--ink);
    border: 4px solid #000; box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255,87,100,0.55);
    font-size: 28px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    z-index: 30;
    text-shadow: 1px 1px 0 #000;
    animation: sabFabPulse 2.4s ease-in-out infinite;
  }
  @media (min-width: 480px) {
    .sab-fab { right: calc(50% - 240px + 14px); }
  }
  .sab-fab:active { transform: translate(2px,2px); box-shadow: 2px 2px 0 #000; }
  .sab-fab .badge {
    position: absolute; top: -6px; right: -6px;
    background: var(--gold); color: #2a1500;
    font-family: var(--px); font-size: 9px;
    padding: 2px 5px; border: 2px solid #000;
  }
  /* Cooldown state — desaturated, no glow, badge swaps to a cyan timer. */
  .sab-fab.cooling {
    filter: grayscale(0.65);
    box-shadow: 4px 4px 0 #000;
    animation: none;
    cursor: not-allowed;
  }
  .sab-fab.cooling .badge {
    background: var(--neon-3); color: #0a2820;
    animation: sabCooldownPulse 1s ease-in-out infinite;
  }
  @keyframes sabCooldownPulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.08); }
  }
  @keyframes sabFabPulse {
    0%,100% { box-shadow: 4px 4px 0 #000; }
    50%     { box-shadow: 4px 4px 0 #000, 0 0 18px rgba(255,87,100,0.6); }
  }
  .sab-modal {
    position: fixed; inset: 0; z-index: 800;
    background: rgba(0,0,0,0.88);
    overflow-y: auto;
    padding: 28px 16px;
  }
  .sab-content {
    max-width: 480px; margin: 0 auto;
    background: var(--card); border: 3px solid var(--danger);
    box-shadow: 6px 6px 0 #000;
    padding: 16px;
  }
  .sab-head {
    display: flex; justify-content: space-between; align-items: center;
    border-bottom: 2px solid var(--line); padding-bottom: 10px; margin-bottom: 12px;
  }
  .sab-head h3 { font-family: var(--px); font-size: 12px; color: var(--danger); letter-spacing: 2px; }
  .sab-charges {
    font-family: var(--px); font-size: 9px; color: var(--gold);
    background: var(--bg-1); padding: 6px 10px; border: 2px solid var(--line);
  }
  .sab-close {
    background: var(--card-2); border: 2px solid var(--line);
    color: var(--ink); padding: 6px 10px;
    font-family: var(--px); font-size: 10px; cursor: pointer;
  }
  .sab-list {
    display: grid; gap: 10px;
  }
  .sab-row {
    background: var(--bg-1); border: 2px solid var(--line);
    padding: 12px; cursor: pointer;
    transition: transform .05s;
    box-shadow: 3px 3px 0 #000;
  }
  .sab-row:active { transform: translate(2px,2px); box-shadow: 1px 1px 0 #000; }
  .sab-row.disabled { opacity: 0.45; cursor: not-allowed; filter: grayscale(0.6); }
  .sab-row.disabled:active { transform: none; box-shadow: 3px 3px 0 #000; }
  .sab-row .head {
    display: flex; align-items: center; gap: 10px; margin-bottom: 4px;
  }
  .sab-row .ic { font-size: 24px; text-shadow: 2px 2px 0 #000; }
  .sab-row .sab-target-pic {
    width: 36px; height: 36px;
    object-fit: cover;
    border: 2px solid var(--neon-3);
    box-shadow: 2px 2px 0 #000;
    image-rendering: auto;
    flex-shrink: 0;
  }
  .sab-row .nm { font-family: var(--px); font-size: 10px; color: var(--ink); letter-spacing: 1px; }
  .sab-row .cost {
    margin-left: auto;
    font-family: var(--px); font-size: 8px; color: var(--gold);
    background: rgba(255,206,79,0.1); padding: 3px 6px; border: 1px solid var(--gold);
  }
  .sab-row .desc { font-family: var(--term); font-size: 14px; color: var(--ink-dim); line-height: 1.3; }

  /* Sabotage effect overlays — applied on the target client */
  .sab-blind-overlay {
    position: fixed; inset: 0; z-index: 9000;
    background: #000;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    color: var(--danger);
    text-align: center;
    pointer-events: all;
    animation: sabBlindFade 0.3s ease-out;
  }
  .sab-blind-overlay .ic { font-size: 80px; margin-bottom: 18px; animation: sabBlindShake 0.4s ease-in-out infinite; }
  .sab-blind-overlay h2 { font-family: var(--px); font-size: 14px; color: var(--danger); letter-spacing: 3px; margin-bottom: 10px; }
  .sab-blind-overlay p { font-family: var(--term); font-size: 18px; color: var(--ink); }
  .sab-blind-overlay .countdown { font-family: var(--px); font-size: 20px; color: var(--gold); margin-top: 18px; }
  @keyframes sabBlindFade {
    0% { opacity: 0; }
    100% { opacity: 1; }
  }
  @keyframes sabBlindShake {
    0%,100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
  }

  body.sab-muted button:not(.sab-immune),
  body.sab-muted [data-shoot]:not(.sab-immune),
  body.sab-muted [data-arm]:not(.sab-immune),
  body.sab-muted [data-judge]:not(.sab-immune),
  body.sab-muted [data-complete]:not(.sab-immune),
  body.sab-muted [data-vote]:not(.sab-immune) {
    pointer-events: none;
    opacity: 0.4;
    cursor: not-allowed;
  }
  body.sab-muted::after {
    /* Full-screen dim overlay + centered MUTED label. Covers everything
       so the player can see at a glance their inputs are dead. */
    content: '🔇 MUTED';
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.62);
    display: flex; align-items: center; justify-content: center;
    font-family: var(--px); font-size: 24px;
    color: var(--danger); text-shadow: 3px 3px 0 #000;
    letter-spacing: 4px;
    z-index: 8500; pointer-events: none;
    animation: sabMuteBlink 0.6s steps(2) infinite;
  }
  @keyframes sabMuteBlink {
    0%,100% { opacity: 0.85; }
    50%     { opacity: 1; }
  }

  /* Team chip in the team-progress strip */
  .team-tag {
    display: inline-block; margin-left: 6px;
    font-family: var(--px); font-size: 7px;
    padding: 2px 5px; border: 1px solid #000;
    letter-spacing: 1px;
  }
  .team-tag.team-A { background: var(--neon-3); color: #0a2820; }
  .team-tag.team-B { background: var(--gold); color: #2a1500; }
  .team-tag.team-C { background: var(--neon-2); color:var(--ink); text-shadow: 1px 1px 0 #000; }
  .team-tag.team-D { background: var(--danger); color:var(--ink); text-shadow: 1px 1px 0 #000; }

  /* Mini-game gate */
  .mg-modal {
    position: fixed; inset: 0; z-index: 9500;
    background: rgba(0,0,0,0.92);
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
  }
  .mg-content {
    background: var(--card); border: 4px solid var(--danger);
    box-shadow: 6px 6px 0 #000;
    padding: 18px;
    width: min(420px, 95vw);
    text-align: center;
  }
  .mg-content h3 {
    font-family: var(--px); font-size: 14px;
    color: var(--danger); letter-spacing: 2px; margin-bottom: 8px;
  }
  .mg-content p {
    font-family: var(--term); font-size: 16px;
    color: var(--ink-dim); margin-bottom: 14px;
  }
  .mg-grid {
    position: relative; height: 280px;
    background: var(--bg-1); border: 2px solid var(--line);
    margin: 0 auto 14px;
    overflow: hidden;
  }
  .mg-circle {
    position: absolute;
    width: 56px; height: 56px;
    border-radius: 0;
    background: var(--neon-3); color: #0a2820;
    border: 3px solid #000;
    box-shadow: 3px 3px 0 #000;
    font-family: var(--px); font-size: 18px;
    cursor: pointer;
    user-select: none;
    transition: transform 0.1s, opacity 0.2s;
  }
  .mg-circle.done {
    background: var(--card-2); color: var(--ink-faint);
    pointer-events: none; opacity: 0.4;
    transform: scale(0.8);
  }
  .mg-circle.next { animation: mgPulse 0.7s ease-in-out infinite; }
  @keyframes mgPulse {
    0%,100% { transform: scale(1); box-shadow: 3px 3px 0 #000; }
    50%     { transform: scale(1.08); box-shadow: 3px 3px 0 #000, 0 0 14px var(--neon-3); }
  }
  .mg-timer {
    font-family: var(--px); font-size: 11px;
    color: var(--gold); letter-spacing: 2px;
    margin-bottom: 6px;
  }
  .mg-status {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim); min-height: 18px; margin-bottom: 10px;
  }
  .mg-cancel {
    background: var(--card-2); border: 2px solid var(--line);
    color: var(--ink); padding: 8px 14px;
    font-family: var(--px); font-size: 10px; cursor: pointer;
  }

  /* Maze chase mini-game */
  .mg-maze {
    display: grid; grid-template-columns: repeat(7, 1fr);
    gap: 2px; background: #000;
    padding: 4px; border: 2px solid var(--line);
    margin: 0 auto 12px; max-width: 320px;
  }
  .mg-maze .mg-cell {
    aspect-ratio: 1;
    background: var(--bg-1);
    display: flex; align-items: center; justify-content: center;
    position: relative;
    font-size: 18px;
    cursor: default;
    user-select: none;
  }
  .mg-maze .mg-cell.wall {
    background: #1a0a0a;
    background-image: repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0 3px, transparent 3px 6px);
  }
  .mg-maze .mg-cell.exit {
    background: var(--neon-3);
    box-shadow: inset 0 0 0 2px var(--gold);
  }
  /* Player cell — colored to match the player's avatar (set via inline
     --mg-me-color) + a slower breathing pulse so the player can spot
     themselves at a glance. */
  .mg-maze .mg-cell.me {
    background: rgba(180, 108, 255, 0.18);
    box-shadow:
      inset 0 0 0 2px var(--neon-3),
      0 0 12px var(--neon-3);
    animation: mgMePulse 1.1s ease-in-out infinite;
  }
  @keyframes mgMePulse {
    0%, 100% { transform: scale(1);    filter: brightness(1);    }
    50%      { transform: scale(1.05); filter: brightness(1.45); }
  }
  /* Enemy cell — always red regardless of target avatar, faster pulse
     so it visibly menaces the player. */
  .mg-maze .mg-cell.enemy {
    background: rgba(255, 87, 100, 0.22);
    box-shadow:
      inset 0 0 0 2px #ff5764,
      0 0 14px #ff5764;
    animation: mgEnemyPulse 0.6s ease-in-out infinite;
  }
  @keyframes mgEnemyPulse {
    0%, 100% { transform: scale(1);    filter: brightness(1);    }
    50%      { transform: scale(1.08); filter: brightness(1.55); }
  }
  .mg-maze .mg-cell.reachable {
    background: var(--card-2);
    cursor: pointer;
  }
  .mg-maze .mg-cell.reachable:active {
    background: var(--neon-3);
  }
  .mg-maze .mg-cell .mg-icon svg {
    image-rendering: pixelated;
  }

  /* Toast for incoming sabotage hits (fades in, sits, fades out) */
  .sab-hit-toast .sab-hit-pic {
    width: 32px; height: 32px;
    object-fit: cover;
    border: 2px solid var(--danger);
    vertical-align: middle;
    margin-right: 6px;
    image-rendering: auto;
  }
  .sab-hit-toast .sab-hit-emoji {
    font-size: 24px;
    margin-right: 6px;
    vertical-align: middle;
  }
  .sab-hit-toast {
    position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
    background: var(--bg-1); border: 3px solid var(--danger);
    color: var(--ink); padding: 10px 16px;
    font-family: var(--term); font-size: 16px;
    box-shadow: 4px 4px 0 #000;
    z-index: 9001;
    animation: sabHitIn 0.3s ease-out;
  }
  @keyframes sabHitIn {
    0% { opacity: 0; transform: translate(-50%, -20px); }
    100% { opacity: 1; transform: translate(-50%, 0); }
  }

  /* Co-op "I finished, waiting for others" panel on the quest screen */
  .coop-wait-panel {
    background: var(--card);
    border: 3px solid var(--neon-3);
    box-shadow: 5px 5px 0 #000;
    padding: 18px 16px; margin: 0 0 14px;
    text-align: center;
  }
  .coop-wait-panel h3 {
    font-family: var(--px); font-size: 12px;
    color: var(--neon-3); letter-spacing: 2px;
    margin-bottom: 8px;
  }
  .coop-wait-panel .all-good { color: var(--gold); }
  .coop-wait-panel p {
    font-size: 16px; color: var(--ink-dim);
    margin-bottom: 14px;
  }
  .coop-wait-list {
    font-family: var(--term); font-size: 15px;
    color: var(--ink-dim);
    text-align: left;
    margin: 0 auto 14px; max-width: 280px;
  }
  .coop-wait-list .row {
    display: flex; justify-content: space-between;
    padding: 3px 0;
    border-bottom: 1px dashed var(--line);
  }
  .coop-wait-list .row:last-child { border-bottom: none; }
  .coop-wait-list .row.done { color: var(--neon-3); }

  /* Generating screen — full-screen wait while AI / local builders run */
  .gen-screen {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    min-height: 70vh; text-align: center;
    padding: 0 24px;
  }
  .gen-icon {
    font-size: 80px;
    text-shadow: 5px 5px 0 #000;
    animation: genBob 1.4s ease-in-out infinite;
    margin-bottom: 22px;
    image-rendering: pixelated;
  }
  @keyframes genBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-14px); }
  }
  /* Animated per-style/story loading character — a 4-frame sprite loop
     (load_<key>_0..3.png) frame-swapped in JS. */
  .gen-anim-img {
    height: 150px; width: auto;
    image-rendering: pixelated;
    display: block; margin: 0 auto 22px;
    filter: drop-shadow(0 6px 10px rgba(0,0,0,0.55));
  }
  /* Gentle hover-bob for floating characters (sci-fi astronaut etc.) —
     layered on top of the drawn sprite loop. */
  @keyframes genFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-14px); }
  }
  .gen-anim-img.gen-anim-float { animation: genFloat 2.4s ease-in-out infinite; }
  .gen-title {
    font-family: var(--px); font-size: 16px;
    color: var(--neon); letter-spacing: 3px;
    margin-bottom: 14px;
    text-shadow: 3px 3px 0 #000;
  }
  .gen-status {
    font-family: var(--term); font-size: 20px;
    color: var(--ink-dim);
    min-height: 28px;
  }
  .gen-dots::after {
    display: inline-block;
    content: '';
    animation: genDots 1.6s steps(4) infinite;
    text-align: left;
    width: 1.5em;
  }
  @keyframes genDots {
    0%   { content: ''; }
    25%  { content: '.'; }
    50%  { content: '..'; }
    75%  { content: '...'; }
    100% { content: ''; }
  }
  /* Elapsed-time counter on the generating screen. Tiny, monospace,
     so the player can see the timer literally ticking — proves the
     screen isn't frozen even if generation takes 30+ seconds. */
  .gen-timer {
    margin-top: 14px;
    font-family: var(--px); font-size: 10px;
    color: var(--ink-dim); letter-spacing: 2px;
    opacity: 0.85;
  }
  .gen-timer.warn { color: var(--gold); }
  .gen-timer.late { color: var(--danger); }
  /* Escalating wait-quip line. Hidden under 5s (no need to apologize
     for a fast load) and only mounts once we cross the 5s threshold. */
  .gen-waitline {
    margin-top: 10px; padding: 8px 14px;
    font-family: var(--term); font-size: 15px;
    color: var(--neon);
    max-width: min(420px, 84vw);
    line-height: 1.4; text-align: center;
    opacity: 0;
    transition: opacity 0.35s ease-out;
  }
  .gen-waitline.show { opacity: 1; }
  .gen-waitline.warn { color: var(--gold); }
  .gen-waitline.late { color: var(--danger); }
  .gen-bar {
    margin-top: 30px;
    height: 8px; width: min(280px, 70vw);
    background: var(--card-2);
    border: 2px solid var(--line);
    overflow: hidden;
    position: relative;
  }
  .gen-bar::after {
    content: '';
    position: absolute; top: 0; bottom: 0;
    width: 30%;
    background: var(--neon-3);
    animation: genBar 1.6s linear infinite;
  }
  @keyframes genBar {
    0%   { left: -30%; }
    100% { left: 100%; }
  }
  .gen-hint {
    margin-top: 30px; padding: 14px 18px;
    background: linear-gradient(160deg, var(--card), var(--bg-1));
    border: 2px dashed var(--neon-3);
    font-family: var(--term); font-size: 17px;
    color: var(--ink); max-width: min(440px, 86vw);
    line-height: 1.4; text-align: center;
    box-shadow: 4px 4px 0 #000, inset 0 0 18px rgba(0,230,195,0.08);
    position: relative;
    /* Slide-in + glow pulse on first appearance */
    animation: hintEnter 0.55s cubic-bezier(.2,.8,.2,1) both, hintGlow 2.4s ease-in-out infinite 0.6s;
  }
  .gen-hint-ic {
    width: 28px; height: 28px;
    object-fit: contain;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    display: inline-block;
    vertical-align: middle;
    margin-right: 6px;
    margin-top: -2px;
    filter: drop-shadow(0 0 6px rgba(255,206,79,0.55));
  }
  .gen-hint::before {
    content: '▶ HINT';
    position: absolute; top: -10px; left: 12px;
    background: var(--bg-0); padding: 2px 8px;
    font-family: var(--px); font-size: 8px; letter-spacing: 2px;
    color: var(--neon-3); border: 2px dashed var(--neon-3);
  }
  @keyframes hintEnter {
    0%   { opacity: 0; transform: translateY(14px) scale(0.96); filter: blur(2px); }
    60%  { filter: blur(0); }
    100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
  }
  @keyframes hintGlow {
    0%, 100% { box-shadow: 4px 4px 0 #000, inset 0 0 18px rgba(0,230,195,0.08); }
    50%      { box-shadow: 4px 4px 0 #000, inset 0 0 30px rgba(0,230,195,0.22); }
  }

  /* Phase 2b/d — Team progress strip + presence dots */
  .team-progress {
    background: var(--card); border: 2px solid var(--line);
    margin-bottom: 14px; padding: 10px 12px;
    box-shadow: 4px 4px 0 #000;
  }
  /* Inlined finish banner — used to be its own .coop-wait-panel; now
     collapsed inside the team progress card so they read as one unit. */
  .team-progress-finished {
    margin-top: 12px;
    padding: 10px 12px;
    background: var(--bg-1);
    border: 2px solid var(--neon-3);
    text-align: center;
  }
  .team-progress-finished.all-done {
    border-color: var(--gold);
    background: rgba(255, 206, 79, 0.08);
  }
  .tp-finished-head {
    font-family: var(--px); font-size: 11px;
    color: var(--neon-3);
    letter-spacing: 1.5px; margin-bottom: 6px;
  }
  .team-progress-finished.all-done .tp-finished-head { color: var(--gold); }
  .tp-finished-sub {
    font-family: var(--term); font-size: 14px;
    color: var(--ink-dim); margin-bottom: 10px;
  }
  .tp-finished-waiting {
    font-family: var(--px); font-size: 9px;
    color: var(--ink-faint);
    padding: 8px;
    background: var(--card-2);
    border: 2px solid var(--line);
    letter-spacing: 1px;
  }
  .team-progress-finished button.primary {
    width: 100%;
  }
  .team-progress .tp-head {
    font-family: var(--px); font-size: 9px;
    color: var(--ink-dim); margin-bottom: 8px; letter-spacing: 1px;
  }
  .tp-row {
    display: grid;
    grid-template-columns: 24px 1fr auto auto;
    align-items: center; gap: 8px;
    padding: 4px 0; font-size: 14px;
  }
  .tp-row.me { color: var(--neon-3); }
  .tp-row.offline { opacity: 0.5; }
  .tp-row .av { font-size: 18px; }
  .tp-row .nm {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .tp-row .bar {
    font-family: var(--term); font-size: 14px;
    color: var(--neon-3); letter-spacing: 1px;
  }
  .tp-row .ct {
    font-family: var(--px); font-size: 9px; color: var(--ink-dim);
    min-width: 28px; text-align: right;
  }
  .presence-dot {
    display: inline-block; width: 8px; height: 8px;
    border-radius: 0;       /* pixel square, not round */
    background: var(--ink-faint);
    box-shadow: 0 0 4px rgba(0,0,0,0.5);
    margin-right: 4px; vertical-align: middle;
  }
  .presence-dot.online { background: var(--neon-3); }
  .player-chip.offline { opacity: 0.55; }

  /* MP Win / Loss result screens */
  .mp-result {
    text-align: center; padding: 36px 18px;
  }
  .mp-result .badge {
    font-family: var(--px); font-size: 26px;
    padding: 16px 24px; display: inline-block;
    border: 4px solid #000; box-shadow: 8px 8px 0 #000;
    margin: 12px 0 22px;
    letter-spacing: 4px;
  }
  .mp-result.win .badge {
    background: var(--gold); color: #2a1500;
    text-shadow: 1px 1px 0 rgba(255,255,255,0.6);
    animation: mpWinPulse 1.4s ease-in-out infinite;
  }
  .mp-result.loss .badge {
    background: var(--danger); color:var(--ink);
    text-shadow: 2px 2px 0 #000;
  }
  @keyframes mpWinPulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.03); }
  }
  .mp-result .ic {
    font-size: 84px; text-shadow: 4px 4px 0 #000;
    margin-bottom: 8px;
  }
  .mp-result h2 {
    font-family: var(--px); font-size: 16px;
    color: var(--ink); margin-bottom: 12px;
  }
  .mp-result p {
    font-size: 18px; color: var(--ink-dim);
    margin-bottom: 20px; line-height: 1.4;
  }
  .mp-result .winner-card {
    background: var(--card); border: 3px solid var(--gold);
    padding: 18px; margin: 18px auto; max-width: 320px;
    box-shadow: 5px 5px 0 #000;
  }
  .mp-result .winner-card .av {
    font-size: 48px; margin-bottom: 6px;
  }
  .mp-result .winner-card .nm {
    font-family: var(--px); font-size: 12px; color: var(--gold);
    letter-spacing: 2px;
  }
  .mp-chest {
    background: var(--card); border: 3px solid var(--neon-3);
    box-shadow: 5px 5px 0 #000;
    padding: 14px 16px; margin: 16px auto 0;
    max-width: 360px;
  }
  .mp-chest.win-chest { border-color: var(--gold); }
  .mp-chest.loss-chest { border-color: var(--neon-2); opacity: 0.92; }
  .mp-chest .chest-ic { font-size: 44px; text-shadow: 3px 3px 0 #000; margin-bottom: 6px; }
  .mp-chest .chest-label {
    font-family: var(--px); font-size: 10px; letter-spacing: 2px;
    color: var(--ink); margin-bottom: 12px;
  }
  .mp-chest .chest-grid {
    display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px;
    margin-bottom: 10px;
  }
  .mp-chest .chest-cell {
    background: var(--bg-1); border: 2px solid var(--line);
    padding: 8px 4px;
  }
  .mp-chest .chest-cell .v {
    font-family: var(--px); font-size: 14px; color: var(--neon-3);
  }
  .mp-chest .chest-cell .l {
    font-family: var(--px); font-size: 7px; color: var(--ink-faint);
    margin-top: 4px; letter-spacing: 1px;
  }
  .mp-chest.win-chest .chest-cell .v { color: var(--gold); }
  .mp-chest .chest-items {
    display: flex; flex-wrap: wrap; gap: 4px; justify-content: center;
    margin-top: 6px;
  }
  .mp-chest .chest-pill {
    background: var(--bg-1); border: 2px solid var(--line);
    font-size: 13px; padding: 4px 8px;
    color: var(--ink-dim);
  }

  /* Phase 5 — End-of-game scoreboard */
  .scoreboard {
    margin: 16px auto 0;
    max-width: 460px;
    background: var(--card);
    border: 3px solid var(--line);
    box-shadow: 5px 5px 0 #000;
    padding: 12px;
    text-align: left;
  }
  .scoreboard.coop    { border-color: var(--neon-3); }
  .scoreboard.compete { border-color: var(--gold); }
  .sb-head {
    border-bottom: 2px dashed var(--line);
    padding-bottom: 8px; margin-bottom: 8px;
    text-align: center;
  }
  .sb-title {
    font-family: var(--px); font-size: 12px;
    letter-spacing: 2px; color: var(--ink);
  }
  .scoreboard.coop .sb-title { color: var(--neon-3); }
  .scoreboard.compete .sb-title { color: var(--gold); }
  .sb-sub {
    font-family: var(--term); font-size: 13px;
    color: var(--ink-faint); margin-top: 3px;
  }
  .sb-list { display: flex; flex-direction: column; gap: 4px; }
  .sb-row {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    align-items: center; gap: 8px;
    padding: 6px 8px;
    background: var(--bg-1);
    border: 2px solid var(--line);
  }
  .sb-row.me { border-color: var(--neon-3); }
  .sb-row.winner {
    border-color: var(--gold);
    background: linear-gradient(90deg, rgba(255,206,79,0.1), var(--bg-1) 50%);
  }
  .sb-rank {
    font-family: var(--px); font-size: 12px;
    min-width: 18px; text-align: center;
  }
  .sb-row.winner .sb-rank { font-size: 16px; }
  .sb-face {
    width: 28px; height: 28px;
    object-fit: cover;
    border: 2px solid var(--line);
    box-shadow: 1px 1px 0 #000;
  }
  .sb-face.emoji {
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 20px; background: var(--bg-0);
  }
  .sb-name {
    font-family: var(--term); font-size: 16px;
    color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .sb-row.winner .sb-name { color: var(--gold); }
  .sb-name .sb-you {
    font-size: 11px; color: var(--ink-faint); margin-left: 4px;
  }
  .sb-name .sb-host-tag {
    display: inline-block; margin-left: 6px;
    background: var(--gold); color: #2a1500;
    font-family: var(--px); font-size: 7px;
    padding: 1px 4px; letter-spacing: 1px;
    border: 1px solid #000;
  }
  .sb-stats {
    display: flex; flex-wrap: wrap; gap: 6px;
    justify-content: flex-end;
  }
  .sb-stat {
    font-family: var(--term); font-size: 13px;
    color: var(--ink-dim);
    background: var(--card-2); border: 1px solid var(--line);
    padding: 1px 6px;
    white-space: nowrap;
  }
  .sb-stat.sb-sab-cast { color: var(--danger); }
  .sb-stat.sb-sab-recv { color: var(--neon-2); }
  .mp-chest.sealed .chest-ic {
    animation: sealedPulse 1.6s ease-in-out infinite;
  }
  @keyframes sealedPulse {
    0%,100% { transform: scale(1); filter: drop-shadow(0 0 0 transparent); }
    50%     { transform: scale(1.06); filter: drop-shadow(0 0 12px rgba(255,206,79,0.7)); }
  }
  .mp-chest .chest-sealed-line {
    font-family: var(--px); font-size: 9px;
    color: var(--gold); letter-spacing: 2px;
    margin-top: 8px;
  }
  .mp-chest.loss-chest .chest-sealed-line { color: var(--neon-2); }

  /* Chest opening modal (inventory) */
  .chest-modal-bg .chest-modal {
    overflow: visible;
  }
  .chest-stage {
    height: 140px;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 14px;
    position: relative;
  }
  .chest-art {
    font-size: 80px;
    text-shadow: 4px 4px 0 #000;
    transform-origin: center;
    transition: transform 0.2s;
    animation: sealedPulse 1.6s ease-in-out infinite;
  }
  .chest-art.chest-art-img {
    height: 130px; width: auto;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    text-shadow: none;
    object-fit: contain;
  }
  .chest-art.chest-jiggle {
    animation: chestJiggle 0.18s ease-in-out infinite;
  }
  @keyframes chestJiggle {
    0%,100% { transform: rotate(-7deg) translateY(0); }
    25%     { transform: rotate(6deg) translateY(-4px); }
    50%     { transform: rotate(-5deg) translateY(2px); }
    75%     { transform: rotate(8deg) translateY(-3px); }
  }
  .chest-art.chest-burst {
    animation: chestBurst 0.55s ease-out forwards;
  }
  @keyframes chestBurst {
    0%   { transform: scale(1) rotate(0); opacity: 1; filter: brightness(1); }
    35%  { transform: scale(1.5) rotate(-3deg); filter: brightness(2); }
    65%  { transform: scale(1.8) rotate(2deg); filter: brightness(2.4); opacity: 0.8; }
    100% { transform: scale(0.4) rotate(0); opacity: 0; filter: brightness(1); }
  }
  .chest-revealed {
    font-size: 80px;
    text-shadow: 4px 4px 0 #000;
    animation: chestRevealPop 0.45s cubic-bezier(.2,1.6,.4,1) both;
  }
  @keyframes chestRevealPop {
    0%   { transform: scale(0.2); opacity: 0; }
    60%  { transform: scale(1.18); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
  }

  .chest-loot {
    margin-top: 4px;
    background: var(--bg-1); border: 2px solid var(--gold);
    box-shadow: 4px 4px 0 #000;
    padding: 12px;
    animation: chestLootIn 0.4s ease-out both;
  }
  @keyframes chestLootIn {
    0% { opacity: 0; transform: translateY(10px); }
    100% { opacity: 1; transform: translateY(0); }
  }
  .chest-loot-line {
    display: flex; justify-content: space-between;
    font-family: var(--term); font-size: 17px;
    color: var(--ink); padding: 6px 0;
    border-bottom: 1px dashed var(--line);
  }
  .chest-loot-line:last-of-type { border-bottom: none; }
  .chest-loot-line span:last-child { color: var(--gold); font-family: var(--px); font-size: 11px; }
  .chest-loot-items {
    margin-top: 8px; padding-top: 8px;
    border-top: 1px dashed var(--line);
    display: flex; flex-direction: column; gap: 4px;
  }
  .chest-loot-item {
    display: flex; align-items: center; gap: 8px;
    background: var(--card); padding: 4px 8px; border: 1px solid var(--line);
    font-family: var(--term); font-size: 14px;
  }
  .chest-loot-item .ic { font-size: 18px; }
  .chest-loot-empty {
    margin-top: 8px; padding: 8px;
    color: var(--ink-faint); font-style: italic; font-size: 14px; text-align: center;
  }

/* Keep party controls reachable on narrow phones. */
@media(max-width:420px){.lobby-cta-grid{grid-template-columns:minmax(0,1fr)}.lobby-id-card{margin-inline:0}.lobby-cta{min-width:0}.avatar-pick{padding:6px;min-width:0}}

[role="button"]:focus-visible {outline:3px solid var(--neon-3);outline-offset:3px}

@media(max-width:440px){.top-bar{flex-wrap:wrap}.top-bar .brand-side{flex:1 0 100%;overflow:visible}.top-bar .stats{width:100%;flex-wrap:wrap;justify-content:space-between;gap:6px}.top-bar .pill{min-width:52px;padding-inline:6px}.top-bar .brand{font-size:10px}}

/* Earned tutorial cosmetic; no coin price or gameplay effect. */
.avatar.frame-img-rookie::after { background-image:url('../img/tutorial-frame-v1/certified-rookie.png'); }
.frame-priceless { display:block; color:var(--gold); font-family:var(--px); font-size:8px; margin-top:6px; }
.frame-earned-note { display:block; color:var(--neon-3); font-family:var(--term); font-size:14px; line-height:1.2; margin-top:4px; }
.frame-earned-note { text-align:center; }
.frame-grid { grid-template-columns:repeat(3,minmax(0,1fr)); }
.frame-cell { min-width:0; justify-content:flex-start; padding-bottom:24px; }
.frame-cell .avatar { margin-top:0; flex-shrink:0; }
@media (max-width:480px) { .frame-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } }
