/* ============================================================
   site.css — structural styles shared by ALL five variants.
   Every color/font/radius comes from custom properties that each
   theme.css sets. Layout mechanics live here so the five themes
   stay visually different but behaviorally identical.
   ============================================================ */

:root {
  --bg: #0b0b0f;
  --bg-accent: #111118;
  --panel: #17171f;
  --panel-2: #20202a;
  --line: #26262f;
  --txt: #f2f2f7;
  --dim: #8e8e9d;
  --accent: #7c5cff;
  --accent-2: #00d4aa;
  --danger: #ff5c8a;
  --radius: 12px;
  --font-body: 16px/1.55 'Segoe UI', system-ui, sans-serif;
  --font-head: inherit;
  --card-art-h: 130px;
  --shell-max: 1200px;
  --shell-pad: clamp(16px, 4vw, 40px);
}

* { margin: 0; box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--txt);
  font: var(--font-body);
  min-height: 100vh;
}

a { color: inherit; }
img { max-width: 100%; height: auto; }
h1, h2, h3 { font-family: var(--font-head); }

.page-shell { max-width: var(--shell-max); margin: 0 auto; padding: 0 var(--shell-pad) 60px; }

kbd {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 1px 7px;
  font-size: 11px;
  color: var(--dim);
}

/* ---------- header / nav ---------- */

.site-header {
  display: flex; align-items: center; gap: 26px;
  padding: 14px var(--shell-pad);
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.logo { font-weight: 900; font-size: 21px; letter-spacing: 1px; text-decoration: none; }
.main-nav { display: flex; gap: 18px; flex-wrap: wrap; }
.main-nav a {
  color: var(--dim); text-decoration: none; font-size: 14px;
  letter-spacing: .5px; transition: color .15s;
}
.main-nav a:hover, .main-nav a.on { color: var(--txt); }

.search-trigger {
  margin-left: auto; display: flex; align-items: center; gap: 10px;
  background: var(--panel); border: 1px solid var(--line); color: var(--dim);
  border-radius: 10px; padding: 8px 14px; min-width: 220px;
  font: inherit; font-size: 13.5px; cursor: pointer; text-align: left;
}
.search-trigger.inline { min-width: 0; margin-left: 0; }
.search-trigger:hover { border-color: var(--accent); }
.search-trigger span { flex: 1; }

/* Member sign-out (partials/member-signout): logout is POST-only, so the
   control is a <form> button dressed as a nav link. --dim/--txt only — every
   theme defines both; bespoke-chrome themes restyle it in their theme.css. */
.member-signout { display: inline-flex; }
.member-signout button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 14px; letter-spacing: .5px;
  color: var(--dim); transition: color .15s;
}
.member-signout button:hover { color: var(--txt); }
/* second surface on /my/history — 3 themes hide .main-nav on phones */
.category-head .member-signout { margin-top: 10px; }

/* ---------- hero / stats ---------- */

.hero { text-align: center; padding: 56px 0 34px; position: relative; z-index: 1; }
.hero h1 { font-size: clamp(30px, 5vw, 54px); letter-spacing: -.5px; }
.hero-sub { color: var(--dim); max-width: 54ch; margin: 14px auto 26px; }
.cta {
  display: inline-block; background: var(--accent); color: var(--bg);
  font-weight: 800; letter-spacing: 1px; text-decoration: none;
  padding: 13px 34px; border-radius: 10px; transition: transform .15s, box-shadow .15s;
}
.cta:hover { transform: translateY(-2px); }
/* Registration CTAs are <button>s, not links: `register` is a POST-only route
   (Clean Registration happens in the clouded pop-open), so an href there 404s.
   Buttons don't inherit page typography, hence the reset. */
button.cta, button.ghost { font: inherit; border: 0; cursor: pointer; }
button.cta { font-weight: 800; letter-spacing: 1px; }
button.ghost { border: 1px solid var(--line); }
.linklike {
  background: none; border: 0; padding: 0; font: inherit; color: var(--accent-2);
  text-decoration: underline; cursor: pointer;
}
.stats { display: flex; gap: 34px; justify-content: center; margin-top: 30px; flex-wrap: wrap; }
.stat b { font-size: 24px; display: block; color: var(--accent-2); }
.stat span { font-size: 12px; color: var(--dim); text-transform: uppercase; letter-spacing: 1px; }

/* ---------- experience strip (home) ---------- */

.exp-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px; padding: 8px 0 4px; position: relative; z-index: 1;
}
.exp {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; display: flex; flex-direction: column; gap: 6px;
}
.exp b { font-size: 14.5px; }
.exp > span:last-child { color: var(--dim); font-size: 12.5px; line-height: 1.45; }
.exp-glyph {
  width: 34px; height: 34px; border-radius: 9px; position: relative;
  border: 2px solid var(--accent-2); opacity: .9; margin-bottom: 2px;
}
.exp-glyph.play::after {
  content: ""; position: absolute; left: 12px; top: 8px;
  border-left: 11px solid var(--accent-2); border-block: 7px solid transparent;
}
.exp-glyph.save::after {
  content: ""; position: absolute; inset: 7px 7px 12px;
  border: 2px solid var(--accent-2); border-radius: 2px;
}
.exp-glyph.save::before {
  content: ""; position: absolute; left: 11px; bottom: 6px; width: 8px; height: 4px;
  background: var(--accent-2);
}
.exp-glyph.pad::after {
  content: ""; position: absolute; left: 6px; top: 12px; width: 6px; height: 6px;
  background: var(--accent-2); box-shadow: 12px 0 0 var(--accent-2);
  border-radius: 50%;
}
.exp-glyph.pad::before {
  content: ""; position: absolute; left: 13px; top: 8px; width: 4px; height: 14px;
  background: var(--accent-2);
}
.exp-glyph.shield::after {
  content: ""; position: absolute; left: 10px; top: 7px; width: 10px; height: 13px;
  border: 2px solid var(--accent-2); border-radius: 50% 50% 50% 50% / 20% 20% 70% 70%;
}

/* ---------- spotlights (home trio) ---------- */

.spotlights { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
.spot {
  background: var(--panel); border: 1px solid var(--line); border-radius: calc(var(--radius) + 2px);
  padding: 20px; text-decoration: none; display: flex; flex-direction: column; gap: 8px;
  transition: transform .18s, border-color .18s;
}
.spot:hover { transform: translateY(-4px); border-color: var(--accent); }
.spot-kick { font-size: 11px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; color: var(--accent-2); }
.spot b { font-size: 18px; }
.spot p { color: var(--dim); font-size: 13.5px; flex: 1; }
.spot-play { color: var(--accent); font-weight: 700; font-size: 13px; }

/* ---------- full library groups (home) ---------- */

.library-group { margin: 18px 0 26px; }
.library-group h3 { font-size: 16px; margin-bottom: 12px; }
.library-group h3 a { text-decoration: none; }
.library-group h3 a:hover { color: var(--accent); }
.lib-count { color: var(--dim); font-size: 12px; font-weight: 400; margin-left: 8px; }

/* ---------- feature banner ---------- */

.feature-banner {
  margin: 22px 0; border-radius: calc(var(--radius) + 6px); overflow: hidden;
  background: linear-gradient(115deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line);
  display: flex; align-items: flex-end; min-height: 230px; position: relative; z-index: 1;
}
.fmeta { padding: 28px; max-width: 560px; }
.fkick { font-size: 11px; font-weight: 800; letter-spacing: 2px; color: var(--accent-2); text-transform: uppercase; }
.fmeta h2 { font-size: 32px; margin: 6px 0 10px; }
.fmeta p { color: var(--dim); margin-bottom: 16px; }
.fbtns { display: flex; gap: 12px; }
.playbig {
  background: var(--txt); color: var(--bg); border: 0; font-weight: 800;
  border-radius: 10px; padding: 11px 26px; cursor: pointer; text-decoration: none; font-size: 15px;
}
.playbig:hover { background: var(--accent-2); }
.ghost {
  background: transparent; color: var(--txt); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px 18px; text-decoration: none; font-size: 14px;
}
.fstats { display: flex; gap: 16px; margin-top: 14px; font-size: 12px; color: var(--dim); flex-wrap: wrap; }

/* A brand or title with no spaces — "RetroPlayers.Club" — is a single
   unbreakable word. In a heading at phone widths it ran past the viewport and
   gave the whole page a horizontal scrollbar (measured: a 455px H1 inside a
   328px column). Headings may break inside a word when there is no alternative. */
h1, h2, h3, .lane-title, .legal-body h2 { overflow-wrap: break-word; }

/* ---------- sign in ---------- */

.auth-shell { display: flex; justify-content: center; padding: 54px 0 70px; }
.auth-panel {
  width: min(430px, 94vw); background: var(--panel, var(--bg-accent, #140b2e));
  border: 1px solid var(--line); border-radius: 16px; padding: 30px 30px 26px;
  box-shadow: 0 0 40px rgba(0, 0, 0, .45);
}
.auth-panel h1 { font-size: 27px; margin: 2px 0 18px; }
.auth-form { display: flex; flex-direction: column; }
.auth-form label { font-size: 12px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--dim); margin-bottom: 6px; }
.auth-form input {
  background: rgba(0, 0, 0, .35); border: 1px solid var(--line); border-radius: 9px;
  color: var(--txt); padding: 11px 13px; font: inherit; margin-bottom: 16px;
}
.auth-form input:focus { outline: 2px solid var(--accent-2); outline-offset: 1px; }
.auth-form .cta { width: 100%; text-align: center; border: 0; cursor: pointer; margin-top: 2px; }
.auth-error {
  background: rgba(255, 45, 149, .12); border: 1px solid var(--accent);
  border-radius: 9px; padding: 10px 13px; margin-bottom: 16px; font-size: 14px;
}
.auth-alt { font-size: 13.5px; color: var(--dim); margin-top: 14px; line-height: 1.6; }

/* ---------- club pages (about / privacy / dmca) ---------- */

.legal-hero { padding: 46px 0 10px; max-width: 78ch; text-align: left; }
.legal-hero h1 { font-size: 38px; line-height: 1.1; margin-bottom: 10px; }
/* .hero-sub is centred+inset for the home hero; these pages read as documents,
   so it aligns with the h1 instead of floating in from the left margin. */
.legal-hero .hero-sub { margin: 0; padding: 0; max-width: 70ch; text-align: left; }
.legal-updated { font-size: 12px; color: var(--dim); text-transform: uppercase; letter-spacing: 1.5px; margin-top: 14px; }
.legal-body { max-width: 78ch; padding-bottom: 60px; }
.legal-body h2 {
  font-size: 15px; text-transform: uppercase; letter-spacing: 2.5px;
  color: var(--accent-2); margin: 32px 0 10px;
}
.legal-body p { margin-bottom: 14px; line-height: 1.75; }
.legal-list { margin: 0 0 16px 22px; }
.legal-list li { margin-bottom: 9px; line-height: 1.7; }
/* An operator detail that is not filled in yet says so, loudly, rather than
   printing an invented address a rights holder would send notices into. */
.legal-pending {
  display: inline-block; background: rgba(255, 209, 102, .12); border: 1px dashed #ffd166;
  color: #ffd166; border-radius: 6px; padding: 2px 9px; font-size: 13px;
}

/* ---------- lanes / cards ---------- */

.lane { padding: 26px 0; position: relative; z-index: 1; }
.lane-title {
  font-size: 15px; text-transform: uppercase; letter-spacing: 2.5px;
  color: var(--accent); margin-bottom: 16px;
}
.card-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); gap: 16px;
}
.game-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; text-decoration: none; transition: transform .18s, border-color .18s, box-shadow .18s;
  display: block; position: relative;
}
.game-card:hover { transform: translateY(-5px); border-color: var(--accent); }
.game-card .art {
  height: var(--card-art-h); position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, var(--panel-2), var(--bg-accent));
}
.game-card .art img { width: 100%; height: 100%; object-fit: cover; }
.art-initials { font-size: 34px; font-weight: 900; color: var(--dim); letter-spacing: 2px; }
[data-fallback-art="0"] { background: linear-gradient(135deg, #b13a5e, #4a1230); }
[data-fallback-art="1"] { background: linear-gradient(135deg, #2c66c4, #101c45); }
[data-fallback-art="2"] { background: linear-gradient(135deg, #c98a12, #3d2703); }
[data-fallback-art="3"] { background: linear-gradient(135deg, #1d8a4a, #07260f); }
[data-fallback-art="4"] { background: linear-gradient(135deg, #7a3aa8, #1e0b33); }
[data-fallback-art="5"] { background: linear-gradient(135deg, #17939d, #062a2e); }
.play-hover {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  color: var(--accent-2); font-weight: 800; letter-spacing: 2px; font-size: 13px;
  opacity: 0; transition: opacity .18s;
}
.game-card:hover .play-hover { opacity: 1; }
.game-card .meta { padding: 10px 12px; }
.game-card .meta b {
  font-size: 13.5px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.game-card .sub {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 6px; color: var(--dim); font-size: 11px;
}
.tag {
  font-size: 10.5px; color: var(--bg); background: var(--accent-2);
  border-radius: 4px; padding: 1px 7px; font-weight: 800; letter-spacing: 1px;
}

/* ---------- console tiles ---------- */

.console-row { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px; }
.console-tile {
  min-width: 126px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; text-align: center;
  text-decoration: none; transition: border-color .15s, transform .15s;
}
.console-tile:hover { border-color: var(--accent); transform: translateY(-3px); }
.console-tile svg { width: 30px; height: 30px; }
.console-tile b { display: block; font-size: 13px; margin-top: 8px; }
.console-tile span { font-size: 11px; color: var(--dim); }

/* ---------- console category hero ---------- */

.cat-hero {
  display: grid; grid-template-columns: 1.15fr .85fr; gap: 30px;
  margin: 22px 0; padding: 30px; align-items: center;
  background: linear-gradient(115deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line); border-radius: calc(var(--radius) + 6px);
  position: relative; z-index: 1; overflow: hidden;
}
.cat-kick {
  font-size: 11px; font-weight: 800; letter-spacing: 2px;
  text-transform: uppercase; color: var(--accent-2); margin-bottom: 8px;
}
.cat-hero h1 { font-size: clamp(26px, 4vw, 42px); }
.cat-blurb { color: var(--dim); margin: 12px 0; max-width: 56ch; font-size: 16px; }
.cat-cta-row { display: flex; gap: 12px; margin-top: 16px; flex-wrap: wrap; align-items: center; }
.cat-cta-row .playbig, .cat-cta-row .ghost { text-decoration: none; display: inline-block; }

.cat-glyph-panel {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 26px; border: 1px solid var(--line); border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg) 40%, transparent);
}
.console-glyph.big { width: 120px; height: 78px; border-width: 4px; border-radius: 16px; color: var(--accent); }
.console-glyph.big::before { left: 18px; width: 26px; height: 26px; border-width: 4px; }
.console-glyph.big::after { right: 20px; width: 16px; height: 16px; box-shadow: -26px 0 0 -2px currentColor; }
.cat-glyph-name { font-weight: 900; letter-spacing: 4px; font-size: 18px; color: var(--accent); }
.cat-chips { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.cat-chip {
  font-size: 11px; font-weight: 700; letter-spacing: .5px;
  border: 1px solid var(--line); border-radius: 99px; padding: 4px 12px; color: var(--dim);
}
.cat-chip.beta { border-color: var(--danger); color: var(--danger); }

/* genre chips */
.chip-row { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  font-size: 12.5px; border: 1px solid var(--line); border-radius: 99px;
  padding: 5px 14px; color: var(--dim); text-decoration: none; transition: .15s;
}
.chip:hover { color: var(--txt); border-color: var(--accent); }
.chip.on { color: var(--bg); background: var(--accent); border-color: var(--accent); font-weight: 700; }

/* empty shelf */
.cat-empty {
  text-align: center; padding: 40px 24px; margin: 22px 0;
  border: 1px dashed var(--line); border-radius: calc(var(--radius) + 6px);
  position: relative; z-index: 1;
}
.cat-empty .console-glyph.big { margin: 0 auto 14px; color: var(--dim); }
.cat-empty h2 { font-size: 24px; }
.cat-empty > p { color: var(--dim); max-width: 62ch; margin: 12px auto 0; }
.cat-empty .card-grid { text-align: initial; margin-top: 14px; }

@media (max-width: 820px) {
  .cat-hero { grid-template-columns: 1fr; }
  .cat-glyph-panel { order: -1; }
}

/* ---------- breadcrumbs / category ---------- */

.breadcrumbs { padding: 18px 0 0; font-size: 12.5px; color: var(--dim); position: relative; z-index: 1; }
.breadcrumbs a { color: var(--dim); text-decoration: none; }
.breadcrumbs a:hover { color: var(--txt); }

.category-head { padding: 22px 0 6px; position: relative; z-index: 1; }
.category-head h1 { font-size: clamp(26px, 4vw, 40px); }
.category-sub { color: var(--dim); margin: 10px 0; max-width: 70ch; }
.category-toolbar {
  display: flex; align-items: center; gap: 18px; margin-top: 14px;
  padding: 10px 0; border-block: 1px solid var(--line); font-size: 13px;
}
.category-toolbar .count { color: var(--dim); }
.sorts { margin-left: auto; display: flex; gap: 12px; }
.sorts a { color: var(--dim); text-decoration: none; }
.sorts a.on { color: var(--accent); font-weight: 700; }

/* ---------- game page ---------- */

.game-head { padding: 20px 0 4px; position: relative; z-index: 1; }
.game-head h1 { font-size: clamp(26px, 4vw, 40px); }
.game-facts { display: flex; gap: 10px; align-items: center; margin: 12px 0; flex-wrap: wrap; font-size: 13px; color: var(--dim); }
.seo-intro { max-width: 76ch; color: var(--txt); }
.seo-intro p { margin: 10px 0; }

.player-zone { position: relative; margin: 22px 0; z-index: 1; }
.player-frame {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 4px); overflow: hidden;
  transition: filter .35s;
}
.game-screen { aspect-ratio: 4 / 3; max-height: 70vh; width: 100%; background: #000; position: relative; }
.emulator-frame { width: 100%; height: 100%; border: 0; display: block; }
.boot-state {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px; text-align: center;
}
/* R100.4 (David): "Screenshots should show fast while the 'games show a
   loading bar'" — the action screenshot is the INSTANT full-frame backdrop of
   every loading state (it is a small, fetchpriority=high image, so it paints
   long before any core/ROM/FMV byte arrives). Text + progress ride above it. */
.boot-art { position: absolute; inset: 0; margin: 0; }
.boot-art img {
  width: 100%; height: 100%; max-height: none; object-fit: cover;
  opacity: .45; filter: saturate(.9); transition: opacity .5s ease;
}
.boot-text, .boot-progress { position: relative; }
.boot-text { color: var(--accent-2); font-family: 'Courier New', monospace; letter-spacing: 2px; animation: boot-blink 1.2s infinite; }
@keyframes boot-blink { 50% { opacity: .3; } }
/* Honest experimental-core notice (round-26) — sits above the game canvas so a
   visitor is told PS2/Play! is early-beta rather than shown a slideshow that
   never becomes playable. */
.emu-experimental {
  position: absolute; top: 0; left: 0; right: 0; z-index: 6;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 16px; text-align: left;
  background: color-mix(in srgb, #b8860b 30%, color-mix(in srgb, var(--bg) 82%, transparent));
  border-bottom: 1px solid color-mix(in srgb, #f6c453 55%, transparent);
  backdrop-filter: blur(2px);
}
.emu-experimental-badge {
  flex: 0 0 auto; font-size: 11px; font-weight: 900; letter-spacing: 2px;
  color: #ffd873; border: 1px solid #f6c453; border-radius: 99px; padding: 4px 12px;
  white-space: nowrap;
}
.emu-experimental p { margin: 0; color: var(--fg, #eee); font-size: 12.5px; line-height: 1.45; max-width: 68ch; }

/* Native desktop full-speed CTA (round-28 PS2 handback) — sits under the
   experimental notice as the real play path for heavy PS2 titles. */
.native-desktop-cta {
  margin: 12px 0; padding: 16px 18px; border-radius: 12px; text-align: left;
  background: color-mix(in srgb, var(--accent, #39c0ff) 12%, color-mix(in srgb, var(--bg) 88%, transparent));
  border: 1px solid color-mix(in srgb, var(--accent, #39c0ff) 45%, transparent);
}
.native-cta-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.native-cta-head strong { font-size: 15px; color: var(--fg, #fff); }
.native-cta-badge {
  flex: 0 0 auto; font-size: 11px; font-weight: 900; letter-spacing: 1.5px;
  color: var(--accent, #39c0ff); border: 1px solid color-mix(in srgb, var(--accent, #39c0ff) 60%, transparent);
  border-radius: 99px; padding: 3px 11px; white-space: nowrap;
}
.native-cta-body { margin: 0 0 10px; color: var(--fg, #ddd); font-size: 13px; line-height: 1.5; max-width: 70ch; }
.native-cta-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.pbtn-native { background: var(--accent, #39c0ff); color: #06121a; font-weight: 800; }
.native-cta-launch { font-size: 12.5px; text-decoration: underline; }
.native-cta-soon { margin: 0; font-size: 13px; font-weight: 700; color: var(--accent, #39c0ff); }
.native-cta-note { margin: 10px 0 0; font-size: 11.5px; color: color-mix(in srgb, var(--fg, #ccc) 70%, transparent); line-height: 1.4; }

/* ============================================================================
   Round-29 NATIVE-DOWNLOAD HERO (PS2 + Dreamcast).
   Fills the game-screen with a looping gameplay FMV; the "Download Our Mini App"
   CTA sits over a scrim. Uses the theme CSS vars so it styles across all five
   variants. When no FMV asset exists yet, the media area falls back to an
   on-brand gradient slate (never fabricated gameplay).
   ============================================================================ */
.native-hero { position: absolute; inset: 0; display: flex; align-items: flex-end; overflow: hidden; }
.native-hero-media {
  position: absolute; inset: 0; z-index: 0;
  background: radial-gradient(130% 120% at 50% 0%, color-mix(in srgb, var(--accent, #39c0ff) 24%, var(--panel)) 0%, var(--panel) 72%);
}
.native-hero-video, .native-hero-still { width: 100%; height: 100%; object-fit: cover; display: block; }
.native-hero-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--bg) 12%, transparent) 0%,
    color-mix(in srgb, var(--bg) 40%, transparent) 42%,
    color-mix(in srgb, var(--bg) 90%, transparent) 100%);
}
.native-hero-body {
  position: relative; z-index: 2; width: 100%;
  padding: clamp(16px, 4vw, 34px);
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
}
.native-hero-badge {
  font-size: 11px; font-weight: 900; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--accent, #39c0ff);
  border: 1px solid color-mix(in srgb, var(--accent, #39c0ff) 60%, transparent);
  border-radius: 99px; padding: 4px 12px;
  background: color-mix(in srgb, var(--bg) 55%, transparent);
}
.native-hero-title { margin: 2px 0 2px; font-size: clamp(20px, 3.4vw, 30px); color: #fff; text-shadow: 0 2px 18px rgba(0, 0, 0, .6); }
.native-hero-cta {
  display: inline-block; max-width: 100%;
  background: var(--accent, #39c0ff); color: #06121a; font-weight: 800;
  font-size: clamp(14px, 1.7vw, 16px); line-height: 1.25;
  padding: 13px 22px; border-radius: 12px; text-decoration: none;
  box-shadow: 0 10px 30px color-mix(in srgb, var(--accent, #39c0ff) 40%, transparent);
  transition: transform .12s ease, box-shadow .12s ease;
  animation: native-cta-pulse 2.6s ease-in-out infinite;
}
.native-hero-cta:hover { transform: translateY(-1px); box-shadow: 0 14px 40px color-mix(in srgb, var(--accent, #39c0ff) 58%, transparent); }
.native-hero-cta.is-soon {
  background: color-mix(in srgb, var(--accent, #39c0ff) 42%, var(--panel));
  color: #fff; cursor: default; box-shadow: none; animation: none;
}
@keyframes native-cta-pulse {
  0%, 100% { box-shadow: 0 10px 30px color-mix(in srgb, var(--accent, #39c0ff) 34%, transparent); }
  50% { box-shadow: 0 12px 42px color-mix(in srgb, var(--accent, #39c0ff) 62%, transparent); }
}
.native-hero-launch { color: var(--accent-2, #ffd873); font-size: 13px; text-decoration: none; }
.native-hero-launch:hover { text-decoration: underline; }
.native-hero-soon { margin: 0; font-size: 13px; color: #e9e9ef; max-width: 66ch; line-height: 1.5; text-shadow: 0 1px 8px rgba(0, 0, 0, .5); }
.native-hero-soon a { color: var(--accent-2, #ffd873); }
.native-hero-note { margin: 4px 0 0; font-size: 12px; color: #cfd2da; line-height: 1.5; max-width: 72ch; text-shadow: 0 1px 8px rgba(0, 0, 0, .5); }

/* R62.2 — APP MODE: the RetroPlayers.Club Player renders this same branded page
   in its own window. R66 rework: the game runs IN THE PAGE FRAME (.app-stage —
   the Player embeds the emulator window over that exact box), with the
   web-style controller information bar (.app-ctx) beneath it. Full screen is
   the bar's button; nothing boots fullscreen. */
.app-mode-page .story-comments-grid { grid-template-columns: 1fr; }
/* The web .game-screen is a fixed 4:3 box — in app mode it holds the stage +
   the controller bar stacked, so it must grow with them or the bar is clipped
   below the box (caught by the R66 screenshot proof). */
.app-mode-page .game-screen { aspect-ratio: auto; max-height: none; height: auto; }
.app-shell { display: flex; flex-direction: column; gap: 0; }
.app-stage { position: relative; aspect-ratio: 16 / 9; min-height: 320px; background: #000; border-radius: 14px 14px 0 0; overflow: hidden; }
/* R103.1 → R104.1 (David, twice: DC/Saturn "still floats … not static when
   scrolling"): position:sticky only pins WITHIN the parent's box, and
   .app-shell is barely taller than the stage, so sticky had no travel room
   and rode the scroll. TRUE static = position:FIXED at the rect the stage
   occupied when play started (JS sets the inset vars); a placeholder keeps
   the page layout intact so nothing jumps. The frame-rect the app sends is
   then scroll-invariant — the embedded child never gets repositioned. */
.app-shell.session-live .app-stage {
  position: fixed;
  top: var(--stage-top, 8px);
  left: var(--stage-left, 0);
  width: var(--stage-w, 100%);
  height: var(--stage-h, auto);
  z-index: 400;
}
.app-stage-holder { display: none; }
.app-shell.session-live .app-stage-holder { display: block; }
/* R104.3: the DC "you will Need to Restart" YES/NO prompt (David's copy). */
.app-restart-ask { position: fixed; inset: 0; z-index: 4200; display: grid; place-items: center; background: rgba(4,4,10,.72); }
.app-restart-card { max-width: 460px; padding: 22px 24px; border-radius: 14px; background: #14141c; border: 1px solid #33334a; box-shadow: 0 24px 60px rgba(0,0,0,.6); text-align: center; }
.app-restart-card p { margin: 0 0 16px; font-weight: 700; line-height: 1.45; color: #f0f0f7; }
.app-restart-row { display: flex; gap: 12px; justify-content: center; }
.app-stage .native-hero-media { position: absolute; inset: 0; }
.app-stage .native-hero-video, .app-stage .native-hero-still { width: 100%; height: 100%; object-fit: cover; }
/* Fullscreen = the stage swallows the window (the Player also fullscreens the
   OS window). ESC — owned by the Player's key hook — brings this back. */
/* R104.1 guard: session-live pins the stage with explicit width/height vars —
   `inset: 0` alone would NOT beat them (width wins over right/bottom), so
   fullscreen must reset the size explicitly or Full renders a small corner
   window. Same specificity, declared later, plus !important-free overrides. */
.app-shell.fs .app-stage { position: fixed; inset: 0; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 4000; aspect-ratio: auto; border-radius: 0; min-height: 100vh; }
.app-gate { position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; gap: 8px; padding: clamp(16px, 4vw, 42px); }
.app-gate[hidden] { display: none; }
.app-shell .app-attest { display: flex; gap: 10px; align-items: flex-start; max-width: 66ch; margin: 2px 0 6px; font-size: 13px; line-height: 1.5; color: #e9e9ef; text-shadow: 0 1px 8px rgba(0, 0, 0, .5); }
.app-shell .app-attest input { margin-top: 3px; width: 17px; height: 17px; flex: 0 0 auto; }
.app-shell .app-play-btn:disabled { opacity: .45; cursor: not-allowed; filter: grayscale(.5); }
.app-shell .app-status { font-size: 13px; color: #e9e9ef; min-height: 18px; text-shadow: 0 1px 8px rgba(0, 0, 0, .5); }
.app-shell .app-bar { height: 8px; width: min(420px, 100%); background: rgba(255, 255, 255, .14); border-radius: 5px; overflow: hidden; margin: 4px 0 8px; }
.app-shell .app-bar > i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent, #8b5cf6), var(--accent-2, #ffd873)); transition: width .2s; }
/* The controller information bar — same .controller-context/.pbtn chrome as
   the web player pages (and never .locked in app mode: premium is the gate). */
.app-ctx { border-radius: 0 0 14px 14px; }
.app-ctx .app-ctx-status { font-size: 12px; color: #cfd2da; margin-left: auto; align-self: center; }
.app-shell .app-tool-btn { padding: 7px 13px; border-radius: 9px; border: 1px solid rgba(255, 255, 255, .25); background: rgba(0, 0, 0, .35); color: #fff; font-size: 13px; font-weight: 600; cursor: pointer; }
.app-shell .app-tool-btn:hover { border-color: var(--accent-2, #ffd873); }
.app-shell .app-tool-note { font-size: 12px; color: #cfd2da; }
.app-shell .app-controls-panel { background: rgba(0, 0, 0, .55); border: 1px solid rgba(255, 255, 255, .18); border-radius: 12px; padding: 14px; margin: 10px 0 4px; max-width: 640px; }
.app-shell .app-map-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin: 10px 0; }
.app-shell .app-map-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .12); border-radius: 8px; padding: 6px 9px; }
.app-shell .app-map-row .lbl { font-size: 12px; color: #e9e9ef; }
.app-shell .app-map-key { min-width: 52px; padding: 4px 8px; border: 1px solid rgba(255, 255, 255, .3); border-radius: 7px; background: rgba(0, 0, 0, .4); color: #fff; font-weight: 700; font-size: 12px; cursor: pointer; }
/* R105 (David, Dreamcast: "only 2 action buttons were mapped"): a bind the
   emulator's config cannot carry — two buttons on one key — is MARKED here.
   The panel must never show a binding that the config silently discards. */
/* R130: the CONTROLLER cell beside each key — dim until a pad bind exists. */
.app-shell .app-map-pad-cell { opacity: .75; border-style: dashed; }
.app-shell .app-map-pad-cell:hover { opacity: 1; }
.app-shell .app-map-row.is-unmapped { border-color: #ffb04d; background: rgba(255, 176, 77, .14); }
.app-shell .app-map-row.is-unmapped .app-map-key { border-color: #ffb04d; color: #ffd9a8; }
.app-shell .app-map-warn { flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%; background: #ffb04d; color: #201400; font-size: 11px; font-weight: 800; line-height: 16px; text-align: center; }
.app-shell .app-controls-actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* Exit confirmation (double-ESC / Exit Game) — the Player hides the game
   window first, so this dialog is genuinely visible + clickable. */
.app-confirm { position: fixed; inset: 0; z-index: 2147483000; display: flex; align-items: center; justify-content: center; background: rgba(4, 4, 12, .72); backdrop-filter: blur(3px); }
.app-confirm[hidden] { display: none; }
.app-confirm-box { background: var(--panel, #14141f); border: 1px solid rgba(255, 255, 255, .2); border-radius: 14px; padding: 26px 30px; max-width: 420px; text-align: center; box-shadow: 0 18px 60px rgba(0, 0, 0, .55); }
.app-confirm-box h3 { margin: 0 0 8px; font-size: 20px; color: #fff; }
.app-confirm-box p { margin: 0 0 18px; font-size: 13px; color: #cfd2da; line-height: 1.5; }
.app-confirm-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* Native-only pages have no in-browser emulator, so every emulator-bound control
   (save/record/online/chat + remap panels) and the device-mode notes are hidden
   — the FMV hero + download CTA is the whole interaction. R66: the APP-MODE
   controller bar (.app-ctx) is exempt — in the Player, the game really does
   run in the page and the bar is its control surface. */
.player-zone.is-native-only .controller-context:not(.app-ctx),
.player-zone.is-native-only .device-switch-note,
.player-zone.is-native-only .mobile-controls-note,
.player-zone.is-native-only .online-cta { display: none !important; }
/* R100.5: the challenge CTA (David's 2-player flags) is EXEMPT on native
   pages — presence now includes Mini App players, so the flash is real. The
   element still starts [hidden]; player.js reveals it only when another
   member is detected playing right now. */
.player-zone.is-native-only .online-cta.challenge-eligible { display: flex !important; }
.player-zone.is-native-only .online-cta.challenge-eligible[hidden] { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  .native-hero-cta { animation: none; }
  /* player.js additionally pauses the <video> loop under reduced motion. */
}

/* Large-game download progress (PS1 discs) — player.js fills it from the
   engine's reported percentage; the bar stops blinking so it reads as real. */
.boot-progress {
  width: min(320px, 70%); height: 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .12); overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .15);
}
.boot-progress-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .3s ease;
}
.boot-state.downloading .boot-text { animation: none; }

/* ============ R50 — the Club home ============ */
/* Header logo (crest + wordmark SVG) — text-logo glow rules don't apply */
.logo.logo-svg { display: inline-flex; align-items: center; text-shadow: none; }
.logo.logo-svg .rpc-logo { height: 40px; width: auto; display: block; }
@media (max-width: 640px) { .logo.logo-svg .rpc-logo { height: 30px; } }

.club-hero .club-kicker {
  color: var(--accent-2); text-transform: uppercase; letter-spacing: 5px;
  font-size: 13px; font-weight: 700; margin-bottom: 10px;
}
.cta.club-join {
  display: inline-block; font-size: 20px; font-weight: 800; letter-spacing: .5px;
  padding: 16px 30px; margin: 18px 0 14px;
  background: linear-gradient(135deg, var(--accent), #b3186a);
  color: #fff; border-radius: 12px; text-decoration: none;
  box-shadow: 0 0 24px rgba(255, 45, 149, .45);
}
.cta.club-join:hover { transform: translateY(-2px); box-shadow: 0 0 34px rgba(255, 45, 149, .65); }
.club-ease { max-width: 62ch; margin: 0 auto 20px; color: var(--dim, #b9a8d8); font-size: 15px; line-height: 1.65; }

.lane-note { color: var(--dim, #b9a8d8); margin: -6px 0 14px; font-size: 14px; }

/* International Top Players */
.tp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.tp-card { background: var(--panel, rgba(255,255,255,.04)); border: 1px solid rgba(255,45,149,.25); border-radius: 12px; overflow: hidden; }
.tp-video { width: 100%; aspect-ratio: 16/9; background: #000; display: block; }
.tp-video-empty { display: flex; align-items: center; justify-content: center; font-size: 42px; opacity: .85; }
/* Click-to-play facade — the poster as a button, so no media element exists
   until someone asks for one (see site.js: a <video> here never lets WebKit
   finish loading the page). */
.tp-play {
  border: 0; padding: 0; cursor: pointer; position: relative;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
.tp-play .tp-play-icon {
  position: absolute; inset: 0; margin: auto; width: 62px; height: 62px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(10, 1, 24, .62); border: 2px solid #fff;
  color: #fff; font-size: 22px; padding-left: 4px; transition: transform .15s, background .15s;
}
.tp-play:hover .tp-play-icon, .tp-play:focus-visible .tp-play-icon {
  transform: scale(1.08); background: var(--accent);
}
.tp-meta { padding: 12px 14px 14px; display: grid; gap: 3px; }
.tp-name { font-size: 16px; }
.tp-game { color: var(--accent-2); font-size: 13px; }
.tp-score { color: var(--accent); font-weight: 700; font-size: 13px; }
.tp-note { color: var(--dim, #b9a8d8); font-size: 13px; }
.tp-cta { margin-top: 16px; font-size: 15px; }
.tp-cta a { color: var(--accent-2); font-weight: 700; }

/* Play-count call-out badge on game-card art */
.game-card .art { position: relative; }
.plays-badge {
  position: absolute; left: 8px; bottom: 8px; z-index: 2;
  /* The pill is a HARD-CODED dark colour on every theme, so its text must not
     be theme-derived: playdeck's --accent-2 is #16161a (near black), which
     painted the play counts black-on-black at 1.13:1 — the R50 "showcase call
     to action Play counts" unreadable on that variant. The border keeps the
     theme accent; the label is white because the pill is always dark. */
  background: rgba(10, 1, 24, .85); border: 1px solid var(--accent-2);
  color: #fff; font-size: 12px; font-weight: 700;
  padding: 3px 9px; border-radius: 999px; letter-spacing: .3px;
}

/* Premium band */
.club-premium {
  margin: 34px 0; padding: 26px 28px; border-radius: 14px;
  border: 1px solid rgba(34, 228, 242, .35);
  background: linear-gradient(135deg, rgba(255,45,149,.12), rgba(34,228,242,.08));
  display: grid; gap: 16px;
}
.cp-noads b { display: block; font-size: 30px; letter-spacing: 1px; color: var(--accent); text-shadow: 0 0 14px rgba(255,45,149,.6); }
.cp-noads span { color: var(--ink, #f4ecff); font-size: 15px; }
.cp-perks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.cp-perks li { font-size: 15px; }
.cp-cta { justify-self: start; }
@media (max-width: 640px) { .cp-noads b { font-size: 24px; } }
/* R45.2 — loading FMV: the game's real clip fills the frame while a big ISO
   streams; the boot text + progress bar ride over it on a soft scrim. */
.loading-fmv {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; filter: brightness(.55) saturate(.9);
  transition: opacity .5s ease;
}
.boot-state.has-fmv { z-index: 1; background: linear-gradient(180deg, rgba(0,0,0,.25), rgba(0,0,0,.55)); }
/* R100.4: the art STAYS visible under has-fmv (it used to be display:none,
   which left NEITHER art nor the still-downloading FMV on screen — David:
   "The loading is slow… Screenshots should show fast"). Once the clip truly
   plays, player.js tags fmv-live and the art fades out to reveal it. */
.boot-state.has-fmv.fmv-live .boot-art img { opacity: 0; }
.boot-error { text-align: center; display: flex; flex-direction: column; gap: 12px; align-items: center; }
.boot-error p { color: var(--danger); font-size: 14px; max-width: 46ch; }

/* When the gate is up, the player is "clouded": blurred + dimmed but running */
.player-zone.gated .player-frame { filter: blur(9px) brightness(.55) saturate(.7); pointer-events: none; }

.controller-context { padding: 12px 16px; border-top: 1px solid var(--line); position: relative; }
.player-controls { display: flex; gap: 8px; flex-wrap: wrap; }
.pbtn {
  background: none; border: 1px solid var(--line); color: var(--txt);
  border-radius: 8px; padding: 6px 13px; cursor: pointer; font-size: 12.5px; transition: border-color .15s, color .15s;
}
.pbtn:hover { border-color: var(--accent-2); color: var(--accent-2); }
.controller-context.locked .pbtn { opacity: .45; cursor: pointer; }
.controller-context.locked::after {
  content: "Create a free account to unlock saves, rewind & controller setup";
  display: block; margin-top: 8px; font-size: 12px; color: var(--dim);
}
.controller-setup {
  margin-top: 12px; padding: 14px 16px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--panel);
}
.controller-setup[hidden] { display: none; }
.cs-gamepad { margin: 0 0 10px; font-size: 13.5px; }
.cs-remap-cta { margin: 0 0 10px; font-size: 13px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cs-remap-cta.muted { color: var(--dim); }
.pbtn.sm { padding: 4px 10px; font-size: 12px; }
kbd.remappable { cursor: pointer; transition: border-color .15s, background .15s; }
kbd.remappable:hover, kbd.remappable:focus { border-color: var(--accent-2); color: var(--accent-2); outline: none; }
kbd.remap-key.listening { border-color: var(--accent); color: var(--accent); animation: boot-blink 1s infinite; }
/* R129: live gamepad binding shown in the Controller column (painted by
   player.js paintPad from the ENGINE's value2 truth). currentColor keeps it
   legible on all five themes without a per-theme variable. */
.remap-pad { display: inline-block; padding: 1px 8px; border: 1px solid currentColor; border-radius: 4px; font-size: 12px; opacity: .8; white-space: nowrap; }
.controls-map { margin-top: 12px; font-size: 13.5px; }
.controls-map summary { cursor: pointer; color: var(--dim); }
.controls-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
.controls-table th, .controls-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--line); font-size: 13px; }
.controls-table th { color: var(--dim); text-transform: uppercase; font-size: 11px; letter-spacing: 1px; }

/* ---------- ad slots (banner anchors) + preroll ---------- */

.ad-slot {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  margin: 18px 0; position: relative; z-index: 1;
}
.ad-label {
  font-size: 9.5px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--dim); opacity: .75;
}
.ad-placeholder {
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--line); border-radius: 8px;
  background: color-mix(in srgb, var(--panel) 60%, transparent);
  color: var(--dim); font-size: 12px; letter-spacing: 1.5px; font-weight: 700;
}
.ad-slot iframe, .ad-slot img { max-width: 100%; }

.ad-preroll {
  position: absolute; inset: 0; z-index: 25;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  border-radius: calc(var(--radius) + 4px);
  transition: opacity .28s;
}
.ad-preroll.leaving { opacity: 0; pointer-events: none; }
.ad-preroll-inner {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: min(560px, 92%); text-align: center;
}
.preroll-placeholder { width: 100%; height: min(46vh, 300px); font-size: 14px; }
.ad-preroll-status {
  display: flex; align-items: center; gap: 10px; color: var(--dim); font-size: 13px;
}
.ad-loading-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--accent-2);
  animation: boot-blink 1.1s infinite;
}
.ad-skip { border-color: var(--accent-2); color: var(--accent-2); }

/* ---------- mobile emulation profile ---------- */

.mobile-controls-note, .device-switch-note {
  padding: 8px 16px; font-size: 12px; color: var(--dim);
  border-top: 1px dashed var(--line);
}
.mobile-controls-note a, .device-switch-note a { color: var(--accent-2); }

/* Mobile profile: the player owns the viewport — full-bleed, tall,
   thumb-reachable; EmulatorJS's virtual gamepad overlays inside the frame. */
.player-zone.is-mobile .player-frame {
  border-radius: 0; border-left: 0; border-right: 0;
  margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
}
.player-zone.is-mobile .game-screen {
  aspect-ratio: auto;
  height: min(72vh, 560px);
}
@media (max-width: 700px) {
  .player-zone.is-mobile .game-screen { height: 62vh; }
  .player-zone.is-mobile .player-controls .pbtn { padding: 10px 16px; font-size: 14px; } /* thumb targets */
  .fomo-strip { padding: 16px; }
}
/* Landscape phones: emulator becomes the whole show */
@media (max-height: 500px) and (orientation: landscape) {
  .player-zone.is-mobile .game-screen { height: 88vh; }
  .player-zone.is-mobile .mobile-controls-note { display: none; }
}

/* ---------- registration gate (clouded pop-open) ---------- */

.reg-gate { position: absolute; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; }
.reg-gate[hidden] { display: none; }
.reg-cloud {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--bg) 55%, transparent), color-mix(in srgb, var(--bg) 88%, transparent));
  backdrop-filter: blur(2px);
  border-radius: calc(var(--radius) + 4px);
}
.reg-panel {
  position: relative; width: min(430px, 92%);
  background: var(--panel); border: 1px solid var(--accent);
  border-radius: calc(var(--radius) + 4px);
  padding: 26px 26px 20px;
  box-shadow: 0 24px 80px color-mix(in srgb, var(--bg) 30%, transparent), 0 0 34px color-mix(in srgb, var(--accent) 35%, transparent);
  animation: gate-pop .3s cubic-bezier(.2, .9, .3, 1.2);
}
@keyframes gate-pop { from { transform: translateY(14px) scale(.96); opacity: 0; } }
.reg-close {
  position: absolute; top: 10px; right: 12px; background: none; border: 0;
  color: var(--dim); font-size: 22px; cursor: pointer; line-height: 1;
}
.reg-close:hover { color: var(--txt); }
.reg-head .reg-title { font-size: 20px; margin-bottom: 6px; }
.reg-head p { color: var(--dim); font-size: 14px; }
.reg-perks { list-style: none; padding: 10px 0 4px; margin: 0; }
.reg-perks li { font-size: 13.5px; padding: 3px 0; }
.reg-tabs { display: flex; gap: 6px; margin: 12px 0; }
.reg-tab {
  flex: 1; background: var(--panel-2); border: 1px solid var(--line); color: var(--dim);
  border-radius: 8px; padding: 8px; font-size: 13px; cursor: pointer;
}
.reg-tab.on { color: var(--txt); border-color: var(--accent); }
.reg-form label { display: block; font-size: 12.5px; color: var(--dim); margin: 10px 0 4px; }
.reg-form input {
  width: 100%; background: var(--bg-accent); border: 1px solid var(--line); color: var(--txt);
  border-radius: 8px; padding: 10px 12px; font-size: 14px; outline: 0;
}
.reg-form input:focus { border-color: var(--accent); }
.reg-prefs { border: 0; padding: 0; margin: 12px 0 0; }
.reg-prefs legend { font-size: 12.5px; color: var(--dim); margin-bottom: 8px; }
.reg-prefs legend span { opacity: .7; font-size: 11px; }
.reg-pref-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pref-chip input { position: absolute; opacity: 0; pointer-events: none; }
.pref-chip span {
  display: inline-block; font-size: 11.5px; font-weight: 700;
  border: 1px solid var(--line); border-radius: 99px; padding: 4px 11px;
  color: var(--dim); cursor: pointer; transition: .12s; user-select: none;
}
.pref-chip input:checked + span { background: var(--accent); color: var(--bg); border-color: var(--accent); }

.reg-submit {
  width: 100%; margin-top: 14px; background: var(--accent); color: var(--bg);
  font-weight: 800; border: 0; border-radius: 9px; padding: 12px; font-size: 14.5px;
  cursor: pointer; letter-spacing: .5px;
}
.reg-submit:hover { filter: brightness(1.12); }
.reg-submit:disabled { opacity: .6; cursor: wait; }
.reg-error { color: var(--danger); font-size: 13px; margin-top: 8px; }
.reg-fine { color: var(--dim); font-size: 11.5px; margin-top: 10px; text-align: center; }

/* ---------- step 2: the $7 upsell ---------- */

.reg-upsell { text-align: center; }
.upsell-burst { font-size: 34px; animation: trophy-pulse 1.6s ease-in-out infinite; }
.upsell-title { font-size: 21px; margin: 6px 0 2px; }
.upsell-title span {
  color: var(--danger);
  text-shadow: 0 0 14px color-mix(in srgb, var(--danger) 60%, transparent);
}
.upsell-price { margin: 8px 0 12px; }
.upsell-price b { font-size: 38px; color: var(--accent-2); font-family: 'Courier New', monospace; }
.upsell-price span { color: var(--dim); font-size: 12.5px; }
.upsell-perks { list-style: none; margin: 0 0 6px; padding: 0; text-align: left; }
.upsell-perks li { padding: 5px 0; font-size: 13.5px; }
.upsell-tag { color: var(--dim); font-size: 12.5px; font-style: italic; margin-bottom: 12px; }

.pay-tabs { display: flex; gap: 6px; margin-bottom: 10px; }
.pay-tab {
  flex: 1; background: var(--panel-2); border: 1px solid var(--line); color: var(--dim);
  border-radius: 8px; padding: 8px; font-size: 13px; cursor: pointer;
}
.pay-tab.on { color: var(--txt); border-color: var(--accent-2); }
.pay-form { text-align: left; }
.pay-form label { display: block; font-size: 12.5px; color: var(--dim); margin: 8px 0 4px; }
.pay-form input {
  width: 100%; background: var(--bg-accent); border: 1px solid var(--line); color: var(--txt);
  border-radius: 8px; padding: 10px 12px; font-size: 14px; outline: 0;
  font-family: 'Courier New', monospace; letter-spacing: 1px;
}
.pay-form input:focus { border-color: var(--accent-2); }
.pay-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.testmode-ribbon {
  display: block; text-align: center; font-size: 10.5px; font-weight: 800; letter-spacing: 1px;
  color: var(--danger); border: 1px dashed var(--danger); border-radius: 6px;
  padding: 4px 8px; margin-bottom: 4px;
}
.upsell-submit { background: var(--accent-2); }
.paypal-btn {
  width: 100%; padding: 12px; border-radius: 9px; border: 0; cursor: pointer;
  background: #ffc439; color: #253b80; font-weight: 800; font-size: 15px;
}
.paypal-btn b { font-style: italic; }
.paypal-btn b span { color: #179bd7; }
.upsell-success {
  border: 1px solid var(--accent-2); color: var(--accent-2);
  border-radius: 9px; padding: 12px; font-size: 14px; margin-top: 10px;
}
.upsell-skip {
  background: none; border: 0; color: var(--dim); font-size: 12px;
  margin-top: 12px; cursor: pointer; text-decoration: underline;
}
.upsell-skip:hover { color: var(--txt); }

/* ---------- SEO body / FAQ ---------- */

.seo-body { max-width: 76ch; padding: 20px 0; position: relative; z-index: 1; }
.seo-body h2 { font-size: 22px; margin: 26px 0 10px; }
.seo-body p { margin: 10px 0; color: color-mix(in srgb, var(--txt) 88%, var(--dim)); }
.faq-item { border-bottom: 1px solid var(--line); padding: 10px 0; }
.faq-item summary { cursor: pointer; font-weight: 600; font-size: 15px; }
.faq-item p { margin-top: 8px; color: var(--dim); }

/* ---------- purchase CTA ---------- */

.purchase-cta {
  margin: 30px 0; padding: 26px; border-radius: calc(var(--radius) + 6px);
  background: var(--panel); border: 1px solid var(--line); position: relative; z-index: 1;
}
.purchase-cta h2 { font-size: 22px; }
.purchase-sub { color: var(--dim); font-size: 14px; margin: 8px 0 18px; }
.purchase-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; }
.purchase-card {
  display: flex; flex-direction: column; gap: 4px;
  background: var(--bg-accent); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px; text-decoration: none; transition: border-color .15s, transform .15s;
}
.purchase-card:hover { border-color: var(--accent-2); transform: translateY(-3px); }
.purchase-card .merchant { font-size: 11px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--accent-2); font-weight: 800; }
.purchase-card b { font-size: 14.5px; }
.purchase-card .price { color: var(--dim); font-size: 12.5px; }
.purchase-card .go { margin-top: 6px; font-size: 12.5px; color: var(--accent); font-weight: 700; }

/* ---------- report a problem ---------- */

/* R105: the report control moved OUT of .controller-context (which native
   pages hide wholesale, taking the report link with it — David: "there is no
   'Report this game not working' link" on Dreamcast). This wrapper carries the
   horizontal padding the controller bar used to give it, and draws its own
   separator on the native pages where that bar is not rendered. */
.report-zone { padding: 0 16px 12px; }
.player-zone.is-native-only .report-zone { border-top: 1px solid var(--line); padding-top: 12px; }
.report-problem { margin-top: 12px; font-size: 13px; }
.report-problem summary { cursor: pointer; color: var(--dim); }
.report-problem summary:hover { color: var(--danger); }
.report-form { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; align-items: center; }
.report-form select, .report-form input {
  background: var(--bg-accent); border: 1px solid var(--line); color: var(--txt);
  border-radius: 8px; padding: 8px 10px; font-size: 13px; outline: 0;
}
.report-form input { flex: 1; min-width: 200px; }
.report-result { color: var(--accent-2); font-size: 12.5px; width: 100%; }

/* ---------- R128e: "Add Game to My Favorites" star CTA ----------
   David 2026-08-10, with a screenshot: a bright star call-to-action to the
   RIGHT of "Report this game not working", on web AND native Mini App pages.

   The gold is a LITERAL, not a theme var, on purpose. David asked for "bright",
   and the five variants define their accents independently — two of them resolve
   to a muted colour that would read as a disabled control. A fixed gold is the
   only way "bright" is true on all five. (Same reason the Upgrade CTA is gold.)
   `--line` / `--dim` are used for the surrounding chrome because those ARE
   defined by every theme. */
.report-row { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.report-row .report-problem { flex: 1 1 260px; min-width: 0; }  /* min-width:0 or the
   open report form cannot shrink below its content and pushes the CTA off-row */

.fav-cta {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 12px; padding: 9px 16px;
  border: 1px solid #f6c453; border-radius: 999px;
  background: linear-gradient(180deg, #ffd76a, #f0a92a);
  color: #241a02; font-weight: 800; font-size: 13px; letter-spacing: .2px;
  cursor: pointer; white-space: nowrap;
  box-shadow: 0 0 0 rgba(246,196,83,.55);
  transition: box-shadow .18s ease, transform .12s ease, filter .18s ease;
}
.fav-cta:hover { filter: brightness(1.07); box-shadow: 0 0 14px rgba(246,196,83,.55); }
.fav-cta:active { transform: translateY(1px); }
.fav-cta:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.fav-cta .fav-star { fill: #241a02; flex: none; }

/* Already a favourite: stays legible but stops shouting, so a page the player
   has already claimed does not compete with the controls they came to use. */
.fav-cta.is-fav {
  background: transparent; color: #f6c453; border-color: #f6c453;
  box-shadow: none;
}
.fav-cta.is-fav .fav-star { fill: #f6c453; }
.fav-cta.is-fav:hover { background: rgba(246,196,83,.12); }

.fav-cta[disabled] { opacity: .6; cursor: progress; }
.fav-result { font-size: 12.5px; color: var(--accent-2); align-self: center; }
.fav-result.is-warn { color: var(--danger); }

@media (max-width: 560px) {
  .report-row { gap: 10px; }
  .fav-cta { width: 100%; justify-content: center; white-space: normal; }
}

/* ---------- retro arcade animations for competitive CTAs ----------
   Applied to the "competitive call outs": FOMO strip, tournament badge,
   claim/premium CTAs. All gated by prefers-reduced-motion. */

@keyframes insert-coin-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .15; } }
@keyframes trophy-pulse {
  0%, 100% { transform: scale(1) rotate(0deg); filter: drop-shadow(0 0 4px color-mix(in srgb, var(--danger) 60%, transparent)); }
  50% { transform: scale(1.18) rotate(-6deg); filter: drop-shadow(0 0 16px var(--danger)); }
}
@keyframes challenger-flash {
  0%, 92%, 100% { text-shadow: none; }
  94% { text-shadow: 0 0 18px var(--accent-2), 0 0 34px var(--accent-2); }
  96% { text-shadow: none; }
  98% { text-shadow: 0 0 18px var(--accent-2); }
}
@keyframes crt-scan {
  0% { background-position: 0 -120%; }
  100% { background-position: 0 220%; }
}
@keyframes marquee-glow {
  0%, 100% { box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 35%, transparent); }
  50% { box-shadow: 0 0 26px color-mix(in srgb, var(--accent) 70%, transparent); }
}

/* FOMO strip: the kicker blinks like an attract screen, the score value
   flashes like a NEW CHALLENGER prompt, the whole strip breathes neon */
.fomo-kick::after {
  content: " ▮"; animation: insert-coin-blink 1.1s step-end infinite;
}
.fomo-value { animation: challenger-flash 6s linear infinite; }
.fomo-strip { animation: marquee-glow 3.4s ease-in-out infinite; }

/* Trophy iconography pulses on tournament callouts + snapshot button */
.ft-badge { animation: trophy-pulse 2.2s ease-in-out infinite; transform-origin: center; }
.fomo-claim:not(:disabled) { position: relative; overflow: hidden; }
.fomo-claim:not(:disabled)::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--accent-2) 22%, transparent) 50%, transparent 100%);
  background-size: 100% 45%; background-repeat: no-repeat;
  animation: crt-scan 2.6s linear infinite;
}

/* Premium/tournament entry CTAs get the arcade marquee treatment */
.premium-lock .playbig, .ft-cta, .upsell-submit {
  animation: marquee-glow 2.8s ease-in-out infinite;
}
.upsell-burst { display: inline-block; }

/* Leaderboard top spot: champion crown shimmer */
.fomo-board li:first-child .fb-name::after {
  content: " 👑"; display: inline-block;
  animation: trophy-pulse 2.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .fomo-kick::after, .fomo-value, .fomo-strip, .ft-badge,
  .fomo-claim::after, .premium-lock .playbig, .ft-cta, .upsell-submit,
  .fomo-board li:first-child .fb-name::after, .upsell-burst {
    animation: none !important;
  }
}

/* ---------- competitive FOMO strip + tournament ---------- */

.fomo-strip {
  display: grid; grid-template-columns: 1.2fr .8fr; gap: 22px;
  margin: 22px 0; padding: 22px 26px; position: relative; z-index: 1;
  background: linear-gradient(115deg, var(--panel), color-mix(in srgb, var(--accent) 10%, var(--panel)));
  border: 1px solid var(--accent); border-radius: calc(var(--radius) + 4px);
}
.fomo-kick { font-size: 10.5px; font-weight: 900; letter-spacing: 2.5px; color: var(--danger); }
.fomo-line { display: flex; gap: 14px; align-items: baseline; margin: 8px 0; flex-wrap: wrap; }
.fomo-holder { font-size: 20px; font-weight: 800; }
.fomo-value {
  font-size: 26px; font-weight: 900; color: var(--accent-2);
  font-family: 'Courier New', monospace; letter-spacing: 1px;
}
.fomo-tease { color: var(--dim); font-size: 13.5px; max-width: 52ch; }
.fomo-claim { margin-top: 10px; border-color: var(--accent-2); color: var(--accent-2); }
.fomo-signin { color: var(--dim); font-size: 12px; margin-top: 8px; }

.fomo-board { list-style: none; margin: 0; padding: 0; align-self: center; }
.fomo-board li {
  display: grid; grid-template-columns: 30px 1fr auto; gap: 10px;
  padding: 5px 10px; font-size: 13px; border-radius: 7px;
}
.fomo-board li.top-decile { background: color-mix(in srgb, var(--danger) 14%, transparent); }
.fomo-board .fb-rank { color: var(--dim); font-weight: 800; }
.fomo-board .fb-score { font-family: 'Courier New', monospace; color: var(--accent-2); font-weight: 700; }

.fomo-tournament {
  grid-column: 1 / -1; display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  border-top: 1px dashed var(--line); padding-top: 14px; font-size: 13px; color: var(--dim);
}
.ft-badge {
  font-size: 10.5px; font-weight: 900; letter-spacing: 2px; color: var(--bg);
  background: var(--danger); border-radius: 99px; padding: 4px 12px;
}
.fomo-tournament b { color: var(--txt); }
.ft-cta { margin-left: auto; text-decoration: none; padding: 7px 14px; border-radius: 9px; }
@media (max-width: 760px) { .fomo-strip { grid-template-columns: 1fr; } }

/* ---------- premium ---------- */

.premium-lock {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; padding: 24px;
  background:
    radial-gradient(ellipse at center, color-mix(in srgb, var(--accent) 18%, transparent), transparent 70%),
    color-mix(in srgb, var(--bg) 88%, transparent);
}
.premium-lock-badge {
  font-size: 11px; font-weight: 900; letter-spacing: 3px;
  color: var(--danger); border: 1px solid var(--danger);
  border-radius: 99px; padding: 4px 14px;
}
.premium-lock h2 { font-size: 22px; max-width: 30ch; }
.premium-lock p { color: var(--dim); font-size: 13.5px; max-width: 52ch; }
.premium-lock .playbig { text-decoration: none; }
.premium-fine { color: var(--dim); font-size: 12px; margin-top: 8px; }
.premium-flash {
  color: var(--accent-2); font-weight: 600; margin-bottom: 12px;
  border: 1px solid var(--accent-2); border-radius: 9px; padding: 9px 16px; display: inline-block;
}
.premium-active { font-size: 16px; margin-bottom: 12px; }
.hero form { display: inline-block; }
.hero .ghost { cursor: pointer; }
.hero .cta { border: 0; cursor: pointer; font-size: 15px; }

/* ---------- my games (user history) ---------- */

.history-list { display: flex; flex-direction: column; gap: 12px; }
.history-row {
  display: grid; grid-template-columns: 120px 1fr auto; gap: 18px; align-items: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 16px; text-decoration: none; transition: border-color .15s, transform .15s;
}
.history-row:hover { border-color: var(--accent); transform: translateX(4px); }
.hist-art { height: 80px; border-radius: 9px; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.hist-art img { width: 100%; height: 100%; object-fit: cover; }
.hist-body b { font-size: 16px; display: block; margin-bottom: 6px; }
.hist-meta { color: var(--dim); font-size: 12.5px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.hist-resume { color: var(--accent-2); font-weight: 700; font-size: 13px; white-space: nowrap; }
@media (max-width: 640px) { .history-row { grid-template-columns: 84px 1fr; } .hist-resume { display: none; } }

/* ---------- search palette ---------- */

.palette { position: fixed; inset: 0; z-index: 90; display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
.palette[hidden] { display: none; }
.palette-backdrop { position: absolute; inset: 0; background: color-mix(in srgb, var(--bg) 78%, transparent); backdrop-filter: blur(3px); }
.palette-box {
  position: relative; width: min(600px, 92vw);
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  overflow: hidden; box-shadow: 0 30px 80px rgba(0, 0, 0, .5);
}
.palette-input-row { display: flex; align-items: center; gap: 12px; padding: 15px 18px; border-bottom: 1px solid var(--line); color: var(--dim); }
.palette-input-row input { flex: 1; background: none; border: 0; outline: 0; color: var(--txt); font-size: 17px; }
/* R123 — the palette is a real GET form to /search now (the auto-suggest list
   and its .palette-res rows are gone). These four classes shipped with the new
   markup and had NO styles in site.css or ANY of the five theme.css files, which
   is the trap CLAUDE.md names verbatim: "new page containers must reuse a themed
   class ... or four variants render them unstyled". The visible symptom was the
   .sr-only label rendering as literal body text — "Search games" jammed into the
   input row next to the magnifier — on all five themes. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.palette-form { display: block; }
.palette-go {
  flex: 0 0 auto; background: var(--accent); color: var(--bg);
  border: 0; border-radius: 8px; padding: 8px 16px;
  font-weight: 700; font-size: 13.5px; letter-spacing: .02em; cursor: pointer;
}
.palette-go:hover { filter: brightness(1.1); }
.palette-hint { margin: 0; padding: 11px 18px; color: var(--dim); font-size: 12.5px; }
.palette-hint kbd {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 4px;
  padding: 1px 5px; font-size: 11.5px;
}

/* ---------- search page / pagination / footer ---------- */

.search-page-form { display: flex; gap: 10px; margin: 14px 0; }
.search-page-form input {
  /* min-width:0 — a flex item defaults to min-width:auto and refuses to shrink
     below its intrinsic width, so `flex: 1` alone let this row push past narrow
     screens (the search page scrolled sideways on vault and gamebox). */
  flex: 1; min-width: 0; max-width: 480px; background: var(--panel); border: 1px solid var(--line);
  color: var(--txt); border-radius: 10px; padding: 11px 14px; font-size: 15px; outline: 0;
}
.search-page-form button {
  background: var(--accent); color: var(--bg); border: 0; border-radius: 10px;
  padding: 11px 22px; font-weight: 700; cursor: pointer;
}

.pagination { display: flex; gap: 6px; justify-content: center; margin-top: 26px; }

.site-footer {
  border-top: 1px solid var(--line); padding: 30px var(--shell-pad) 44px;
  color: var(--dim); font-size: 12.5px;
  display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  position: relative; z-index: 1;
}
.footer-links a { color: var(--dim); }

/* ---------- responsive ---------- */

@media (max-width: 720px) {
  .main-nav { display: none; }
  .search-trigger { min-width: 0; }
  .card-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .fmeta h2 { font-size: 24px; }
}

/* ===== Online multiplayer (round-19) ===================================== */
.online-btn { position: relative; }
.online-btn .online-badge {
  display: inline-block; margin-left: 7px; padding: 1px 7px; border-radius: 999px;
  background: var(--accent-2); color: var(--bg); font-size: 11px; font-weight: 800;
  letter-spacing: .3px; vertical-align: middle;
}
/* Flashing state: a live room exists — entice the solo player to join. */
.online-btn.someone-online {
  border-color: var(--accent-2);
  animation: onlinePulse 1.15s ease-in-out infinite;
}
.online-btn.someone-online .online-badge { animation: badgeBlink 1.15s steps(1) infinite; }
@keyframes onlinePulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-2) 70%, transparent); }
  50%      { box-shadow: 0 0 10px 3px color-mix(in srgb, var(--accent-2) 60%, transparent); }
}
@keyframes badgeBlink { 0%, 60% { opacity: 1; } 61%, 100% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .online-btn.someone-online, .online-btn.someone-online .online-badge { animation: none; }
  .online-btn.someone-online { box-shadow: 0 0 8px 2px color-mix(in srgb, var(--accent-2) 55%, transparent); }
}

/* Lobby overlay — a viewport-centred modal (fixed so it's always in view). */
.online-lobby {
  position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 82%, transparent); backdrop-filter: blur(3px); padding: 18px;
}
.online-lobby[hidden] { display: none; }
.lobby-card {
  position: relative; width: min(440px, 100%); background: var(--panel); color: var(--fg);
  border: 1px solid var(--line); border-radius: calc(var(--radius) + 2px); padding: 22px 22px 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.lobby-close {
  position: absolute; top: 10px; right: 12px; background: none; border: none; color: var(--dim);
  font-size: 24px; line-height: 1; cursor: pointer;
}
.lobby-close:hover { color: var(--fg); }
.lobby-kick { font-size: 11px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; color: var(--accent-2); }
.lobby-head h3 { margin: 4px 0 6px; font-size: 22px; }
.lobby-status { color: var(--dim); font-size: 14px; margin: 0 0 12px; min-height: 20px; }
.lobby-players { list-style: none; padding: 0; margin: 0 0 12px; display: grid; gap: 6px; }
.lobby-player {
  padding: 9px 12px; border-radius: 8px; background: var(--panel-2); border: 1px solid var(--line);
  font-weight: 600; font-size: 14px;
}
.lobby-player.me { border-color: var(--accent); }
.lobby-player.empty { color: var(--dim); font-weight: 500; font-style: italic; border-style: dashed; }
.lobby-invite label { display: block; font-size: 12px; color: var(--dim); margin-bottom: 5px; }
.lobby-invite-row { display: flex; gap: 6px; }
.lobby-invite-row input {
  flex: 1; min-width: 0; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--bg-accent); color: var(--fg); font-size: 12.5px;
}
.lobby-soon {
  margin: 12px 0; padding: 11px 13px; border-radius: 8px; font-size: 13px; line-height: 1.5;
  background: color-mix(in srgb, var(--accent-2) 12%, var(--panel-2));
  border: 1px solid color-mix(in srgb, var(--accent-2) 40%, var(--line));
}
.lobby-actions { display: flex; gap: 8px; margin-top: 14px; }
.lobby-actions .pbtn { flex: 1; }
.lobby-actions .pbtn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.lobby-local-hint { color: var(--dim); font-size: 12px; line-height: 1.5; margin: 12px 0 0; }
.lobby-local-hint kbd {
  display: inline-block; padding: 1px 5px; border-radius: 4px; background: var(--panel-2);
  border: 1px solid var(--line); font-size: 11px;
}

/* ===== Arcade "Controls for This Game" deck (round-21) =================== */
.game-controls { margin-top: 10px; }
.arcade-deck {
  display: flex; align-items: center; justify-content: center; gap: 34px; flex-wrap: wrap;
  padding: 22px 18px 16px; margin-bottom: 14px;
  background: linear-gradient(180deg, var(--panel-2), color-mix(in srgb, var(--panel) 70%, black));
  border: 1px solid var(--line); border-radius: calc(var(--radius) + 2px);
  box-shadow: inset 0 2px 12px rgba(0,0,0,.45);
}
.deck-stick { text-align: center; }
.stick-graphic { position: relative; width: 84px; height: 84px; margin: 0 auto 8px; }
.stick-base {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 74px; height: 22px; border-radius: 50%;
  background: radial-gradient(ellipse at 50% 30%, var(--panel-2), #000 85%);
  border: 1px solid var(--line);
}
.stick-shaft {
  position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%) rotate(-8deg);
  transform-origin: bottom center; width: 8px; height: 46px; border-radius: 4px;
  background: linear-gradient(90deg, #666, #2c2c34 70%);
}
.stick-ball {
  position: absolute; left: 50%; bottom: 48px; transform: translateX(-58%);
  width: 30px; height: 30px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #ff8888, #d40000 60%, #7a0000);
  box-shadow: 0 3px 8px rgba(0,0,0,.6);
}
.stick-keys { display: flex; gap: 4px; justify-content: center; margin-bottom: 3px; }
.deck-buttons { display: flex; gap: 18px; align-items: flex-end; flex-wrap: wrap; justify-content: center; }
/* R115.3 (David): a 6-button arcade game shows 3-on-top / 3-on-bottom — the
   physical cabinet layout. Cap the flow at 3 per row for the 6-button case only,
   so 4-button decks (e.g. NARC) keep their natural single row. */
.deck-buttons-6 { max-width: 300px; }
.deck-buttons-6 .deck-btn { flex: 0 0 calc(33.333% - 12px); }
.deck-btn { text-align: center; }
.deck-btn-cap {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; margin: 0 auto 7px; border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, color-mix(in srgb, var(--accent) 75%, white), var(--accent) 55%, color-mix(in srgb, var(--accent) 55%, black));
  border: 2px solid color-mix(in srgb, var(--accent) 60%, black);
  box-shadow: 0 4px 10px rgba(0,0,0,.55), inset 0 -3px 6px rgba(0,0,0,.35);
}
.deck-btn:nth-child(even) .deck-btn-cap {
  background: radial-gradient(circle at 34% 28%, color-mix(in srgb, var(--accent-2) 75%, white), var(--accent-2) 55%, color-mix(in srgb, var(--accent-2) 55%, black));
  border-color: color-mix(in srgb, var(--accent-2) 60%, black);
}
.deck-btn-cap .deck-key { background: rgba(0,0,0,.5); }
.deck-key {
  display: inline-block; min-width: 20px; padding: 1px 6px; border-radius: 5px;
  background: rgba(0,0,0,.4); border: 1px solid rgba(255,255,255,.25);
  color: #fff; font: 700 11.5px/1.5 monospace; text-align: center;
}
.deck-label { font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--dim); max-width: 88px; margin: 0 auto; }
.deck-pills { display: flex; flex-direction: column; gap: 8px; }
.deck-pill {
  display: flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--line);
  font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; color: var(--dim);
}

/* ===== ADB screenshot gallery (round-22) ================================= */
.game-gallery {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px; margin: 0 0 26px;
}
.gallery-shot {
  margin: 0; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.gallery-shot img { display: block; width: 100%; height: 150px; object-fit: cover; }
.gallery-shot figcaption {
  padding: 6px 10px; font-size: 11px; font-weight: 700; letter-spacing: .8px;
  text-transform: uppercase; color: var(--dim);
}

/* ===== Hop-in CTA strip (round-21) ======================================= */
.online-cta {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 11px 16px; border-radius: 10px;
  background: color-mix(in srgb, var(--accent-2) 10%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent-2) 45%, var(--line));
  font-size: 14px;
}
.online-cta[hidden] { display: none; }
.online-cta.live { animation: ctaGlow 1.4s ease-in-out infinite; }
.online-cta-btn { border-color: var(--accent-2); white-space: nowrap; }
@keyframes ctaGlow {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-2) 55%, transparent); }
  50%      { box-shadow: 0 0 14px 2px color-mix(in srgb, var(--accent-2) 45%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .online-cta.live { animation: none; box-shadow: 0 0 10px 2px color-mix(in srgb, var(--accent-2) 40%, transparent); }
}

/* ===== Competitive rollback advanced-option (R110) ======================= */
/* The prompted premium upgrade on eligible arcade-fighter pages. Additive to
   in-browser online (which stays the default). Themed with the shared vars so
   all five variants render it — never a bare color (invisible-text trap). */
.rollback-cta {
  margin: 12px 0 4px; padding: 14px 16px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 9%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--line));
  color: var(--txt);
}
.rollback-cta-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.rollback-cta-badge {
  font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; color: var(--bg);
  background: var(--accent); align-self: center;
}
.rollback-cta-title { font-size: 16px; font-weight: 800; color: var(--txt); }
.rollback-cta-sub { font-size: 13px; color: var(--dim); }
.rollback-cta-note { margin: 8px 0 12px; font-size: 13.5px; line-height: 1.5; color: var(--dim); }
.rollback-cta-note b { color: var(--txt); }
.rollback-cta-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }
.rollback-cta-btn {
  display: inline-block; padding: 11px 18px; border-radius: 10px;
  background: var(--accent); color: var(--bg); font-weight: 800; font-size: 14px;
  text-decoration: none; border: 1px solid var(--accent); cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.rollback-cta-btn:hover { transform: translateY(-1px); box-shadow: 0 12px 34px color-mix(in srgb, var(--accent) 52%, transparent); }
.rollback-cta-btn.is-soon { opacity: .7; cursor: default; background: var(--panel-2); color: var(--dim); border-color: var(--line); }
.rollback-cta-btn.is-soon:hover { transform: none; box-shadow: none; }
.rollback-cta-launch { font-size: 13px; color: var(--accent-2); text-decoration: none; }
.rollback-cta-launch:hover { text-decoration: underline; }
.rollback-cta-soon { margin: 4px 0 0; font-size: 12.5px; color: var(--dim); }
.player-zone.is-native-only .rollback-cta { display: none !important; }

/* Toast (local co-op ready etc.) */
.online-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 20px);
  z-index: 90; max-width: min(520px, 92vw); padding: 12px 18px; border-radius: 10px;
  background: var(--panel); color: var(--fg); border: 1px solid var(--accent-2);
  box-shadow: 0 12px 40px rgba(0,0,0,.45); font-size: 14px; opacity: 0; transition: opacity .3s, transform .3s;
}
.online-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ============================================================
   Premium gameplay recording (round-27) — recorder.mjs UI.
   Styles live here (already-loaded site.css); the LOGIC is a
   lazy-imported module, so the game page still ships 0 new JS.
   ============================================================ */
.pbtn-record { border-color: color-mix(in srgb, var(--danger, #ff4d6d) 55%, transparent); }
.pbtn-record:hover { background: color-mix(in srgb, var(--danger, #ff4d6d) 16%, transparent); }

.rec-hud {
  position: absolute; top: 12px; left: 12px; z-index: 40;
  display: flex; align-items: center; gap: 8px;
  font-family: 'Courier New', monospace; font-weight: 700; letter-spacing: 1px;
  background: rgba(10,10,16,.82); color: #fff; border: 1px solid rgba(255,255,255,.18);
  padding: 7px 12px; border-radius: 999px; font-size: 13px; backdrop-filter: blur(3px);
}
.rec-dot { width: 10px; height: 10px; border-radius: 50%; background: #ff3b4e; box-shadow: 0 0 8px #ff3b4e;
  animation: rec-blink 1s steps(2, start) infinite; }
@keyframes rec-blink { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .rec-dot { animation: none; } }
.rec-stop { margin-left: 4px; border: 1px solid rgba(255,255,255,.35); background: transparent; color: #fff;
  border-radius: 999px; padding: 3px 12px; font: inherit; font-size: 12px; cursor: pointer; }
.rec-stop:hover { background: #ff3b4e; border-color: #ff3b4e; }

.rec-modal-back {
  position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  background: rgba(5,5,12,.72); backdrop-filter: blur(4px); padding: 20px;
}
.rec-modal {
  background: var(--surface, #14141f); color: var(--fg, #eee);
  border: 1px solid var(--border, #2a2a3d); border-radius: 16px;
  width: min(560px, 96vw); max-height: 92vh; overflow: auto; padding: 22px; position: relative;
  box-shadow: 0 24px 70px rgba(0,0,0,.55);
}
.rec-modal h3 { margin: 0 0 14px; font-size: 20px; }
.rec-x { position: absolute; top: 12px; right: 14px; background: none; border: none; color: var(--dim, #999);
  font-size: 26px; line-height: 1; cursor: pointer; }
.rec-x:hover { color: var(--fg, #eee); }
.rec-preview { width: 100%; border-radius: 10px; background: #000; aspect-ratio: 4 / 3; }
.rec-meta { font-family: 'Courier New', monospace; font-size: 12.5px; color: var(--dim, #9a9ab0); margin: 10px 0 4px; }
.rec-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.rec-actions .pbtn { text-decoration: none; flex: 1 1 auto; text-align: center; min-width: 150px; }
.rec-status { margin-top: 14px; font-size: 14px; min-height: 1px; }
.rec-ok { color: #46d17a; font-weight: 600; }
.rec-err { color: var(--danger, #ff6b6b); }
.rec-showcase { margin-top: 12px; padding: 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--accent, #22d3ee) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent, #22d3ee) 40%, transparent); }
.rec-showcase p { margin: 0 0 10px; font-size: 13.5px; color: var(--fg, #eee); }

/* ---- live-now discovery strip (round-27 P6b) ---- */
.live-strip { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; }
.live-card { display: flex; align-items: center; gap: 10px; text-decoration: none;
  background: linear-gradient(100deg, color-mix(in srgb, #ff3b4e 22%, var(--panel, #17171f)), var(--panel, #17171f));
  border: 1px solid color-mix(in srgb, #ff3b4e 45%, transparent); border-radius: 12px;
  padding: 9px 14px; color: var(--txt, #eee); transition: transform .15s, border-color .15s; }
.live-card:hover { transform: translateY(-2px); border-color: #ff3b4e; }
.live-dot { width: 9px; height: 9px; border-radius: 50%; background: #ff3b4e; box-shadow: 0 0 8px #ff3b4e;
  animation: rec-blink 1s steps(2, start) infinite; }
.live-live { font-family: 'Courier New', monospace; font-size: 11px; font-weight: 800; letter-spacing: 1px; color: #ff6b7d; }
.live-who { font-size: 13.5px; }
.live-go { margin-left: auto; font-size: 12.5px; color: var(--accent-2, #00d4aa); font-weight: 700; }
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }

/* ---- broadcast (round-27 P6): live HUD + viewer page ---- */
.pbtn-live { border-color: color-mix(in srgb, #ff3b4e 55%, transparent); }
.pbtn-live:hover { background: color-mix(in srgb, #ff3b4e 16%, transparent); }
.rec-hud-live { gap: 6px; }
.rec-hud-live .bcast-viewers { font-variant-numeric: tabular-nums; }
.rec-hud-live .bcast-link { color: var(--accent-2, #00d4aa); text-decoration: underline; font-size: 11px; margin: 0 4px; }

.watch-shell { padding-top: 20px; }
.watch-head { display: flex; align-items: center; gap: 14px; margin: 10px 0 14px; flex-wrap: wrap; }
.watch-head h1 { font-size: clamp(22px, 4vw, 32px); }
.watch-badge { font-family: 'Courier New', monospace; font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
  color: #fff; background: #ff3b4e; border-radius: 999px; padding: 4px 12px; }
.watch-stage { position: relative; width: 100%; aspect-ratio: 4 / 3; max-height: 74vh; background: #000;
  border: 1px solid var(--line, #26262f); border-radius: 14px; overflow: hidden;
  display: flex; align-items: center; justify-content: center; }
.watch-stage .watch-video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.watch-hint { color: var(--dim, #8e8e9d); font-size: 14px; }
.watch-cta { display: flex; gap: 12px; margin-top: 16px; flex-wrap: wrap; align-items: center; }

/* ---- live chat panel (round-27 P5, lazy chat.mjs) ---- */
.chat-panel {
  position: absolute; top: 12px; right: 12px; z-index: 45;
  width: min(320px, 86vw); max-height: min(430px, 70vh);
  display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--panel, #17171f) 92%, transparent);
  border: 1px solid var(--line, #26262f); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0,0,0,.5); backdrop-filter: blur(6px);
}
.chat-head { display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border-bottom: 1px solid var(--line, #26262f); font-size: 14px; }
.chat-status { margin-left: auto; font-family: 'Courier New', monospace; font-size: 11px;
  color: var(--accent-2, #00d4aa); text-transform: uppercase; letter-spacing: .06em; }
.chat-x { background: none; border: none; color: var(--dim, #8e8e9d); font-size: 20px; cursor: pointer; line-height: 1; }
.chat-x:hover { color: var(--txt, #eee); }
.chat-list { list-style: none; margin: 0; padding: 10px 14px; overflow-y: auto; flex: 1;
  display: flex; flex-direction: column; gap: 7px; min-height: 120px; }
.chat-list li { font-size: 13px; line-height: 1.4; overflow-wrap: anywhere; }
.chat-list li b { color: var(--accent-2, #00d4aa); font-weight: 700; margin-right: 6px; }
.chat-list li time { display: inline-block; margin-left: 8px; color: var(--dim, #8e8e9d); font-size: 10.5px; }
.chat-new { animation: chat-pop .25s ease-out; }
@keyframes chat-pop { from { transform: translateY(4px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .chat-new { animation: none; } }
.chat-form { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--line, #26262f); }
.chat-input { flex: 1; background: var(--panel-2, #20202a); border: 1px solid var(--line, #26262f);
  border-radius: 9px; color: var(--txt, #eee); padding: 8px 11px; font: inherit; font-size: 13px; }
.chat-input:focus { outline: none; border-color: var(--accent, #7c5cff); }
.chat-send { flex: 0 0 auto; }
.chat-signin { margin: 0; padding: 10px 14px; border-top: 1px solid var(--line, #26262f);
  color: var(--dim, #8e8e9d); font-size: 12.5px; }

/* "▶ Watch" chip on a Top-Players board entry that has a public showcase run. */
.fb-watch { margin-left: 8px; font-family: 'Courier New', monospace; font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; text-decoration: none;
  color: var(--accent-2, #ff6ec7); border: 1px solid currentColor; border-radius: 999px; padding: 1px 8px;
  cursor: pointer; background: transparent; }
.fb-watch:hover { background: color-mix(in srgb, var(--accent-2, #ff6ec7) 18%, transparent); }

/* R41.4b — per-console controller layout (partials/console-pad) */
.console-pad{margin:14px auto 6px;max-width:420px}
.console-pad svg{width:100%;height:auto;display:block}
.cp-body{fill:rgba(255,255,255,.05);stroke:rgba(255,255,255,.16);stroke-width:1.5}
.cp-shoulder,.cp-pill{fill:rgba(255,255,255,.10);stroke:rgba(255,255,255,.22);stroke-width:1}
.cp-dpad-bar{fill:rgba(255,255,255,.12);stroke:rgba(255,255,255,.22);stroke-width:1}
.cp-face{fill:rgba(139,92,246,.20);stroke:rgba(139,92,246,.65);stroke-width:1.5}
.cp-face-name{fill:#e6e0f8;font:700 11px system-ui,sans-serif;text-anchor:middle}
.cp-btn-name{fill:#8f89a8;font:600 8.5px system-ui,sans-serif;text-anchor:middle;letter-spacing:.4px}
.cp-key{fill:#22d3ee;font:700 11px ui-monospace,Consolas,monospace;text-anchor:middle}
.cp-key.sm{font-size:10px}
.cp-caption{text-align:center;font-size:11.5px;color:var(--dim,#a79fc4);margin-top:4px}

/* R41.5 — chat rebuilt as a floating, draggable popup on <body>: fixed
   BOTTOM-RIGHT (not stuck inside the game frame), above everything, drag by
   the header (cursor set in chat.mjs). Overrides the legacy in-frame rules. */
.chat-panel.chat-float{
  position:fixed; top:auto; right:18px; bottom:18px; left:auto;
  z-index:9999; width:min(320px,86vw); max-height:min(430px,70vh);
  touch-action:none;
}
.chat-panel.chat-float .chat-head{user-select:none}

/* R41.6 — recording HUD: STICKY lower-left of the PAGE (on <body>, outside the
   gameplay box) + unmistakable pulsing ring while recording. Overrides the
   legacy in-frame top-left rules. */
.rec-hud{
  position:fixed; top:auto; left:18px; bottom:18px; z-index:9998;
  animation:rec-glow 1.4s ease-in-out infinite;
}
@keyframes rec-glow{
  0%,100%{box-shadow:0 0 0 0 rgba(228,50,50,.55), 0 8px 26px rgba(0,0,0,.5)}
  50%{box-shadow:0 0 0 9px rgba(228,50,50,0), 0 8px 26px rgba(0,0,0,.5)}
}
.rec-hud .rec-dot{animation:rec-blink 1s steps(2,start) infinite}
@keyframes rec-blink{to{visibility:hidden}}
/* R41.6 — the Play Cloud upload is the primary action */
.rec-upload-primary{
  background:linear-gradient(90deg,#8b5cf6,#22d3ee); color:#fff; font-weight:800;
  border:0; box-shadow:0 6px 18px rgba(139,92,246,.35);
}

/* R42 — shaped pads: PSP handheld + DualShock */
.console-pad-psp{max-width:520px}
.console-pad-dualshock{max-width:460px}
.cp-screen{fill:#0b0a12;stroke:rgba(139,92,246,.5);stroke-width:1.5}
.cp-screen-label{fill:rgba(139,92,246,.35);font:700 26px system-ui,sans-serif;text-anchor:middle;letter-spacing:6px}
.cp-analog{fill:rgba(255,255,255,.08);stroke:rgba(255,255,255,.25);stroke-width:1.2}
.cp-analog-nub{fill:rgba(255,255,255,.16)}
.cp-face-ps{fill:rgba(255,255,255,.06);stroke:rgba(255,255,255,.35)}
.console-pad .cp-face-name{font-size:12px}
/* ===== R120.2 — full console navigation + central profile menu ===== */
.nav-consoles,.nav-profile{position:relative;display:inline-flex}
.nav-consoles-trigger,.nav-profile-trigger{
  display:inline-flex;align-items:center;gap:6px;background:none;border:0;cursor:pointer;
  color:inherit;font:inherit;padding:6px 8px;border-radius:8px}
.nav-consoles-trigger:hover,.nav-profile-trigger:hover,
.nav-consoles-trigger[aria-expanded="true"],.nav-profile-trigger[aria-expanded="true"]{
  background:rgba(255,255,255,.08)}
.nav-consoles-menu,.nav-profile-menu{
  position:absolute;top:calc(100% + 8px);z-index:120;
  background:var(--panel,#17171f);border:1px solid var(--line,#26262f);
  border-radius:12px;box-shadow:0 18px 44px rgba(0,0,0,.5);padding:10px}
.nav-consoles-menu{left:0;width:min(560px,92vw)}
.nav-profile-menu{right:0;min-width:220px;display:flex;flex-direction:column}
/* R120.2 FIX: the panel ships with the `hidden` ATTRIBUTE, but `[hidden]` is only
   `display:none` from the UA stylesheet — any class that sets `display` outranks
   it. `.nav-profile-menu{display:flex}` therefore forced the profile menu OPEN on
   every page of every theme, covering the nav and clipping the H1. `.nav-consoles-menu`
   sets no `display`, which is exactly why the Consoles dropdown stayed correctly
   shut — the two side by side are the proof. Give the attribute its meaning back.
   Any future panel that sets `display` must be added here too. */
.nav-consoles-menu[hidden],.nav-profile-menu[hidden]{display:none}
.nav-consoles-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:4px;
  max-height:min(60vh,420px);overflow-y:auto}
.nav-consoles-grid a{display:flex;justify-content:space-between;align-items:center;gap:8px;
  padding:8px 10px;border-radius:8px;text-decoration:none;font-size:14px}
.nav-consoles-grid a:hover,.nav-consoles-grid a.on{background:rgba(255,255,255,.09)}
.ncm-count{font-size:11px;color:var(--dim,#8e8e9d);font-variant-numeric:tabular-nums}
.nav-profile-name{font-size:13px;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.npm-head{padding:8px 10px 10px;border-bottom:1px solid var(--line,#26262f);margin-bottom:6px;
  display:flex;flex-direction:column;gap:2px}
.npm-head span{font-size:11.5px;color:var(--dim,#8e8e9d)}
.nav-profile-menu a,.npm-signout button{
  display:block;width:100%;text-align:left;padding:8px 10px;border-radius:8px;
  text-decoration:none;font-size:14px;background:none;border:0;color:inherit;font-family:inherit;cursor:pointer}
.nav-profile-menu a:hover,.npm-signout button:hover{background:rgba(255,255,255,.09)}
.npm-signout{margin-top:4px;border-top:1px solid var(--line,#26262f);padding-top:4px}
@media (max-width:720px){
  .nav-consoles-menu{left:auto;right:0;width:min(420px,94vw)}
  .nav-profile-name{display:none}
  /* R120.2 phone header: the profile icon was added to an already-tight row, so
     the search trigger is cramped ("Search games…" wraps, the `Ctrl K` chip
     crowds the icon). `Ctrl K` is a desktop-only affordance — a phone has no
     Ctrl key — so hide it and the label, and keep the button SHRINKABLE.
     Never pin flex-shrink:0 on a header item: doing so removed the only element
     that could absorb slack and pushed the row 125-144px past the viewport
     (16 sweep failures on neon-arcade + playdeck). */
  .search-trigger kbd,.search-trigger span{display:none}
  .search-trigger{min-width:0;flex-shrink:1;justify-content:center}
}
/* R115.6 — Sega Genesis 6-button pad (Sega CD / 32X / Genesis), per David's image */
.console-pad-genesis6{max-width:520px}
.cp-start{fill:#2f4bd6;stroke:#5b73e8;stroke-width:1.2}
.cp-face-xyz{fill:#e3c84a;stroke:#c9ae2f;stroke-width:1.5}
.cp-face-abc{fill:#3a3a44;stroke:rgba(255,255,255,.28);stroke-width:1.5}
.console-pad-genesis6 .cp-face-name{fill:#15151b;font-weight:800}
.console-pad-genesis6 .cp-face-abc + .cp-face-name{fill:#f2f2f7}
/* R116.3 — ColecoVision controller (joystick + 12-key keypad + 2 fire buttons) */
.console-pad-coleco{max-width:540px}
.cp-brand{fill:#e8e8ef;font:800 20px 'Segoe UI',system-ui,sans-serif;letter-spacing:1px}
.cp-ball{fill:#f2f2f7}
.cp-keypad-key{fill:rgba(255,255,255,.07);stroke:rgba(255,255,255,.22);stroke-width:1}
.cp-keypad-lbl{fill:#c9c9d2;font:600 16px 'Segoe UI',system-ui,sans-serif;text-anchor:middle}
.cp-fire{fill:#ededf2;stroke:#c9c9d2;stroke-width:2}
.console-pad-coleco .cp-btn-name{font-size:12px}
.console-pad-coleco .cp-key{font-size:14px}
/* R125 — Intellivision hand controller: a recessed 12-key keypad over a large
   metallic 16-direction disc, four side buttons carrying three signals. Drawn
   to David's supplied reference (intellivision_controller_configuration.png) —
   pale keys in a dark well, lowercase clear/0/enter, silver disc — under the
   HANDOFF ruling that SVG is allowed for these eight consoles provided it
   follows the reference's real parameters. Portrait, so NARROWER than every
   other pad. */
.console-pad-intv{max-width:300px}
.console-pad-intv .cp-body{fill:#26262e;stroke:rgba(255,255,255,.20);stroke-width:1.5}
.console-pad-intv .cp-brand{font:800 12px 'Segoe UI',system-ui,sans-serif;letter-spacing:2px;fill:#9a9aa8}
.cp-keypad-well{fill:rgba(0,0,0,.45);stroke:rgba(255,255,255,.10);stroke-width:1}
.console-pad-intv .cp-keypad-key{fill:#d9d5c8;stroke:#a9a597;stroke-width:1}
.console-pad-intv .cp-keypad-lbl{fill:#2a2a2f;font:700 15px 'Segoe UI',system-ui,sans-serif}
.cp-disc-well{fill:rgba(0,0,0,.45);stroke:rgba(255,255,255,.10);stroke-width:1}
.cp-disc{fill:#b9b6ad;stroke:#8d8a82;stroke-width:2}
.console-pad-intv .cp-fire{fill:#ededf2;stroke:#c9c9d2;stroke-width:1.5}
.console-pad-intv .cp-btn-name{font-size:8px}
/* Key labels drawn ON the pale keypad keys or ON the silver disc need a DARK
   fill — the sitewide cyan (#22d3ee) is near-invisible on either. Carried on an
   explicit class rather than a positional selector, so the labels that sit
   outside the body (the side buttons, on the page background) keep the normal
   cyan and stay readable. Blanket-darkening every .cp-key inside this shape is
   exactly how the "invisible text on 2 of 5 themes" class of bug happens. */
.console-pad-intv .cp-key-dark{fill:#173a5e}

/* R125 — six new console-pad shapes (atari 2600/5200/7800, gb/gbc, gba, lynx).
   Each replaces the generic gamepad body, which drew L/R shoulders and 4 face
   buttons for hardware that has neither. Colours follow the reference images
   in laravel/public/assets/img/ enough to be recognisable, without inventing
   detail (David's ruling: "You can redraw only based on the existing
   parameters of the images"). */
.console-pad-atari2600, .console-pad-atari7800{max-width:260px}
.console-pad-atari2600 .cp-body, .console-pad-atari7800 .cp-body{fill:#1a1a20;stroke:rgba(255,255,255,.20);stroke-width:1.5}
.cp-stick{fill:#101015;stroke:rgba(255,255,255,.18);stroke-width:1.2}
.cp-stick-base{fill:#111117;stroke:rgba(255,255,255,.14);stroke-width:1}
.cp-stick-knob{fill:#e0dccb;stroke:#8d8a7c;stroke-width:1.5}
.cp-fire-red{fill:#c8351d;stroke:#7d1f0f;stroke-width:1.5}

.console-pad-atari5200{max-width:280px}
.console-pad-atari5200 .cp-body{fill:#1a1a20;stroke:rgba(255,255,255,.20);stroke-width:1.5}
.cp-5200-pills .cp-pill-start{fill:#3a8b3a;stroke:#256b25}
.cp-5200-pills .cp-pill-pause{fill:#c4a83a;stroke:#8f7a24}
.cp-5200-pills .cp-pill-reset{fill:#c8351d;stroke:#7d1f0f}
.console-pad-atari5200 .cp-keypad-key{fill:#141419;stroke:rgba(255,255,255,.20)}
.console-pad-atari5200 .cp-keypad-lbl{fill:#c9be3a;font:700 14px 'Segoe UI',system-ui,sans-serif;text-anchor:middle}

.console-pad-gameboy{max-width:320px}
.console-pad-gameboy .cp-gb-body{fill:#c0c1c4;stroke:#7f7f83;stroke-width:1.5}
.console-pad-gameboy .cp-gb-bezel{fill:#3c3c42;stroke:#22222a;stroke-width:1}
.console-pad-gameboy .cp-gb-screen{fill:#8f9f68;stroke:#4c5a32;stroke-width:1}
.cp-face-red{fill:#8a2649;stroke:#5d1732;stroke-width:1.2}
.console-pad-gameboy .cp-face-name, .console-pad-lynx .cp-face-name{fill:#f4ecff}
/* R125 CHILD — the sitewide cyan cp-key (#22d3ee) is near-invisible against
   the Game Boy's light-grey body (1.0:1 measured by verify_new_pad_shapes.py).
   Same pattern as .console-pad-intv .cp-key-dark for the pale keypad keys.
   Applied blanket: every key label inside a gameboy shape is dark navy, which
   has 8.7:1 against the light-grey body and 12+:1 against the dark red faces. */
.console-pad-gameboy .cp-key{fill:#173a5e}

.console-pad-gba{max-width:520px}
.console-pad-gba .cp-gba-body{fill:#3a3fb9;stroke:#232878;stroke-width:1.5}
.console-pad-gba .cp-gb-bezel{fill:#141520;stroke:#0b0c15;stroke-width:1}
.console-pad-gba .cp-gb-screen{fill:#4c4e60;stroke:#2a2c3a;stroke-width:1}
.console-pad-gba .cp-dpad-bar{fill:#c9c9d2;stroke:#8b8b95}
.console-pad-gba .cp-face{fill:#dcdce4;stroke:#8f8f97}
.console-pad-gba .cp-face-name{fill:#1f1f28;font-weight:800}

.console-pad-lynx{max-width:620px}
.console-pad-lynx .cp-lynx-body{fill:#3f414a;stroke:#22232a;stroke-width:1.5}
.console-pad-lynx .cp-gb-bezel{fill:#111116;stroke:#000;stroke-width:1}
.console-pad-lynx .cp-gb-screen{fill:#20232c;stroke:#000;stroke-width:1}
.cp-lynx-dpad-well{fill:rgba(0,0,0,.35);stroke:rgba(255,255,255,.10);stroke-width:1}
.cp-pill-ref{opacity:.42}

/* R129b — Visual Controller Mapper: the player's USB pad drawn beside the
   console pad. player.js polls navigator.getGamepads while the Controllers
   panel is open; a pressed control gets .usb-live, its console action is
   painted into the .usb-assign badge from the ENGINE's value2 truth. */
.mapper-stage{display:flex;flex-wrap:wrap;gap:18px;align-items:flex-start;justify-content:center}
.mapper-stage > *{flex:1 1 320px;min-width:0}
.mapper-stage .console-pad{margin-top:0}
.usb-mapper{max-width:560px;margin:0 auto}
.usb-mapper-head{font-weight:700;font-size:14px;letter-spacing:.5px;margin:2px 0 6px;text-align:center}
.usb-mapper-status{margin:0 0 6px;font-size:12.5px;color:var(--dim);text-align:center;min-height:1.4em}
/* live-state TEXT takes the theme's own accent: hardcoded cyan measured
   1.8:1 on playdeck's white / gamebox's cream panels (mapper_theme_check),
   and every theme defines --accent-2 readable on its own panel. The SHAPE
   light-up below stays cyan on purpose — a filled glow, not text. */
.usb-mapper-status[data-state="live"]{color:var(--accent-2, #22d3ee)}
.usb-mapper-hint{font-size:12px;color:var(--dim);margin:6px 0 0;text-align:center}
.usb-pad svg{width:100%;height:auto;display:block}
.usb-assign{fill:#8f89a8;font:600 8.5px system-ui,sans-serif}
.usb-arrow{fill:rgba(255,255,255,.35);font:700 11px system-ui,sans-serif}
.usb-ctl{cursor:pointer}
/* Light-up: shape fills go accent-cyan; the arrow glyphs recolour. The
   drop-shadow glow reads on every theme because the base shapes are
   translucent white — no per-theme variable needed. */
rect.usb-ctl.usb-live,circle.usb-ctl.usb-live{fill:rgba(34,211,238,.50);stroke:#22d3ee;filter:drop-shadow(0 0 6px rgba(34,211,238,.85))}
text.usb-arrow.usb-live{fill:#22d3ee}

/* R139 — adaptive controller-type picker + per-type controller drawings. The
   <select> swaps which .usb-pad-shape is visible; the light-up JS rescopes to
   the visible one. Colours are explicit (not theme tokens) because they are
   the CONTROLLER's own hardware colours — an N64's blue A, green B, yellow C —
   and read on the dark controls panel every theme shows the mapper in. */
.usb-pad-picker{display:flex;align-items:center;justify-content:center;gap:8px;margin:2px 0 8px;flex-wrap:wrap;min-width:0}
.usb-pad-type-label{font-size:12px;color:var(--dim);display:inline-flex;align-items:center;gap:6px}
.usb-pad-type{background:rgba(255,255,255,.06);color:inherit;border:1px solid rgba(255,255,255,.22);border-radius:6px;padding:3px 8px;font-size:12.5px;font-family:inherit;cursor:pointer}
.usb-pad-type:focus{outline:2px solid var(--accent-2,#22d3ee);outline-offset:1px}
.usb-pad-type option{background:#1b1b24;color:#f0f0f5}
.usb-pad-auto{font-size:11px;color:var(--accent-2,#22d3ee);border:1px solid rgba(34,211,238,.4);border-radius:10px;padding:1px 8px;white-space:nowrap}
.usb-pad-shape[hidden]{display:none}
/* letters on coloured buttons — white with a dark halo reads on blue/green/
   red/yellow/lavender alike, so no per-colour letter juggling. */
.usb-on-color{fill:#fff;font-weight:800;paint-order:stroke;stroke:#0d0d12;stroke-width:2.4px;stroke-linejoin:round}
/* N64 hardware colours */
.usb-n64-body{fill:rgba(210,210,220,.10);stroke:rgba(255,255,255,.22);stroke-width:1.5}
.usb-n64-start{fill:#d23b3b;stroke:#a12a2a;stroke-width:1.5}
.usb-n64-stick{fill:#eceff4;stroke:#b9bdc7;stroke-width:1.2}
.usb-n64-z{fill:#4a4a56;stroke:rgba(255,255,255,.28);stroke-width:1.2}
.usb-n64-a{fill:#3b6fd2;stroke:#2a52a0;stroke-width:1.5}
.usb-n64-b{fill:#2ba361;stroke:#1f7d4a;stroke-width:1.5}
.usb-n64-c{fill:#e3c84a;stroke:#c9ae2f;stroke-width:1.4}
.usb-n64-c-label{fill:#e3c84a;font:800 13px system-ui,sans-serif}
/* SNES lavender faces; Genesis 6-button yellow (top) + dark (bottom) */
.usb-snes-face{fill:#7c74c7;stroke:#5a52a0;stroke-width:1.5}
.usb-genesis-xyz{fill:#e3c84a;stroke:#c9ae2f;stroke-width:1.5}
.usb-genesis-abc{fill:#3a3a44;stroke:rgba(255,255,255,.28);stroke-width:1.5}
kbd.usb-flash{border-color:var(--accent-2, #22d3ee);color:var(--accent-2, #22d3ee);animation:boot-blink .5s 2}
/* R136: the native app-mode map rows are not kbd — clicking a control on the
   Visual Controller Mapper flashes the matching action row here. */
.app-map-row.usb-flash{outline:2px solid var(--accent-2, #22d3ee);outline-offset:2px;border-radius:6px;animation:boot-blink .5s 2}
.cp-key-armable{cursor:pointer}

/* R42 — chat optimistic echo states */
.chat-list li.chat-pending{opacity:.55}
.chat-list li.chat-failed{opacity:.75}
.chat-list li.chat-failed time{color:#ff8fa5}

/* R42 — "What Do You Think About This Game" comments beside the story */
.story-comments-grid{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:26px;align-items:start}
@media (max-width:980px){.story-comments-grid{grid-template-columns:1fr}}
.game-comments{background:var(--panel,#17171f);border:1px solid var(--line,#26262f);border-radius:14px;padding:16px 18px;position:sticky;top:14px}
.game-comments h2{margin:0 0 10px;font-size:17px}
.gc-list{list-style:none;margin:0 0 12px;padding:0;max-height:420px;overflow-y:auto;display:flex;flex-direction:column;gap:10px}
.gc-list li{background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);border-radius:10px;padding:8px 11px;font-size:13.5px;line-height:1.45}
.gc-list li b{color:var(--accent,#8b5cf6);font-size:12.5px;display:block;margin-bottom:2px}
.gc-list li time{display:block;color:var(--dim,#8f89a8);font-size:11px;margin-top:4px}
.gc-list .gc-empty{color:var(--dim,#8f89a8);background:none;border:0;text-align:center}
.gc-form textarea{width:100%;background:rgba(255,255,255,.05);border:1px solid var(--line,#26262f);border-radius:10px;color:inherit;padding:9px 11px;font:inherit;font-size:13.5px;resize:vertical;margin-bottom:8px}
.gc-form .gc-status{margin-left:10px;font-size:12px;color:var(--dim,#8f89a8)}
.gc-signin{color:var(--dim,#8f89a8);font-size:13px}
.gc-pending{opacity:.55}

/* R96 (David): the remap save needs a DISTINGUISHED "definitely saved +
   transferred to the emulator" confirmation, not a quiet status line. The save
   button flashes green with a check, and a badge pops over the pad visual
   naming exactly what happened (live push vs applies-at-launch). Colors are
   self-contained — var(--muted)/theme vars are NOT defined on all variants. */
.app-tool-btn.app-save-flash{background:#1f7a3d;border-color:#2ecc71;color:#eafff1;
  animation:appSavePulse .5s ease-out 2}
@keyframes appSavePulse{0%{box-shadow:0 0 0 0 rgba(46,204,113,.75)}
  100%{box-shadow:0 0 0 14px rgba(46,204,113,0)}}
.app-saved-badge{position:absolute;right:12px;top:12px;z-index:40;pointer-events:none;
  background:linear-gradient(135deg,#123d24,#1f7a3d);border:1px solid #2ecc71;color:#eafff1;
  font-size:13px;font-weight:700;letter-spacing:.02em;padding:9px 14px;border-radius:10px;
  box-shadow:0 6px 22px rgba(0,0,0,.45);display:flex;align-items:center;gap:8px;
  animation:appSavedIn .28s cubic-bezier(.2,.9,.3,1.4),appSavedOut .35s ease-in 2.3s forwards}
.app-saved-badge .tick{width:18px;height:18px;border-radius:50%;background:#2ecc71;color:#06220f;
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:900}
@keyframes appSavedIn{0%{opacity:0;transform:translateY(-8px) scale(.92)}
  100%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes appSavedOut{to{opacity:0;transform:translateY(-6px)}}
/* P1 — public player profile (/player/{username}). Layout only rides on the
   universal theme vars (panel/line/accent/dim/radius) so all five variants
   style it; colors never invent new vars. */
.profile-hero .profile-avatar{width:96px;height:96px;border-radius:18px;border:1px solid var(--line,#26262f);
  box-shadow:0 10px 30px rgba(0,0,0,.35);margin-bottom:12px}
.profile-rank{margin:6px 0 0}
.profile-rank .rank-tag{font-size:13px;padding:5px 14px;text-transform:uppercase;letter-spacing:.08em}
.profile-stats{display:flex;gap:26px;justify-content:center;flex-wrap:wrap;margin-top:18px}
.pstat{display:flex;flex-direction:column;min-width:0}
.pstat b{font-size:clamp(18px,3vw,26px);font-variant-numeric:tabular-nums}
.pstat span{color:var(--dim,#8f89a8);font-size:12px;text-transform:uppercase;letter-spacing:.06em;margin-top:2px}
.profile-about{max-width:60ch;margin-left:auto;margin-right:auto}
.profile-empty{color:var(--dim,#8f89a8);padding:8px 0}
.profile-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.ppanel{position:relative;background:var(--panel,#17171f);border:1px solid var(--line,#26262f);
  border-radius:var(--radius,14px);padding:18px;overflow:hidden;min-width:0}
.ppanel h3{font-size:16px;margin:0}
.ppanel p{color:var(--dim,#8f89a8);font-size:13.5px;line-height:1.5;margin:10px 0 0}
.ppanel-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.ppanel .cta{display:inline-block;margin-top:14px;font-size:13px}
/* Locked premium panel: blurred DECORATIVE bars behind the pitch — pure
   layout shapes, never fake numbers. */
.ppanel.locked{border-style:dashed}
.plock-veil{position:absolute;inset:0;display:flex;flex-direction:column;gap:10px;padding:16px;
  filter:blur(5px);opacity:.35;pointer-events:none}
.plock-veil span{display:block;height:18px;border-radius:6px;
  background:linear-gradient(90deg,var(--accent,#8b5cf6),transparent 80%)}
.plock-veil span:nth-child(2){width:70%;background:linear-gradient(90deg,var(--accent-2,#22d3ee),transparent 85%)}
.plock-veil span:nth-child(3){width:45%}
.plock-body{position:relative;z-index:1}
.profile-videos{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}
.pvideo{margin:0;background:var(--panel,#17171f);border:1px solid var(--line,#26262f);
  border-radius:var(--radius,14px);overflow:hidden;min-width:0}
.pvideo video{display:block;width:100%;aspect-ratio:16/9;background:#000}
.pvideo figcaption{padding:10px 12px 12px;font-size:13.5px}
.pvideo figcaption b{display:block;margin-bottom:6px}
.pvideo-meta{display:flex;align-items:center;gap:8px;color:var(--dim,#8f89a8);font-size:12px}
.pvideo-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.pvideo-tags .tag{font-size:10.5px}
.ppanel .pstand{color:inherit;font-size:14px;margin-top:12px}
.ppanel .pstand b{font-size:22px;font-variant-numeric:tabular-nums}
.pruns{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:8px}
.pruns li{display:flex;align-items:center;gap:10px;font-size:13.5px;min-width:0}
.pruns li a{color:inherit;text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
.pruns li a:hover{color:var(--accent,#8b5cf6)}
.pruns li b{font-variant-numeric:tabular-nums}
.pruns li span{color:var(--dim,#8f89a8);font-size:12px;white-space:nowrap}
.rank-history{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;max-width:520px}
.rank-history li{display:flex;align-items:center;gap:12px;background:var(--panel,#17171f);
  border:1px solid var(--line,#26262f);border-radius:10px;padding:9px 13px;font-size:13.5px}
.rank-history li b{font-variant-numeric:tabular-nums}
.rank-history li time{margin-left:auto;color:var(--dim,#8f89a8);font-size:12px}
@media (max-width:640px){.profile-stats{gap:16px}}
