/* ============================================================
   Wash Street 24 — v3 UI
   "Cross-section laundromat" idle game look & feel
   Display: Fredoka (latin) · 得意黑 SmileySans (CJK)
   ============================================================ */

/* ---------- Local fonts ---------- */
@font-face {
  font-family: 'Fredoka';
  src: url('../assets/fonts/Fredoka-Variable.ttf') format('truetype');
  font-weight: 300 700;
  font-display: swap;
}
@font-face {
  font-family: 'SmileySans';
  src: url('../assets/fonts/SmileySans-Oblique.otf') format('opentype');
  font-weight: 400;
  font-display: swap;
}

/* ---------- Design tokens ---------- */
:root {
  --ink-950: #060913;
  --ink-900: #0a0e1d;
  --ink-800: #10152b;
  --ink-700: #171d3a;
  --ink-600: #20284e;
  --ink-500: #2c3566;

  --teal: #35e0c6;
  --teal-soft: rgba(53, 224, 198, 0.14);
  --gold: #ffbe3d;
  --gold-deep: #e79b12;
  --gold-soft: rgba(255, 190, 61, 0.14);
  --pink: #ff7aa8;
  --pink-soft: rgba(255, 122, 168, 0.14);
  --violet: #b197ff;
  --violet-soft: rgba(177, 151, 255, 0.14);
  --sky: #5ac8ff;
  --sky-soft: rgba(90, 200, 255, 0.14);
  --leaf: #54e08c;
  --leaf-soft: rgba(84, 224, 140, 0.12);

  --paper: #f2f5fc;
  --mist: #a6b0cf;
  --dim: #636d92;

  --line: rgba(255, 255, 255, 0.07);
  --line-strong: rgba(255, 255, 255, 0.13);

  --r-s: 10px;
  --r-m: 16px;
  --r-l: 22px;
  --r-pill: 999px;

  --font-display: 'Fredoka', 'SmileySans', system-ui, sans-serif;
  --font-body: 'Fredoka', 'SmileySans', system-ui, sans-serif;

  --shadow-pop: 0 10px 30px rgba(2, 4, 12, 0.55);

  /* ---- M1.3 neon palette tokens (深夜霓虹色板 2.4 节) ---- */
  --neon-orange: #E9A568;   /* 旧城区 怀旧暖橙 */
  --neon-cyan: #38BDF8;     /* 商业区 科技青 */
  --neon-purple: #C084FC;   /* 艺术区 梦幻紫 */
  --neon-green: #6EE7B7;    /* 港口区 工业绿 */
  --neon-gold: #FBBF24;     /* 豪华区 金黄 */
  --accent-primary: #38BDF8;
  --accent-success: #6EE7B7;
  --accent-warning: #FBBF24;
  --accent-error: #F87171;
  --glow-cyan: 0 0 20px rgba(56, 189, 248, 0.6);
  --glow-orange: 0 0 20px rgba(233, 165, 104, 0.6);
  --shadow-elevated: 0 10px 40px rgba(0, 0, 0, 0.4);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html, body {
  width: 100%;
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  background: var(--ink-950);
  font-family: var(--font-body);
  color: var(--paper);
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

#game-container {
  width: 100%;
  height: 100%;
  height: 100dvh;
  position: relative;
  background:
    radial-gradient(1200px 700px at 50% -10%, rgba(53, 224, 198, 0.05), transparent 60%),
    radial-gradient(900px 600px at 85% 110%, rgba(177, 151, 255, 0.05), transparent 60%),
    var(--ink-950);
}

#game-root {
  width: 100%;
  height: 100%;
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Let Phaser's Scale.FIT + CENTER_BOTH handle all canvas sizing and
   positioning via inline styles. Don't override with our own centering. */
#game-root canvas {
  display: block;
}

/* ============================================================
   Overlay — the "480 column": every HUD layer is pinned to the
   same centered 480px column the canvas FITs into, so HTML and
   Phaser art always share one frame (letterboxed on wide screens).
   ============================================================ */

.ui-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 100;
  display: flex;
  justify-content: center;
}

/* The column is a full-height strip whose WIDTH always matches the Phaser
   canvas width, so horizontal alignment is exact on every ratio. Height is
   100% so the HUD stays glued to the top edge and the dock to the bottom
   edge (thumb-friendly), instead of being pulled up onto the letterboxed
   canvas box on tall (modern) phones. Elements that must overlay the game
   ART (region cards) are aligned to the canvas frame via the --canvas-*
   variables below. */
.ui-col {
  position: relative;
  width: min(100vw, 56.2061vh); /* 480 / 854 = canvas width */
  height: 100%;
  flex-shrink: 0;
}

/* Phaser FIT-scales the 480×854 design into the viewport and letterboxes it.
   These variables reproduce that box so DOM layers can align to the art:
     width  = min(100vw, 480/854 × 100vh)
     height = min(100vh, 854/480 × 100vw)
     top/left = centered offset of that box within the viewport            */
:root {
  --canvas-w: min(100vw, 56.2061vh);
  --canvas-h: min(100vh, 177.9167vw);
  --canvas-top: calc((100vh - var(--canvas-h)) / 2);
  --canvas-left: calc((100vw - var(--canvas-w)) / 2);
  /* Mobile non-fullscreen browsers: the dynamic viewport (dvh) matches the
     Phaser canvas (FIT to #game-container's 100dvh) better than 100vh while
     the URL bar is visible. dvh overrides above when supported; unsupported
     browsers silently keep the vh line. */
  --canvas-w: min(100vw, 56.2061dvh);
  --canvas-h: min(100dvh, 177.9167vw);
  --canvas-top: calc((100dvh - var(--canvas-h)) / 2);
  --canvas-left: calc((100vw - var(--canvas-w)) / 2);
}

.ui-layer { position: absolute; inset: 0; pointer-events: none; }
.ui-layer > * { pointer-events: auto; }

/* Modals / tutorial / title are appended directly to .ui-col, which
   inherits pointer-events:none — re-enable it on the veils themselves. */
.ui-col > .sheet-veil,
.ui-col > .tut-veil,
.ui-col > .title-veil { pointer-events: auto; }

/* ============================================================
   HUD — cash is the hero
   ============================================================ */

.hud {
  position: absolute;
  top: 0; left: 0; right: 0;
  bottom: auto;
  padding: max(8px, env(safe-area-inset-top)) 10px 22px;
  background: linear-gradient(180deg, rgba(14, 24, 52, 0.88) 0%, rgba(12, 21, 45, 0.5) 62%, transparent 100%);
  z-index: 30;
}

.hud-row-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.hud-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.hud-logo {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  overflow: hidden;
  flex-shrink: 0;
  border: 1.5px solid rgba(53, 224, 198, 0.45);
  box-shadow: 0 0 12px rgba(53, 224, 198, 0.25);
}
.hud-logo img { width: 100%; height: 100%; object-fit: cover; }

.hud-tier {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--mist);
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 180px;
}
.hud-tier.chain { color: var(--violet); border-color: rgba(177, 151, 255, 0.35); background: var(--violet-soft); }

.hud-tools { display: flex; gap: 6px; }

.tool-btn {
  width: 34px;
  height: 34px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.06);
  color: var(--mist);
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: transform 0.15s, background 0.2s;
}
.tool-btn:hover { background: rgba(255, 255, 255, 0.12); color: var(--paper); }
.tool-btn:active { transform: scale(0.9); }
.tool-btn .dot {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--pink);
  box-shadow: 0 0 7px var(--pink);
  display: none;
}
.tool-btn .dot.on { display: block; animation: chip-pop 1.4s ease-in-out infinite; }

/* boost chip lives inside the boost tool button */
.boost-chip {
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 22px;
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--pink), #ff5c92);
  color: #1a0710;
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 700;
  text-align: center;
  display: none;
  box-shadow: 0 2px 8px rgba(255, 122, 168, 0.5);
  animation: chip-pop 1s ease-in-out infinite;
}
.boost-chip.active { display: block; }
.boost-chip.cooling {
  display: block;
  background: #2c3554;
  color: #8e97ba;
  box-shadow: none;
  animation: none;
}
@keyframes chip-pop {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

/* --- Cash hero --- */
.hud-cash {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.cash-coin {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  filter: drop-shadow(0 0 8px rgba(255, 190, 61, 0.5));
  animation: coin-spin 5s linear infinite;
}
@keyframes coin-spin {
  0%, 60%, 100% { transform: rotateY(0deg); }
  80% { transform: rotateY(180deg); }
}

.cash-num {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 2px 0 rgba(120, 70, 0, 0.35), 0 0 24px rgba(255, 190, 61, 0.35);
  letter-spacing: 0.5px;
  transition: transform 0.12s;
}
.cash-num.bump { transform: scale(1.07); }

.hud-cps {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  color: var(--teal);
  background: var(--teal-soft);
  border: 1px solid rgba(53, 224, 198, 0.25);
  padding: 3px 9px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

.hud-row-bottom {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 5px;
  font-size: 10px;
  color: var(--dim);
}
.hud-mini { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.hud-mini .sat { color: var(--leaf); font-weight: 600; }

/* mini hot-order chip in HUD bottom row */
.order-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 190, 61, 0.55);
  background: rgba(27, 33, 64, 0.85);
  color: #ffbe3d;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 0 10px rgba(255, 190, 61, 0.22);
}
.order-chip .oc-icon { font-size: 12px; }
.order-chip.ending {
  border-color: rgba(255, 125, 125, 0.8);
  color: #ff7d7d;
  box-shadow: 0 0 12px rgba(255, 125, 125, 0.35);
  animation: chip-pop 0.8s ease-in-out infinite;
}

/* ============================================================
   M1.5 District progress bar — persistent "next zone" goal in HUD
   ============================================================ */
.district-progress {
  margin-top: 6px;
  padding: 7px 10px 7px;
  border-radius: 12px;
  background: rgba(8, 13, 30, 0.55);
  border: 1px solid var(--line);
  border-left: 3px solid var(--neon-cyan);
  font-family: var(--font-body);
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.district-progress .dp-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.district-progress .dp-label {
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--neon-cyan);
  text-shadow: 0 0 8px rgba(56, 189, 248, 0.4);
}
.district-progress .dp-route {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  overflow: hidden;
  font-size: 10px;
}
.district-progress .dp-route b {
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
}
.district-progress .dp-from { color: var(--mist); }
.district-progress .dp-to { color: var(--paper); text-shadow: 0 0 8px rgba(255, 255, 255, 0.25); }
.district-progress .dp-arrow { font-style: normal; color: var(--dim); }
.district-progress .dp-pct {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 11px;
  color: var(--dp-accent, var(--neon-cyan));
  text-shadow: 0 0 8px rgba(56, 189, 248, 0.4);
}
.district-progress .dp-track {
  height: 6px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.district-progress .dp-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--neon-cyan), var(--neon-green));
  box-shadow: 0 0 10px rgba(56, 189, 248, 0.55);
  transition: width 0.4s ease;
}
.district-progress .dp-remain {
  margin-top: 3px;
  font-size: 9px;
  color: var(--dim);
  text-align: right;
}
/* gold flash when a district unlock fires */
.district-progress.celebrate {
  border-color: var(--neon-gold);
  box-shadow: 0 0 20px rgba(251, 191, 36, 0.35);
}
.district-progress.celebrate .dp-fill { animation: dp-celebrate 0.9s ease-out; }
@keyframes dp-celebrate {
  0% { filter: brightness(1); }
  50% { filter: brightness(1.7); }
  100% { filter: brightness(1); }
}
.district-progress.all-open {
  border-left-color: var(--neon-gold);
}
.district-progress.all-open .dp-route { color: var(--neon-gold); font-weight: 700; }
.district-progress.all-open .dp-fill { background: linear-gradient(90deg, var(--neon-gold), var(--neon-orange)); box-shadow: 0 0 10px rgba(251, 191, 36, 0.5); }
.district-progress.all-open .dp-remain { color: var(--neon-gold); font-size: 10px; }

/* Compact on moderately short screens; hidden on very short ones where the
   region cards already expose per-card unlock progress. */
@media (max-height: 720px) {
  .district-progress { padding: 5px 9px 5px; margin-top: 4px; }
  .district-progress .dp-head { margin-bottom: 3px; }
}
@media (max-height: 600px) {
  .district-progress { display: none; }
}
@media (max-width: 375px) {
  .district-progress .dp-label { font-size: 8px; }
  .district-progress .dp-route { font-size: 9px; }
  .district-progress .dp-remain { font-size: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .district-progress.celebrate .dp-fill,
  .district-progress .dp-fill { transition-duration: 0.01s !important; animation: none !important; }
}
.a11y-large-text .district-progress .dp-route { font-size: calc(10px * var(--a11y-scale)); }
.a11y-large-text .district-progress .dp-remain { font-size: calc(9px * var(--a11y-scale)); }
.a11y-large-text .district-progress .dp-pct { font-size: calc(11px * var(--a11y-scale)); }

/* ============================================================
   HTML Region Cards — unified rounded-rect wrapper matching dock
   ============================================================ */

/* Region cards overlay the building art, so they must align to the canvas
   frame (not the full viewport). Pixel analysis of background.webp puts the
   lower edge of the illustrated roof/header at design-y ≈ 216 / 854 (25.3%).
   The ticker is anchored to that real visual edge, with a deliberate 16px
   breathing gap; the cards follow 4px below it. Their bottom edge remains at
   the authored building baseline, so the extra top spacing never crowds the
   register or dock. */
.region-cards-wrap {
  position: absolute;
  left: 10px;
  right: 10px;
  top: calc(var(--canvas-top) + var(--canvas-h) * 0.253 + 42px);
  height: calc(var(--canvas-h) * 0.52 - 25px);
  z-index: 25;
  border-radius: 20px;
  background: rgba(18, 28, 56, 0.94);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  overflow: hidden;
}

/* Live news ticker — a DOM strip parked ABOVE the region-card panel.
   It used to be a Phaser canvas object drawn across the building facade,
   which clipped the walking NPCs. Its top is based on the background's real
   illustrated edge (25.3% of canvas height), not the older logical roofY;
   the 16px offset keeps a visible but tighter breathing gap. */
.news-ticker-bar {
  position: absolute;
  left: 10px;
  right: 10px;
  top: calc(var(--canvas-top) + var(--canvas-h) * 0.253 + 16px);
  height: 22px;
  z-index: 26;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  border-radius: 11px;
  background: rgba(10, 15, 34, 0.96);
  border: 1px solid rgba(53, 224, 198, 0.6);
  box-shadow: 0 4px 14px rgba(2, 4, 12, 0.45), inset 0 0 12px rgba(53, 224, 198, 0.08);
  overflow: hidden;
  pointer-events: none;
  font-family: var(--font-body);
}

.news-ticker-kicker {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  height: 100%;
}

.news-ticker-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ff5d5d;
  box-shadow: 0 0 6px rgba(255, 93, 93, 0.9);
  animation: news-dot-pulse 1.3s ease-in-out infinite;
}

@keyframes news-dot-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.8); }
}

.news-ticker-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #ffbe3d;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.news-ticker-divider {
  width: 1.5px;
  height: 13px;
  background: rgba(53, 224, 198, 0.4);
}

.news-ticker-window {
  position: relative;
  flex: 1 1 auto;
  height: 100%;
  overflow: hidden;
  display: flex;
  align-items: center;
}

.news-ticker-text {
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 700;
  color: #5cf0da;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .news-ticker-dot { animation: none; opacity: 0.85; }
}

.region-cards {
  position: relative;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 5px;
  display: grid;
  grid-template-rows: repeat(var(--region-count, 5), minmax(0, 1fr));
  gap: 2px;
  pointer-events: auto;
}

.region-card {
  position: relative;
  min-width: 0;
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border: 1px solid rgba(var(--region-rgb), 1);
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  font-family: var(--font-body);
  color: var(--paper);
  background: linear-gradient(180deg, rgba(var(--region-rgb), 0.95), rgba(var(--region-rgb), 0.60));
  box-shadow: inset 0 -14px 22px -12px rgba(var(--region-rgb), 1), 0 0 18px rgba(var(--region-rgb), 0.35);
  text-align: left;
  transition: transform 0.12s, border-color 0.18s, background 0.18s;
}

.region-card:hover {
  background: linear-gradient(180deg, rgba(var(--region-rgb), 1), rgba(var(--region-rgb), 0.75));
  border-color: rgba(var(--region-rgb), 1);
}
.region-card:active { transform: scale(0.975); }
.region-cards.has-six .region-card {
  grid-template-columns: 46px minmax(0, 1fr) auto;
  gap: 9px;
  padding: 7px 11px;
}
.region-cards.has-six .region-icon { width: 42px; height: 42px; border-radius: 12px; font-size: 21px; }
.region-cards.has-six .region-name { font-size: 15px; }
.region-cards.has-six .region-kicker { font-size: 9px; }
.region-cards.has-six .region-value { padding: 6px 9px; font-size: 11px; }

.region-card.locked {
  opacity: 0.75;
  border-color: rgba(var(--region-rgb), 0.5);
  background: linear-gradient(180deg, rgba(var(--region-rgb), 0.70), rgba(var(--region-rgb), 0.25));
  box-shadow: inset 0 -14px 22px -12px rgba(var(--region-rgb), 0.5);
}

/* per-region accent: left border + bright text colors matching dock */
.region-card[data-accent="wash"]    { border-left: 3px solid rgba(56,232,208,1); }
.region-card[data-accent="dry"]     { border-left: 3px solid rgba(255,184,77,1); }
.region-card[data-accent="care"]    { border-left: 3px solid rgba(255,107,157,1); }
.region-card[data-accent="leather"] { border-left: 3px solid rgba(201,165,90,1); }
.region-card[data-accent="self"]    { border-left: 3px solid rgba(92,224,138,1); }
.region-card[data-accent="repair"]  { border-left: 3px solid rgba(115,216,255,1); }
.region-card.locked[data-accent]     { border-left-color: rgba(255, 255, 255, 0.2); }

/* bright text colors per region — 10x brightness */
.region-card[data-accent="wash"]    .region-name { color: #f0fffc; text-shadow: 0 0 40px rgba(56,232,208,1), 0 0 20px rgba(56,232,208,1); }
.region-card[data-accent="dry"]     .region-name { color: #fffeed; text-shadow: 0 0 40px rgba(255,184,77,1), 0 0 20px rgba(255,184,77,1); }
.region-card[data-accent="care"]    .region-name { color: #fff5f9; text-shadow: 0 0 40px rgba(255,107,157,1), 0 0 20px rgba(255,107,157,1); }
.region-card[data-accent="leather"] .region-name { color: #fffdf2; text-shadow: 0 0 40px rgba(201,165,90,1), 0 0 20px rgba(201,165,90,1); }
.region-card[data-accent="self"]    .region-name { color: #f0fff5; text-shadow: 0 0 40px rgba(92,224,138,1), 0 0 20px rgba(92,224,138,1); }
.region-card[data-accent="repair"]  .region-name { color: #f2fbff; text-shadow: 0 0 40px rgba(115,216,255,1), 0 0 20px rgba(115,216,255,1); }

.region-card[data-accent="wash"]    .region-kicker { color: #e0fff8; text-shadow: 0 0 20px rgba(56,232,208,1); }
.region-card[data-accent="dry"]     .region-kicker { color: #fff5d0; text-shadow: 0 0 20px rgba(255,184,77,1); }
.region-card[data-accent="care"]    .region-kicker { color: #ffe0ec; text-shadow: 0 0 20px rgba(255,107,157,1); }
.region-card[data-accent="leather"] .region-kicker { color: #fff0c0; text-shadow: 0 0 20px rgba(201,165,90,1); }
.region-card[data-accent="self"]    .region-kicker { color: #d8ffd8; text-shadow: 0 0 20px rgba(92,224,138,1); }
.region-card[data-accent="repair"]  .region-kicker { color: #dff7ff; text-shadow: 0 0 20px rgba(115,216,255,1); }

.region-glow {
  position: absolute;
  inset: -30%;
  background:
    radial-gradient(circle at 8% 42%, rgba(var(--region-rgb), 0.90), transparent 25%),
    radial-gradient(circle at 96% 16%, rgba(255,255,255,0.50), transparent 20%);
  pointer-events: none;
}

.region-icon {
  position: relative;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border-radius: 15px;
  background: linear-gradient(180deg, rgba(var(--region-rgb), 0.95), rgba(var(--region-rgb), 0.40));
  border: 1.2px solid rgba(var(--region-rgb), 1);
  font-size: 24px;
  line-height: 1;
  text-shadow: 0 2px 4px rgba(0,0,0,0.48);
  box-shadow: inset 0 -12px 18px -12px rgba(var(--region-rgb), 1), 0 0 20px rgba(var(--region-rgb), 0.60);
}
.region-card.locked .region-icon { opacity: 0.88; filter: grayscale(0.12); }

.region-copy {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.region-kicker {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  opacity: 0.95;
  text-shadow: 0 1px 2px rgba(0,0,0,0.45);
}

.region-name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.25px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.region-value {
  position: relative;
  justify-self: end;
  max-width: 116px;
  padding: 7px 11px;
  border-radius: var(--r-pill);
  background: rgba(4, 8, 22, 0.26);
  border: 1px solid rgba(255,255,255,0.20);
  color: rgba(255,255,255,0.92);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgba(0,0,0,0.45);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 0 10px rgba(0,0,0,0.16);
}

.region-card.locked .region-name { opacity: 0.85; }
.region-card.locked .region-value { color: rgba(255,255,255,0.86); }

/* mini unlock-progress bar on locked region cards */
.region-progress {
  grid-column: 1 / -1;
  position: relative;
  display: block;
  height: 8px;
  margin-top: 2px;
  border-radius: var(--r-pill);
  background: rgba(3, 7, 20, 0.42);
  border: 1px solid rgba(255,255,255,0.14);
  overflow: hidden;
}
.region-progress i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, rgba(var(--region-rgb), 0.9), var(--region-accent));
  box-shadow: 0 0 8px rgba(var(--region-rgb), 0.65);
  transition: width 0.4s ease;
}
.region-progress em {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-style: normal;
  font-size: 7px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: rgba(255,255,255,0.92);
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
  line-height: 1;
}

@media (max-height: 720px) {
  .region-cards-wrap { top: calc(var(--canvas-top) + var(--canvas-h) * 0.253 + 42px); height: calc(var(--canvas-h) * 0.512 - 25px); }
  .region-cards { padding: 4px; gap: 1px; }
  .region-card,
  .region-cards.has-six .region-card { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 7px; padding: 4px 8px; border-radius: 11px; }
  .region-icon,
  .region-cards.has-six .region-icon { width: 29px; height: 29px; font-size: 16px; border-radius: 9px; }
  .region-copy { gap: 1px; }
  .region-name,
  .region-cards.has-six .region-name { font-size: 12px; }
  .region-value,
  .region-cards.has-six .region-value { max-width: 82px; padding: 4px 7px; font-size: 9px; }
  .region-kicker,
  .region-cards.has-six .region-kicker { font-size: 7px; }
  .region-progress { height: 6px; margin-top: 0; }
  .region-progress em { font-size: 6px; }
}

@media (max-height: 600px) {
  .region-cards-wrap { height: calc(var(--canvas-h) * 0.40 - 18px); }
  .region-card,
  .region-cards.has-six .region-card { grid-template-columns: 27px minmax(0, 1fr) auto; gap: 5px; padding: 2px 6px; }
  .region-icon,
  .region-cards.has-six .region-icon { width: 24px; height: 24px; font-size: 14px; border-radius: 7px; }
  .region-kicker,
  .region-cards.has-six .region-kicker,
  .region-progress { display: none; }
  .region-name,
  .region-cards.has-six .region-name { font-size: 11px; }
  .region-value,
  .region-cards.has-six .region-value { max-width: 76px; padding: 3px 6px; font-size: 8px; }
}

/* 窄屏（宽度受限导致画布变矮、卡片行高缩小）：图标缩到与短行匹配，避免 emoji 底部被裁 */
@media (max-width: 384px) {
  .region-card,
  .region-cards.has-six .region-card { grid-template-columns: 26px minmax(0, 1fr) auto; gap: 5px; padding: 3px 7px; }
  .region-icon,
  .region-cards.has-six .region-icon { width: 24px; height: 24px; font-size: 14px; border-radius: 7px; }
  .region-value,
  .region-cards.has-six .region-value { max-width: 76px; padding: 3px 6px; font-size: 8px; }
}

/* ============================================================
   Bottom Dock — 4 chunky, candy-colored tiles
   ============================================================ */

.dock {
  position: absolute;
  left: 10px; right: 10px;
  bottom: max(10px, env(safe-area-inset-bottom));
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  padding: 8px;
  border-radius: 20px;
  background: rgba(18, 28, 56, 0.94);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-pop);
  /* Higher than the modal veil (200) so the dock stays visible & clickable
     while a centered sheet is open — the buttons act as tab switchers. */
  z-index: 210;
  transition: box-shadow 0.25s, border-color 0.25s;
}
/* When a sheet is open, the dock lifts a touch and glows to signal that
   its buttons double as panel tabs. */
body.modal-open .dock {
  border-color: rgba(53, 224, 198, 0.35);
  box-shadow: var(--shadow-pop), 0 0 26px rgba(53, 224, 198, 0.16);
}
body.modal-open .dock-btn.active-tab {
  filter: brightness(1.25);
  transform: translateY(-2px);
}

/* ============================================================
   M2.5 — extreme-short-screen compaction (JS sets .short-screen on
   <body> when innerHeight < 600). Pairs with the existing max-height
   media queries: those shrink region cards / hide the district bar;
   this tightens HUD + dock so the scene gets more vertical room and
   mis-taps near the bottom are less likely.
   ============================================================ */
body.short-screen .hud {
  padding: max(6px, env(safe-area-inset-top)) 10px 10px;
}
body.short-screen .hud-row-top { margin-bottom: 3px; }
body.short-screen .dock {
  padding: 6px;
  border-radius: 16px;
  gap: 6px;
}
body.short-screen .dock-btn {
  min-height: 0;
  padding: 5px 4px;
  border-radius: 12px;
}
body.short-screen .dock-icon { font-size: 19px; }
body.short-screen .dock-label { font-size: 8.5px; }


.dock-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 10px 2px 9px;
  border-radius: 14px;
  border: 1px solid transparent;
  cursor: pointer;
  overflow: hidden;
  font-family: var(--font-body);
  transition: transform 0.12s, filter 0.2s;
}
.dock-btn:hover { filter: brightness(1.2); }
.dock-btn:active { transform: scale(0.92); }

.dock-icon { font-size: 23px; line-height: 1; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.4)); }
.dock-label {
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.4px;
  opacity: 0.92;
}

.dock-btn .dot {
  position: absolute;
  top: 6px; right: 8px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--leaf);
  box-shadow: 0 0 8px var(--leaf);
  display: none;
  animation: chip-pop 1.4s ease-in-out infinite;
}
.dock-btn .dot.on { display: block; }

/* per-tab flavors — bold, distinct, game-y */
.dock-btn[data-accent="machines"] {
  background: linear-gradient(180deg, rgba(53, 224, 198, 0.28), rgba(53, 224, 198, 0.06));
  border-color: rgba(53, 224, 198, 0.4);
  color: #7df3e0;
  box-shadow: inset 0 -14px 22px -12px rgba(53, 224, 198, 0.35);
}
.dock-btn[data-accent="upgrades"] {
  background: linear-gradient(180deg, rgba(255, 190, 61, 0.28), rgba(255, 190, 61, 0.06));
  border-color: rgba(255, 190, 61, 0.4);
  color: #ffd47a;
  box-shadow: inset 0 -14px 22px -12px rgba(255, 190, 61, 0.35);
}
.dock-btn[data-accent="branch"] {
  background: linear-gradient(180deg, rgba(177, 151, 255, 0.28), rgba(177, 151, 255, 0.06));
  border-color: rgba(177, 151, 255, 0.4);
  color: #cdbaff;
  box-shadow: inset 0 -14px 22px -12px rgba(177, 151, 255, 0.35);
}
.dock-btn[data-accent="stats"] {
  background: linear-gradient(180deg, rgba(90, 200, 255, 0.28), rgba(90, 200, 255, 0.06));
  border-color: rgba(90, 200, 255, 0.4);
  color: #9adfff;
  box-shadow: inset 0 -14px 22px -12px rgba(90, 200, 255, 0.35);
}

/* ============================================================
   Sheet (modal) system
   ============================================================ */

/* Veils are children of .ui-col (which is sized to the canvas frame), but
   they must cover the WHOLE screen — so use position:fixed. The panel is
   centered (not bottom-anchored) so the dock below stays reachable. */
.sheet-veil {
  position: fixed;
  inset: 0;
  background: rgba(4, 6, 14, var(--veil-alpha, 0.78));
  backdrop-filter: blur(var(--veil-blur, 7px));
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  animation: veil-in 0.22s ease;
}
@keyframes veil-in { from { opacity: 0; } to { opacity: 1; } }

/* On desktop the veil is full-screen; cap the sheet to the 480-column
   width so it stays visually anchored to the game frame. Rounded on all
   corners — it's a centered floating panel now, not a bottom sheet. */
.sheet {
  width: 100%;
  max-width: min(100vw, 56.2061vh);
  max-height: 74vh;
  background: linear-gradient(180deg, var(--ink-800) 0%, var(--ink-900) 100%);
  border-radius: 22px;
  border: 1px solid var(--line-strong);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(53, 224, 198, 0.06);
  animation: sheet-pop 0.32s cubic-bezier(0.18, 1.1, 0.3, 1);
  touch-action: manipulation;
}
@keyframes sheet-pop {
  from { transform: translateY(24px) scale(0.94); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

.sheet-grab {
  width: 42px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.14);
  margin: 9px auto 0;
  flex-shrink: 0;
}

.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 18px 10px;
  flex-shrink: 0;
}

.sheet-title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  color: var(--paper);
  letter-spacing: 0.3px;
}

.sheet-x {
  width: 32px; height: 32px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.06);
  color: var(--mist);
  font-size: 14px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: all 0.2s;
}
.sheet-x:hover { background: rgba(248, 113, 113, 0.16); color: #ff8f8f; border-color: rgba(248, 113, 113, 0.35); }
.sheet-x:active { transform: scale(0.9); }

/* --- Tabs --- */
.sheet-tabs {
  display: flex;
  gap: 8px;
  padding: 0 18px 10px;
  flex-shrink: 0;
}
.sheet-tab {
  flex: 1;
  padding: 9px 0 8px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--dim);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.2s;
}
.sheet-tab:hover { color: var(--mist); }
.sheet-tab.active {
  color: var(--teal);
  background: var(--teal-soft);
  border-color: rgba(53, 224, 198, 0.4);
  box-shadow: 0 0 14px rgba(53, 224, 198, 0.12);
}
.sheet-tab.active.tab-amber {
  color: var(--gold);
  background: var(--gold-soft);
  border-color: rgba(255, 190, 61, 0.4);
  box-shadow: 0 0 14px rgba(255, 190, 61, 0.12);
}

.sheet-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px 14px 24px;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
}
.sheet-body *:focus { outline: none; }
.sheet-body::-webkit-scrollbar { width: 3px; }
.sheet-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 3px; }

/* First-visit strategy tip shown inside the device / upgrade panels */
.shop-strategy-tip {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 6px 0 12px;
  padding: 10px 12px;
  border-radius: 12px;
  font-size: 12px;
  line-height: 1.5;
  color: #bfe9ff;
  background: linear-gradient(135deg, rgba(56,232,208,0.12), rgba(120,160,255,0.10));
  border: 1px solid rgba(120,200,255,0.22);
  animation: strategy-tip-in 0.28s ease;
}
.shop-strategy-tip .t-ic { font-size: 15px; line-height: 1.4; }
@keyframes strategy-tip-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* ============================================================
   Store cards
   ============================================================ */

/* bulk-buy selector row (×1 / ×10 / ×100 / MAX) */
.bulk-bar {
  display: flex;
  gap: 7px;
  margin: 2px 0 10px;
  position: sticky;
  top: -4px;
  z-index: 2;
  background: linear-gradient(180deg, var(--ink-900), rgba(10, 15, 34, 0.92));
  padding: 6px 2px;
}
.bulk-btn {
  flex: 1;
  padding: 6px 0;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(18, 26, 52, 0.85);
  color: var(--dim);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.08s ease, border-color 0.15s ease, color 0.15s ease;
}
.bulk-btn:active { transform: scale(0.94); }
.bulk-btn.on {
  color: #081018;
  background: linear-gradient(135deg, var(--teal), #25b8a8);
  border-color: var(--teal);
  box-shadow: 0 0 12px rgba(53, 224, 198, 0.4);
}

.card {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 12px;
  margin-bottom: 9px;
  border-radius: var(--r-m);
  background: linear-gradient(140deg, var(--ink-700), var(--ink-800));
  border: 1px solid var(--line);
  transition: border-color 0.2s, box-shadow 0.2s;
  position: relative;
}
.card:hover { border-color: var(--line-strong); }

/* M1.4 purchase-success pop — the device card snaps with a cyan flash */
.card.pop { animation: card-pop 0.42s cubic-bezier(0.18, 1.4, 0.4, 1); }
@keyframes card-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.045); box-shadow: 0 0 26px rgba(56, 189, 248, 0.55), 0 0 0 1px rgba(56, 189, 248, 0.65); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .card.pop { animation: none; box-shadow: 0 0 18px rgba(56, 189, 248, 0.5); }
}

.card.can-buy {
  border-color: rgba(53, 224, 198, 0.45);
  box-shadow: 0 0 0 1px rgba(53, 224, 198, 0.12), 0 4px 18px rgba(53, 224, 198, 0.08);
}

.card.locked-card {
  opacity: 0.45;
  filter: grayscale(0.6) brightness(0.8);
}
.card.locked-card::after {
  content: '🔒';
  position: absolute;
  right: 12px; top: 50%;
  transform: translateY(-50%);
  font-size: 15px;
}

.card.maxed-card { border-color: rgba(255, 190, 61, 0.3); }

.card-icon {
  width: 54px; height: 54px;
  border-radius: 13px;
  background: var(--ink-600);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 26px;
  flex-shrink: 0;
  overflow: hidden;
  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.35);
}
.card-icon img { width: 100%; height: 100%; object-fit: cover; }

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

.card-name {
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--paper);
  margin-bottom: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.card-desc {
  font-size: 10.5px;
  color: var(--dim);
  line-height: 1.35;
  margin-bottom: 4px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-meta { display: flex; align-items: center; gap: 8px; font-size: 10px; }
.meta-cps { color: var(--teal); font-weight: 600; }
.meta-owned { color: var(--mist); }

.lv-dots { display: inline-flex; gap: 2.5px; }
.lv-dots i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
}
.lv-dots i.f { background: var(--gold); box-shadow: 0 0 5px rgba(255, 190, 61, 0.6); }

.card-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex-shrink: 0;
}

.card-price {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  color: var(--gold);
}
.card-price.broke { color: #ff7d7d; }

.btn-buy {
  padding: 7px 17px;
  border-radius: var(--r-pill);
  border: none;
  background: linear-gradient(180deg, #43ecca, #17b89d);
  color: #052a22;
  font-family: var(--font-display);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(53, 224, 198, 0.35), inset 0 1px 0 rgba(255,255,255,0.4);
  transition: transform 0.12s, box-shadow 0.2s;
}
.btn-buy:hover {
  box-shadow: 0 4px 18px rgba(56, 189, 248, 0.6), 0 0 24px rgba(56, 189, 248, 0.35), inset 0 1px 0 rgba(255,255,255,0.4);
  filter: brightness(1.06);
}
.btn-buy:active {
  transform: scale(0.92);
  box-shadow: 0 0 26px rgba(56, 189, 248, 0.7), inset 0 1px 0 rgba(255,255,255,0.4);
}
.btn-buy:disabled {
  background: var(--ink-600);
  color: var(--dim);
  box-shadow: none;
  cursor: not-allowed;
  filter: none;
}
.btn-buy.btn-gold {
  background: linear-gradient(180deg, #ffce6a, #eda317);
  color: #3a2600;
  box-shadow: 0 3px 10px rgba(255, 190, 61, 0.35), inset 0 1px 0 rgba(255,255,255,0.45);
}
.btn-buy.btn-gold:hover {
  box-shadow: 0 4px 18px rgba(251, 191, 36, 0.6), 0 0 24px rgba(251, 191, 36, 0.35), inset 0 1px 0 rgba(255,255,255,0.45);
}
.btn-buy.btn-max {
  background: var(--gold-soft);
  color: var(--gold);
  cursor: default;
  box-shadow: none;
}

/* ============================================================
   Quest board
   ============================================================ */

.quest-rep-line {
  padding: 8px 10px;
  margin-bottom: 12px;
  border: 1px solid rgba(255, 190, 61, 0.28);
  border-radius: 8px;
  background: rgba(255, 190, 61, 0.08);
  color: var(--gold);
  font-size: 12px;
}
.quest-section { margin-bottom: 16px; }
.quest-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 7px;
  color: var(--mist);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
}
.quest-refresh { color: var(--dim); font-size: 10px; font-weight: 500; }
.quest-row {
  min-height: 66px;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) 84px;
  align-items: center;
  gap: 8px;
  padding: 8px 6px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.quest-row.ready { background: rgba(92, 224, 138, 0.06); }
.quest-row.claimed { opacity: 0.56; }
.quest-ic { font-size: 21px; text-align: center; }
.quest-copy { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.quest-name {
  color: var(--paper);
  font-size: 11.5px;
  line-height: 1.25;
  white-space: normal;
  overflow-wrap: anywhere;
}
.quest-bar {
  height: 5px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,0.08);
  overflow: hidden;
}
.quest-bar i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--teal);
  transition: width 0.3s ease;
}
.quest-prog { color: var(--dim); font-size: 9.5px; }
.quest-reward { display: flex; flex-direction: column; align-items: stretch; gap: 2px; text-align: right; }
.quest-cash { color: var(--gold); font-size: 10px; }
.quest-rep { color: var(--violet); font-size: 9.5px; }
.quest-claim {
  width: 84px;
  height: 24px;
  padding: 0 6px;
  border: 0;
  border-radius: 6px;
  background: var(--leaf);
  color: #06130b;
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 700;
  cursor: pointer;
}
.quest-claim:disabled { background: rgba(255,255,255,0.08); color: var(--dim); cursor: default; }
.quest-note { color: var(--dim); font-size: 10.5px; line-height: 1.45; padding: 2px 4px 8px; }

/* 28-day season reward track */
.season-panel {
  margin: 0 0 14px;
  padding: 10px;
  border: 1px solid color-mix(in srgb, var(--season-accent) 40%, transparent);
  border-radius: 9px;
  background: color-mix(in srgb, var(--season-accent) 8%, rgba(10,14,29,0.9));
}
.season-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.season-head > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.season-head b { color: var(--paper); font-size: 12px; }
.season-head small { color: var(--dim); font-size: 8.5px; }
.season-head strong { color: var(--season-accent); font-size: 10px; white-space: nowrap; }
.season-theme { margin: 7px 0 5px; color: var(--season-accent); font-family: var(--font-display); font-size: 16px; font-weight: 700; }
.season-xp { position: relative; height: 14px; overflow: hidden; border-radius: 7px; background: rgba(255,255,255,0.07); }
.season-xp i { position: absolute; inset: 0 auto 0 0; background: var(--season-accent); opacity: 0.7; }
.season-xp span { position: relative; z-index: 1; display: block; text-align: center; color: var(--paper); font-size: 8px; line-height: 14px; }
.season-stats { display: flex; justify-content: space-between; gap: 8px; padding: 6px 1px; color: var(--mist); font-size: 9px; }
.season-stats b { color: var(--gold); }
.season-track { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; max-height: 224px; overflow-y: auto; }
.season-level { display: grid; grid-template-columns: 22px minmax(0, 1fr) 48px; align-items: center; gap: 5px; min-height: 38px; padding: 4px 5px; border: 1px solid rgba(255,255,255,0.07); border-radius: 6px; background: rgba(10,14,29,0.62); }
.season-level.locked { opacity: 0.55; }
.season-level.claimed { border-color: rgba(92,224,138,0.28); }
.season-level-num { display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--season-accent); color: #07101b; font-size: 9px; font-weight: 800; }
.season-level-copy { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.season-level-copy b { overflow: hidden; color: var(--mist); font-size: 7.5px; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
.season-level-copy small { color: var(--dim); font-size: 7px; }
.season-claim { width: 48px; min-height: 23px; padding: 2px; border: 1px solid var(--season-accent); border-radius: 5px; background: color-mix(in srgb, var(--season-accent) 16%, transparent); color: var(--paper); font-size: 7.5px; cursor: pointer; }
.season-claim:disabled { border-color: var(--line); background: rgba(255,255,255,0.04); color: var(--dim); cursor: default; }
@media (max-width: 360px) {
  .season-track { grid-template-columns: 1fr; max-height: 210px; }
  .season-level { grid-template-columns: 22px minmax(0, 1fr) 54px; }
  .season-claim { width: 54px; }
}

/* ============================================================
   Branch specialization
   ============================================================ */

.specialization-picker,
.specialization-current {
  width: 100%;
  margin: 10px 0 2px;
  border: 1px solid rgba(167, 139, 250, 0.28);
  border-radius: 8px;
  background: rgba(167, 139, 250, 0.07);
}
.specialization-picker { padding: 10px; }
.specialization-heading {
  color: var(--paper);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
}
.specialization-note {
  margin: 3px 0 8px;
  color: var(--dim);
  font-size: 9.5px;
  line-height: 1.35;
}
.specialization-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.specialization-choice,
.specialization-current {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.specialization-choice {
  min-height: 72px;
  padding: 7px 6px;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 7px;
  background: rgba(10, 14, 29, 0.66);
  color: var(--paper);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.16s, background 0.16s, transform 0.12s;
}
.specialization-choice:hover,
.specialization-choice:focus-visible {
  border-color: var(--violet);
  background: rgba(167, 139, 250, 0.13);
  outline: 2px solid transparent;
}
.specialization-choice:active { transform: scale(0.98); }
.specialization-current { padding: 9px 10px; }
.specialization-icon { font-size: 22px; line-height: 1; text-align: center; }
.specialization-copy { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.specialization-copy b { color: var(--paper); font-size: 10.5px; line-height: 1.2; }
.specialization-copy span { color: var(--mist); font-size: 8.5px; line-height: 1.3; overflow-wrap: anywhere; }

@media (max-width: 360px), (max-height: 650px) {
  .specialization-grid { grid-template-columns: 1fr; }
  .specialization-choice { min-height: 48px; grid-template-columns: 26px minmax(0, 1fr); }
  .specialization-picker { padding: 8px; }
}

/* ============================================================
   Intel sections
   ============================================================ */

.intel-block { margin-bottom: 16px; }

.intel-label {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1.8px;
  color: var(--dim);
  margin-bottom: 8px;
  padding-left: 2px;
}

.intel-note {
  font-size: 10.5px;
  color: var(--teal);
  margin: -4px 0 8px 2px;
  opacity: 0.9;
}

/* Reputation tree and permanent collection */
.reputation-balance {
  padding: 7px 9px;
  margin-bottom: 8px;
  border-block: 1px solid rgba(255, 190, 61, 0.18);
  color: var(--gold);
  font-size: 11px;
}
.reputation-tree { display: grid; gap: 10px; }
.reputation-route { border-top: 1px solid rgba(255,255,255,0.08); padding-top: 7px; }
.reputation-route-head { margin-bottom: 4px; color: var(--paper); font-size: 11px; font-weight: 700; }
.reputation-node {
  min-height: 44px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 112px;
  align-items: center;
  gap: 8px;
  padding: 5px 2px;
  border-bottom: 1px dashed rgba(255,255,255,0.05);
}
.reputation-node-copy { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.reputation-node-copy b { color: var(--mist); font-size: 10.5px; }
.reputation-node-copy span { color: var(--dim); font-size: 9px; line-height: 1.3; }
.reputation-node.purchased .reputation-node-copy b { color: var(--leaf); }
.reputation-buy {
  width: 112px;
  min-height: 28px;
  padding: 4px 6px;
  border: 1px solid rgba(167, 139, 250, 0.35);
  border-radius: 6px;
  background: rgba(167, 139, 250, 0.12);
  color: var(--paper);
  font-size: 9px;
  line-height: 1.2;
  cursor: pointer;
}
.reputation-buy:disabled { border-color: var(--line); background: rgba(255,255,255,0.04); color: var(--dim); cursor: default; }
.collection-summary { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 12px; }
.collection-line { display: flex; justify-content: space-between; gap: 8px; padding: 6px 2px; border-bottom: 1px dashed rgba(255,255,255,0.05); color: var(--mist); font-size: 10px; }
.collection-line b { color: var(--violet); }
.league-summary {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.league-summary > div {
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: rgba(255,255,255,0.035);
}
.league-summary span { display: block; color: var(--dim); font-size: 9px; }
.league-summary b { display: block; margin-top: 3px; color: var(--gold); font-size: 12px; }
.league-board { margin-top: 10px; }
.league-board > strong { display: block; margin-bottom: 4px; color: var(--mist); font-size: 10px; }
.league-row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 4px 7px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
  color: var(--mist);
  font-size: 10px;
}
.league-row.you { background: rgba(53,224,198,0.09); color: var(--paper); }
.league-rank { color: var(--dim); text-align: center; }
.league-row.you .league-rank,
.league-row.you b { color: var(--teal); }
@media (max-width: 360px) {
  .reputation-node { grid-template-columns: minmax(0, 1fr) 94px; gap: 5px; }
  .reputation-buy { width: 94px; font-size: 8px; }
  .collection-summary { grid-template-columns: 1fr; }
}

/* daily login reward dots */
.daily-dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin: 10px 0 4px;
}
.daily-dot {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--line);
  background: rgba(18, 26, 52, 0.85);
  color: var(--dim);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
}
.daily-dot.claimed {
  border-color: var(--leaf);
  color: var(--leaf);
  background: var(--leaf-soft);
}
.daily-dot.today {
  border-color: #ffbe3d;
  color: #1a0f00;
  background: linear-gradient(135deg, #ffbe3d, #f59a1d);
  box-shadow: 0 0 12px rgba(255, 190, 61, 0.55);
  animation: chip-pop 1s ease-in-out infinite;
}

.intel-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 7px 2px;
  font-size: 12px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.05);
}
.intel-row:last-child { border-bottom: none; }
.intel-row .k { color: var(--mist); }
.intel-row .v {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--paper);
}
.intel-row .v.good { color: var(--leaf); }
.intel-row .v.epic { color: var(--violet); }

.bar {
  height: 8px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
  margin: 8px 0 4px;
}
.bar i {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--violet), var(--pink));
  box-shadow: 0 0 10px rgba(177, 151, 255, 0.5);
  transition: width 0.6s cubic-bezier(0.2, 0.9, 0.3, 1);
}

.codex-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 7px;
}
.codex-cell {
  aspect-ratio: 1;
  border-radius: 12px;
  background: var(--ink-700);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 21px;
  overflow: hidden;
  transition: all 0.25s;
}
.codex-cell img { width: 100%; height: 100%; object-fit: cover; }
.codex-cell.got {
  border-color: rgba(53, 224, 198, 0.4);
  background: var(--teal-soft);
  box-shadow: 0 0 10px rgba(53, 224, 198, 0.12);
}
.codex-cell.miss { filter: grayscale(1) brightness(0.35); opacity: 0.5; }

/* ============================================================
   Feature sheets (offline / prestige / reset)
   ============================================================ */

.feature {
  text-align: center;
  padding: 20px 20px 26px;
}
.feature-emblem {
  font-size: 52px;
  margin-bottom: 10px;
  animation: bob 2.4s ease-in-out infinite;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.4));
}
@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
.feature-title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  color: var(--paper);
  margin-bottom: 6px;
}
.feature-sub {
  font-size: 12px;
  color: var(--mist);
  margin-bottom: 14px;
  line-height: 1.55;
}
.feature-amount {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 700;
  color: var(--gold);
  text-shadow: 0 0 28px rgba(255, 190, 61, 0.4);
  margin: 6px 0 18px;
}
.feature-btns { display: flex; flex-direction: column; gap: 8px; }

.btn-hero {
  padding: 14px;
  border-radius: 14px;
  border: none;
  background: linear-gradient(180deg, #ffce6a, #eda317);
  color: #3a2600;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 5px 18px rgba(255, 190, 61, 0.35), inset 0 1px 0 rgba(255,255,255,0.5);
  transition: transform 0.12s, box-shadow 0.2s;
}
.btn-hero:hover { box-shadow: 0 6px 24px rgba(255, 190, 61, 0.5), inset 0 1px 0 rgba(255,255,255,0.5); }
.btn-hero:active { transform: scale(0.97); }

.btn-hero.btn-violet {
  background: linear-gradient(180deg, #c4b0ff, #8f6ef2);
  color: #1d1240;
  box-shadow: 0 5px 18px rgba(177, 151, 255, 0.4), inset 0 1px 0 rgba(255,255,255,0.5);
}
.btn-hero.btn-danger {
  background: linear-gradient(180deg, #ff8f8f, #e05252);
  color: #3a0808;
  box-shadow: 0 5px 18px rgba(248, 113, 113, 0.35), inset 0 1px 0 rgba(255,255,255,0.4);
}

.btn-ghost {
  padding: 12px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.05);
  color: var(--mist);
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
}
.btn-ghost:hover { background: rgba(255, 255, 255, 0.1); color: var(--paper); }

.prestige-badge-pill {
  display: inline-block;
  padding: 7px 20px;
  border-radius: var(--r-pill);
  background: var(--violet-soft);
  border: 1px solid rgba(177, 151, 255, 0.4);
  color: var(--violet);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 12px;
  box-shadow: 0 0 18px rgba(177, 151, 255, 0.15);
}
.prestige-feature {
  flex: 1;
  min-height: 0;
  padding-top: 14px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.prestige-summary {
  display: grid;
  gap: 6px;
  margin: 0 0 14px;
  text-align: left;
}
.prestige-line {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.5fr);
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.035);
  color: var(--mist);
  font-size: 10.5px;
  line-height: 1.3;
}
.prestige-line b { color: var(--paper); font-weight: 700; text-align: right; }
.prestige-line.keep { border-color: rgba(53, 224, 198, 0.3); background: rgba(53, 224, 198, 0.06); }
.prestige-line.keep b { color: var(--teal); }
.prestige-line.reset { border-color: rgba(248, 113, 113, 0.25); background: rgba(248, 113, 113, 0.045); }
.prestige-line.special { border-color: rgba(255, 190, 61, 0.32); background: rgba(255, 190, 61, 0.06); }
.prestige-line.special b { color: var(--gold); }
.btn-hero.armed {
  background: linear-gradient(180deg, #ffcf83, #e58a2a);
  color: #361e06;
}

/* ============================================================
   Settings rows
   ============================================================ */

.set-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 15px;
  margin-bottom: 8px;
  background: var(--ink-700);
  border: 1px solid var(--line);
  border-radius: 14px;
  cursor: pointer;
  transition: all 0.2s;
}
.set-row:hover { background: var(--ink-600); border-color: var(--line-strong); }
.set-row:active { transform: scale(0.98); }

.set-k { display: flex; align-items: center; gap: 11px; font-size: 14px; color: var(--paper); }
.set-k .ic { font-size: 19px; width: 26px; text-align: center; }

.set-v {
  font-size: 11.5px;
  font-weight: 700;
  padding: 4px 13px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.07);
  color: var(--dim);
}
.set-v.on { background: var(--leaf-soft); color: var(--leaf); }
.set-row.danger-row { border-color: rgba(248, 113, 113, 0.25); }
.set-row.danger-row .set-k { color: #ff8f8f; }
.set-row.danger-row:hover { background: rgba(248, 113, 113, 0.09); }

.set-row-slider { cursor: default; }
.set-row-slider:hover { transform: none; }
.set-slider-wrap { display: flex; align-items: center; gap: 10px; }
.set-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 110px;
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.12);
  outline: none;
  cursor: pointer;
}
.set-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--teal);
  box-shadow: 0 0 8px rgba(53, 224, 198, 0.5);
  cursor: pointer;
}
.set-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--teal);
  border: none;
  box-shadow: 0 0 8px rgba(53, 224, 198, 0.5);
  cursor: pointer;
}
.set-slider-val {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  color: var(--teal);
  min-width: 26px;
  text-align: right;
}
.set-slider-percent { min-width: 34px; }
.offline-cap-note {
  margin-top: 5px;
  color: var(--teal);
}

.savecode-box {
  box-sizing: border-box;
  width: 100%;
  min-height: 118px;
  padding: 12px;
  resize: vertical;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  outline: none;
  background: rgba(8, 13, 30, 0.9);
  color: var(--paper);
  font: 11px/1.55 ui-monospace, SFMono-Regular, Consolas, monospace;
  word-break: break-all;
  user-select: text;
}
.savecode-box:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 2px rgba(53, 224, 198, 0.12);
}

/* ============================================================
   Toasts — one-at-a-time queue below the HUD
   ============================================================ */

.toast-stack {
  position: absolute;
  left: 14px; right: 14px;
  top: 11%;
  z-index: 300;
  min-height: 44px;
  pointer-events: none;
}
.toast-stack:has(.toast-action) { pointer-events: auto; }

.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 14px;
  border-radius: 13px;
  background: rgba(25, 36, 72, 0.97);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--sky);
  font-size: 12.5px;
  color: var(--paper);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  animation: toast-in 0.28s cubic-bezier(0.18, 1.2, 0.3, 1), toast-out 0.28s ease var(--toast-out-delay, 1.85s) forwards;
}
.toast .t-copy { flex: 1; min-width: 0; }
.toast-action {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 6px 11px;
  border: 1px solid rgba(53, 224, 198, 0.55);
  border-radius: var(--r-pill);
  background: rgba(53, 224, 198, 0.13);
  color: var(--teal);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 800;
  cursor: pointer;
}
.toast-action:active { transform: scale(0.96); }
.toast-action:focus-visible { outline: 2px solid var(--paper); outline-offset: 2px; }
.toast.t-success { border-left-color: var(--leaf); }
.toast.t-warning { border-left-color: var(--gold); }
.toast.t-info { border-left-color: var(--sky); }
.toast .t-ic { font-size: 16px; }

/* M1.3 golden milestone toasts — gold border + breathing glow (5 districts,
   cumulative $1M, etc.). Keep the standard in/out lifecycle, add a glow pulse. */
.toast.t-milestone {
  border: 1.5px solid rgba(251, 191, 36, 0.85);
  border-left: 3px solid var(--neon-gold);
  background: linear-gradient(180deg, rgba(48, 39, 18, 0.98), rgba(30, 26, 15, 0.98));
  color: #fff3d6;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5), 0 0 22px rgba(251, 191, 36, 0.45), inset 0 0 14px rgba(251, 191, 36, 0.10);
  animation: toast-in 0.28s cubic-bezier(0.18, 1.2, 0.3, 1),
             toast-out 0.28s ease var(--toast-out-delay, 1.85s) forwards,
             milestone-glow 1.1s ease-in-out 0.3s 1;
}
.toast.t-milestone .t-ic { filter: drop-shadow(0 0 8px rgba(251, 191, 36, 0.8)); }
@keyframes milestone-glow {
  0%, 100% { box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5), 0 0 14px rgba(251, 191, 36, 0.35); }
  50% { box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5), 0 0 32px rgba(251, 191, 36, 0.75), inset 0 0 18px rgba(251, 191, 36, 0.16); }
}
@media (prefers-reduced-motion: reduce) {
  .toast.t-milestone { animation: toast-in 0.01s ease, toast-out 0.28s ease var(--toast-out-delay, 1.85s) forwards; }
}

@keyframes toast-in {
  from { transform: translateY(-14px) scale(0.95); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes toast-out {
  from { opacity: 1; }
  to { opacity: 0; transform: translateY(-10px); }
}

/* ============================================================
   Device purchase placement feedback
   ============================================================ */

.device-placement-fly {
  position: fixed;
  z-index: 245;
  width: 54px;
  height: 54px;
  margin: -27px 0 0 -27px;
  display: grid;
  place-items: center;
  pointer-events: none;
  filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 12px rgba(53, 224, 198, 0.42));
  transform-origin: center;
}
.device-placement-fly img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.device-placement-fly b {
  position: absolute;
  right: -8px;
  bottom: -5px;
  min-width: 28px;
  padding: 3px 6px;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--ink-900);
  font: 800 12px/1 var(--font-display);
  text-align: center;
}
.region-card.device-landed::after {
  content: '';
  position: absolute;
  inset: 3px;
  border: 2px solid var(--teal);
  border-radius: inherit;
  pointer-events: none;
  animation: device-landed 0.72s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes device-landed {
  from { opacity: 1; transform: scale(0.82); }
  to { opacity: 0; transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .region-card.device-landed::after { animation-duration: 0.1s; }
}

/* ============================================================
   Register click feedback + floating tap numbers
   ============================================================ */

.register-click-ripple {
  position: absolute;
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  border: 3px solid rgba(255, 190, 61, 0.92);
  border-radius: 50%;
  box-shadow: 0 0 12px rgba(255, 190, 61, 0.7), inset 0 0 8px rgba(255, 232, 164, 0.4);
  pointer-events: none;
  z-index: 220;
  animation: register-ripple 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
body.modal-open .register-click-ripple { display: none; }
@keyframes register-ripple {
  from { opacity: 1; transform: scale(0.72); }
  to { opacity: 0; transform: scale(2.65); }
}
.register-click-ripple.tier-1 { border-color: rgba(255, 210, 90, 0.95); box-shadow: 0 0 16px rgba(255, 200, 80, 0.8), inset 0 0 10px rgba(255, 232, 164, 0.5); }
.register-click-ripple.tier-2 { border-color: rgba(255, 157, 60, 0.97); box-shadow: 0 0 20px rgba(255, 150, 60, 0.85), inset 0 0 12px rgba(255, 200, 150, 0.55); }
.register-click-ripple.tier-3 { border-color: rgba(255, 94, 94, 0.98); box-shadow: 0 0 24px rgba(255, 90, 90, 0.9), inset 0 0 14px rgba(255, 170, 170, 0.6); }
.register-click-ripple.crit { border-color: rgba(255, 241, 168, 0.98); box-shadow: 0 0 26px rgba(255, 240, 150, 0.95), inset 0 0 14px rgba(255, 255, 210, 0.7); }

.float-num {
  position: absolute;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  color: var(--gold);
  text-shadow: 0 2px 0 rgba(90, 50, 0, 0.4), 0 0 14px rgba(255, 190, 61, 0.55);
  pointer-events: none;
  z-index: 150;
  animation: num-rise 0.95s ease-out forwards;
  white-space: nowrap;
}
/* M3 — "miss tap" hint (QA #28): a faint pointer back to the register when a
   tap lands on the canvas but missed it. Auto-fades, never blocks input. */
.miss-hint {
  position: absolute;
  transform: translate(-50%, -100%);
  font-size: 12px;
  font-weight: 600;
  color: rgba(244, 241, 255, 0.85);
  background: rgba(13, 18, 37, 0.82);
  border: 1px solid rgba(53, 224, 198, 0.35);
  border-radius: 999px;
  padding: 4px 11px;
  white-space: nowrap;
  pointer-events: none;
  z-index: 158;
  animation: miss-hint-pop 1.5s ease-out forwards;
}
@keyframes miss-hint-pop {
  0%   { transform: translate(-50%, -100%) scale(0.7); opacity: 0; }
  14%  { transform: translate(-50%, -100%) scale(1); opacity: 1; }
  75%  { opacity: 1; }
  100% { transform: translate(-50%, -140%) scale(0.96); opacity: 0; }
}
/* combo-tiered floating numbers grow + heat up with the streak */
.float-num.combo-1 { font-size: 21px; }
.float-num.combo-2 { font-size: 24px; color: #ffc24a; text-shadow: 0 2px 0 rgba(90, 50, 0, 0.4), 0 0 16px rgba(255, 194, 74, 0.7); }
.float-num.combo-3 { font-size: 28px; color: #ff9d3c; text-shadow: 0 2px 0 rgba(90, 40, 0, 0.45), 0 0 18px rgba(255, 157, 60, 0.8); }
.float-num.crit { color: #fff1a8; text-shadow: 0 0 18px rgba(255, 240, 150, 0.95); }
.float-num .float-combo { font-size: 0.6em; margin-left: 3px; opacity: 0.85; vertical-align: 0.12em; font-weight: 800; }
@keyframes num-rise {
  0% { opacity: 0; transform: translateY(6px) scale(0.7); }
  15% { opacity: 1; transform: translateY(0) scale(1.1); }
  100% { opacity: 0; transform: translateY(-64px) scale(0.85); }
}

/* combo badge — a single persistent streak counter above the register */
.combo-badge {
  position: absolute;
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 20px;
  color: #ffd24a;
  text-shadow: 0 2px 0 rgba(90, 50, 0, 0.5), 0 0 14px rgba(255, 190, 61, 0.7);
  pointer-events: none;
  z-index: 215;
  opacity: 0;
  transition: opacity 0.2s ease;
  text-align: center;
  line-height: 1;
  white-space: nowrap;
}
.combo-badge.show { opacity: 1; }
.combo-badge.tier-1 { color: #ffc24a; }
.combo-badge.tier-2 { color: #ff9d3c; font-size: 23px; }
.combo-badge.tier-3 { color: #ff5e5e; font-size: 26px; text-shadow: 0 2px 0 rgba(80, 0, 0, 0.5), 0 0 18px rgba(255, 90, 90, 0.85); }
.combo-badge.crit { color: #fff1a8; text-shadow: 0 0 18px rgba(255, 240, 150, 0.95); }
.combo-badge.pop { animation: combo-pop 0.26s ease-out; }
@keyframes combo-pop {
  0% { transform: translate(-50%, -50%) scale(0.6); }
  45% { transform: translate(-50%, -50%) scale(1.25); }
  100% { transform: translate(-50%, -50%) scale(1); }
}
/* live click-multiplier readout inside the combo badge */
.combo-badge .combo-mult {
  display: inline-block;
  margin-left: 5px;
  font-size: 0.56em;
  font-weight: 800;
  color: #9effa0;
  vertical-align: 0.18em;
  text-shadow: 0 0 10px rgba(120, 255, 140, 0.7);
}
.combo-badge .cb-crit { color: #fff1a8; }

/* ============================================================
   可玩性补强 (M-playability) — cold-start & combo ceremony
   ============================================================ */

/* P0-4 — first-10-tap floats: bigger, brighter, longer-lived */
.float-num.boosted {
  font-size: 26px;
  color: #ffe9a8;
  text-shadow: 0 2px 0 rgba(120, 70, 0, 0.5), 0 0 22px rgba(255, 220, 120, 0.95);
}
/* P0-3 — very first tap "welcome" float, biggest of the session */
.float-num.welcome {
  font-size: 34px;
  color: #fff6d0;
  text-shadow: 0 3px 0 rgba(140, 80, 0, 0.55), 0 0 30px rgba(255, 235, 160, 1);
  animation: num-rise 1.6s ease-out forwards;
}
.float-num.welcome .welcome-label {
  display: inline-block;
  font-size: 0.5em;
  vertical-align: 0.35em;
  margin-right: 6px;
  color: #6effe2;
  text-shadow: 0 0 14px rgba(110, 255, 226, 0.85);
}

/* P0-1 — combo milestone explosion (screen-center ceremony) */
.combo-milestone {
  position: absolute;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%);
  text-align: center;
  font-family: var(--font-display);
  pointer-events: none;
  z-index: 230;
  animation: cm-burst 1.1s cubic-bezier(0.18, 0.89, 0.32, 1.28) forwards;
}
.combo-milestone .cm-label {
  display: block;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 3px;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 0 14px rgba(120, 255, 226, 0.9);
  text-transform: uppercase;
  margin-bottom: 4px;
}
.combo-milestone .cm-value {
  font-size: 64px;
  font-weight: 900;
  line-height: 1;
  color: #ffd24a;
  text-shadow: 0 4px 0 rgba(90, 50, 0, 0.55), 0 0 34px rgba(255, 200, 70, 1);
}
.combo-milestone .cm-value b {
  color: #fff;
  margin-left: -4px;
}
.combo-milestone .cm-sub {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 1px;
  color: #9effa0;
  text-shadow: 0 0 12px rgba(120, 255, 140, 0.8);
}
.combo-milestone.tier-common .cm-value { color: #ffd24a; }
.combo-milestone.tier-rare  .cm-value { color: #ff9df0; text-shadow: 0 4px 0 rgba(90, 0, 70, 0.55), 0 0 34px rgba(255, 120, 230, 1); }
.combo-milestone.tier-epic   .cm-value { color: #6ec9ff; text-shadow: 0 4px 0 rgba(0, 50, 90, 0.55), 0 0 34px rgba(90, 200, 255, 1); }
.combo-milestone.tier-legendary .cm-value { color: #fff1a8; text-shadow: 0 4px 0 rgba(140, 80, 0, 0.55), 0 0 44px rgba(255, 240, 150, 1); }
@keyframes cm-burst {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.35); }
  20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
  38%  { transform: translate(-50%, -50%) scale(1); }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -58%) scale(0.98); }
}

/* P1-2 — high-combo (>=60) ambient edge glow on the whole screen.
   Drawn on a dedicated layer ABOVE the Phaser canvas: a plain inset
   box-shadow (even at a higher z-index) was still covered by the WebGL
   canvas' composited layer. The outer layer owns the show/hide transition
   (opacity — composited, cheap); the ::before pseudo owns the fixed gold
   gradient and pulses ONLY opacity (smooth breathing, no per-frame
   full-screen repaint that animating background-image would cause).
   Layer order: canvas(z1) < glow(z5) < DOM UI(z100). */
#high-combo-glow {
  position: absolute;
  /* Anchor to the letterboxed CANVAS frame, not the full viewport: on wide
     desktops the glow must stay over the playfield instead of bleeding into
     the side letterbox bars (which made it look stretched / off-center). */
  left: var(--canvas-left);
  top: var(--canvas-top);
  width: var(--canvas-w);
  height: var(--canvas-h);
  pointer-events: none;
  z-index: 5;
  opacity: 0;
  transition: opacity 0.3s ease;
}
#high-combo-glow::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, transparent 52%, rgba(255, 215, 0, 0.30) 100%);
}
body.high-combo #high-combo-glow { opacity: 1; }
body.high-combo #high-combo-glow::before {
  animation: combo-glow-pulse 1.6s ease-in-out infinite;
}
@keyframes combo-glow-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 0.95; }
}
body.power-save .combo-milestone,
body.power-save .float-num.boosted,
body.power-save .float-num.welcome,
body.power-save #high-combo-glow::before {
  animation: none !important;
  opacity: 0.3 !important;
}

/* ============================================================
   Prestige cinematic overlay
   ============================================================ */

.prestige-cinematic {
  position: fixed;
  inset: 0;
  z-index: 380;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 42%, rgba(177, 151, 255, 0.22), rgba(4, 6, 14, 0.92) 62%);
  pointer-events: auto;
  touch-action: none;
  animation: prestige-veil-in 0.2s ease-out;
}
.prestige-halo {
  position: absolute;
  width: 210px;
  height: 210px;
  border-radius: 50%;
  border: 2px solid rgba(177, 151, 255, 0.55);
  box-shadow: 0 0 44px rgba(177, 151, 255, 0.45), inset 0 0 34px rgba(255, 190, 61, 0.28);
  opacity: 0;
  animation: prestige-halo 1.15s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.prestige-halo.gold { animation-delay: 0.1s; border-color: rgba(255, 190, 61, 0.6); }
.prestige-copy {
  position: relative;
  z-index: 2;
  text-align: center;
  padding: 0 28px;
}
.prestige-cine-emblem {
  font-size: 68px;
  line-height: 1;
  filter: drop-shadow(0 0 20px rgba(255, 190, 61, 0.55));
  animation: prestige-emblem 0.75s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.prestige-cine-title {
  max-width: min(88vw, 420px);
  margin-top: 12px;
  font-family: var(--font-display);
  font-size: clamp(24px, 7.5vw, 32px);
  font-weight: 800;
  color: var(--paper);
  line-height: 1.15;
  overflow-wrap: anywhere;
  text-shadow: 0 3px 0 rgba(73, 44, 126, 0.45), 0 0 26px rgba(177, 151, 255, 0.55);
  opacity: 0;
  animation: prestige-title-in 0.5s 0.18s ease-out forwards;
}
.prestige-cine-bonus {
  display: inline-block;
  max-width: 88vw;
  margin-top: 12px;
  padding: 7px 18px;
  border-radius: var(--r-pill);
  border: 1.5px solid rgba(255, 190, 61, 0.62);
  background: linear-gradient(180deg, rgba(255, 190, 61, 0.2), rgba(255, 190, 61, 0.08));
  color: var(--gold);
  font-family: var(--font-display);
  font-size: clamp(19px, 5.8vw, 25px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: 0.5px;
  overflow-wrap: anywhere;
  box-shadow: 0 0 24px rgba(255, 190, 61, 0.35);
  opacity: 0;
  animation: prestige-bonus-in 0.55s 0.34s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.prestige-this-bonus {
  width: fit-content;
  margin: 12px auto 8px;
  padding: 6px 13px;
  border: 1px solid rgba(255, 190, 61, 0.46);
  border-radius: var(--r-pill);
  background: rgba(255, 190, 61, 0.1);
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 800;
}
.prestige-confetti {
  position: absolute;
  top: -16px;
  width: 8px;
  height: 12px;
  border-radius: 2px;
  opacity: 0.95;
  animation-name: prestige-confetti-fall;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes prestige-veil-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes prestige-halo {
  0% { opacity: 0; transform: scale(0.35); }
  35% { opacity: 1; }
  100% { opacity: 0; transform: scale(2.1); }
}
@keyframes prestige-emblem {
  0% { opacity: 0; transform: scale(0.4) rotate(-16deg); }
  55% { opacity: 1; transform: scale(1.18) rotate(6deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
@keyframes prestige-title-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes prestige-bonus-in {
  0% { opacity: 0; transform: scale(0.6); }
  60% { opacity: 1; transform: scale(1.14); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes prestige-confetti-fall {
  0% { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg); }
  100% { opacity: 0; transform: translate3d(var(--drift, 0px), 108vh, 0) rotate(660deg); }
}
@media (max-height: 480px) {
  .prestige-cine-emblem { font-size: 48px; }
  .prestige-cine-title { margin-top: 7px; font-size: clamp(21px, 6vw, 27px); }
  .prestige-cine-bonus { margin-top: 8px; font-size: clamp(17px, 4.8vw, 21px); }
}
@media (prefers-reduced-motion: reduce) {
  .prestige-cinematic,
  .prestige-halo,
  .prestige-cine-emblem,
  .prestige-cine-title,
  .prestige-cine-bonus {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
  }
  .prestige-confetti { display: none; }
}

/* ============================================================
   Tutorial
   ============================================================ */

.tut-veil {
  position: fixed;
  inset: 0;
  z-index: 400;
  background: rgba(4, 6, 14, 0.72);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0 16px 120px;
  animation: veil-in 0.25s ease;
}

.tut-focus {
  position: absolute;
  z-index: 1;
  border: 2px solid var(--gold);
  border-radius: 16px;
  box-shadow: 0 0 0 9999px rgba(4, 6, 14, 0.28), 0 0 24px rgba(255, 190, 61, 0.65);
  pointer-events: none;
  animation: tut-focus-pulse 1.1s ease-in-out infinite;
}
@keyframes tut-focus-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.025); }
}

.tut-card {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: min(100vw, 56.2061vh);
  background: linear-gradient(180deg, var(--ink-700), var(--ink-800));
  border: 1px solid rgba(53, 224, 198, 0.35);
  border-radius: 20px;
  padding: 20px 22px;
  text-align: center;
  box-shadow: 0 0 34px rgba(53, 224, 198, 0.12), 0 14px 40px rgba(0,0,0,0.5);
  animation: sheet-up 0.34s cubic-bezier(0.18, 1.1, 0.3, 1);
}
.tut-title {
  font-family: var(--font-display);
  font-size: 16.5px;
  font-weight: 700;
  color: var(--teal);
  margin-bottom: 7px;
}
.tut-text {
  font-size: 13px;
  color: var(--mist);
  line-height: 1.65;
  margin-bottom: 13px;
}
.tut-step {
  font-size: 10px;
  color: var(--dim);
  letter-spacing: 2px;
  margin-bottom: 12px;
}
.tut-next {
  padding: 11px 34px;
  border-radius: var(--r-pill);
  border: none;
  background: linear-gradient(180deg, #43ecca, #17b89d);
  color: #052a22;
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(53, 224, 198, 0.35);
  transition: transform 0.12s;
}
.tut-next:active { transform: scale(0.94); }
.tut-skip {
  margin-top: 11px;
  font-size: 11px;
  color: var(--dim);
  text-decoration: underline;
  cursor: pointer;
}
.tut-skip:hover { color: var(--mist); }

/* Non-blocking coach mark for the opening tutorial's first step. Sits above
   the dock but below the full-screen tutorial veil; never intercepts input
   except its own skip link, so the player can tap the register freely. */
.tut-coach {
  position: fixed;
  left: 0; right: 0;
  bottom: 96px;
  z-index: 360;
  display: flex;
  justify-content: center;
  pointer-events: none;
  padding: 0 16px;
  animation: coach-in 0.32s cubic-bezier(0.18, 1.1, 0.3, 1);
}
@keyframes coach-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
.tut-coach .tut-coach-card {
  pointer-events: none;
  position: relative;
  width: 100%;
  max-width: min(100vw, 56.2061vh);
  background: linear-gradient(180deg, var(--ink-700), var(--ink-800));
  border: 1px solid rgba(255, 190, 61, 0.5);
  border-radius: 18px;
  padding: 13px 18px 11px;
  text-align: center;
  box-shadow: 0 0 28px rgba(255, 190, 61, 0.16), 0 10px 30px rgba(0,0,0,0.5);
}
.tut-coach .tut-coach-arrow {
  position: absolute;
  bottom: -7px; left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 14px; height: 14px;
  background: var(--ink-800);
  border-right: 1px solid rgba(255, 190, 61, 0.5);
  border-bottom: 1px solid rgba(255, 190, 61, 0.5);
}
.tut-coach .tut-title {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--gold);
  margin-bottom: 5px;
}
.tut-coach .tut-text {
  font-size: 12.5px;
  color: var(--mist);
  line-height: 1.55;
  margin-bottom: 8px;
}
.tut-coach .tut-skip { pointer-events: auto; }

/* ============================================================
   M2.4 — coach tap-gesture (finger + rippling tap ring). Pure
   decoration: pointer-events none, animated loop showing the
   player to tap the register below the coach bubble.
   ============================================================ */
.coach-gesture {
  pointer-events: none;
  position: absolute;
  top: calc(100% + 14px);      /* below the coach card, toward the register */
  left: 50%;
  transform: translateX(-50%);
  width: 44px; height: 60px;
}
.coach-gesture .gesture-finger {
  position: absolute; left: 50%; top: 0;
  transform: translateX(-50%);
  font-size: 34px; line-height: 1;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.4));
  animation: gesture-tap 1.15s ease-in-out infinite;
  z-index: 1;
  transform-origin: 50% 30%;
}
.coach-gesture .gesture-ripple {
  position: absolute; left: 50%; top: 14px;
  width: 38px; height: 38px;
  margin-left: -19px;
  border: 3px solid var(--gold, #ffbe3d);
  border-radius: 50%;
  opacity: 0;
  animation: gesture-ripple 1.15s ease-out infinite;
}
@keyframes gesture-tap {
  0%, 100% { transform: translateX(-50%) translateY(0)  scale(1); }
  45%      { transform: translateX(-50%) translateY(-6px) scale(0.92); }
  60%      { transform: translateX(-50%) translateY(2px)  scale(1.05); }
  72%      { transform: translateX(-50%) translateY(0)   scale(1); }
}
@keyframes gesture-ripple {
  0%   { transform: scale(0.35); opacity: 0.85; }
  100% { transform: scale(1.7);  opacity: 0; }
}

/* ============================================================
   Title screen — the laundromat marquee at midnight
   ============================================================ */

.title-veil {
  position: fixed;
  inset: 0;
  z-index: 500;
  background:
    radial-gradient(ellipse 100% 72% at 50% 30%, rgba(36, 52, 94, 0.62) 0%, rgba(8, 13, 30, 0.88) 78%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  opacity: 0;
  transition: opacity 0.55s ease;
  pointer-events: auto;
}
.title-veil.show { opacity: 1; }
.title-veil.gone { opacity: 0; pointer-events: none; }

/* drifting soap bubbles on the title */
.title-bubbles { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.title-bubbles span {
  position: absolute;
  bottom: -24px;
  border-radius: 50%;
  border: 1.5px solid rgba(53, 224, 198, 0.35);
  background: radial-gradient(circle at 32% 30%, rgba(255,255,255,0.22), rgba(53, 224, 198, 0.05));
  animation: bubble-rise linear infinite;
}
@keyframes bubble-rise {
  0% { transform: translateY(0) translateX(0); opacity: 0; }
  12% { opacity: 0.8; }
  100% { transform: translateY(-105vh) translateX(24px); opacity: 0; }
}

.title-sign {
  position: relative;
  text-align: center;
  padding: 26px 30px 22px;
  border: 2px solid rgba(53, 224, 198, 0.5);
  border-radius: 20px;
  background: rgba(10, 14, 29, 0.55);
  box-shadow: 0 0 34px rgba(53, 224, 198, 0.16), inset 0 0 30px rgba(53, 224, 198, 0.05);
  animation: sign-buzz 6s linear infinite;
  margin-bottom: 26px;
}
@keyframes sign-buzz {
  0%, 100% { box-shadow: 0 0 34px rgba(53, 224, 198, 0.16), inset 0 0 30px rgba(53, 224, 198, 0.05); }
  88% { box-shadow: 0 0 34px rgba(53, 224, 198, 0.16), inset 0 0 30px rgba(53, 224, 198, 0.05); }
  89% { box-shadow: 0 0 10px rgba(53, 224, 198, 0.06), inset 0 0 8px rgba(53, 224, 198, 0.02); }
  90% { box-shadow: 0 0 40px rgba(53, 224, 198, 0.24), inset 0 0 34px rgba(53, 224, 198, 0.08); }
  92% { box-shadow: 0 0 18px rgba(53, 224, 198, 0.1), inset 0 0 12px rgba(53, 224, 198, 0.03); }
  94%, 100% { box-shadow: 0 0 34px rgba(53, 224, 198, 0.16), inset 0 0 30px rgba(53, 224, 198, 0.05); }
}

.title-logo-wrap {
  width: 92px; height: 92px;
  margin: 0 auto 14px;
  border-radius: 24px;
  overflow: hidden;
  border: 2px solid rgba(255, 190, 61, 0.5);
  box-shadow: 0 0 30px rgba(255, 190, 61, 0.25), 0 10px 26px rgba(0,0,0,0.5);
  animation: bob 3.4s ease-in-out infinite;
}
.title-logo-wrap img { width: 100%; height: 100%; object-fit: cover; }

.title-name {
  font-family: var(--font-display);
  font-size: 31px;
  font-weight: 700;
  color: var(--paper);
  letter-spacing: 1.5px;
  text-shadow: 0 0 26px rgba(53, 224, 198, 0.45), 0 3px 10px rgba(0,0,0,0.6);
  margin-bottom: 5px;
}
.title-sub {
  font-size: 12px;
  color: var(--teal);
  letter-spacing: 3.5px;
  text-transform: uppercase;
  opacity: 0.85;
}

.title-open24 {
  display: inline-block;
  margin-bottom: 30px;
  padding: 7px 26px;
  border: 2px solid var(--pink);
  border-radius: var(--r-pill);
  color: var(--pink);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 5px;
  text-shadow: 0 0 14px rgba(255, 122, 168, 0.7);
  box-shadow: 0 0 22px rgba(255, 122, 168, 0.2), inset 0 0 18px rgba(255, 122, 168, 0.06);
  animation: open-flicker 4.5s linear infinite;
}
@keyframes open-flicker {
  0%, 100% { opacity: 1; }
  54% { opacity: 1; }
  55% { opacity: 0.45; }
  56% { opacity: 1; }
  70% { opacity: 0.75; }
  71% { opacity: 1; }
}

.title-play {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 11px;
  padding: 16px 56px;
  border-radius: var(--r-pill);
  border: none;
  background: linear-gradient(180deg, #43ecca, #12a98e);
  color: #043026;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 1px;
  cursor: pointer;
  box-shadow: 0 6px 26px rgba(53, 224, 198, 0.4), 0 0 60px rgba(53, 224, 198, 0.12), inset 0 2px 0 rgba(255,255,255,0.45);
  animation: play-throb 2.2s ease-in-out infinite;
  transition: transform 0.15s;
  margin-bottom: 14px;
}
@keyframes play-throb {
  0%, 100% { box-shadow: 0 6px 26px rgba(53, 224, 198, 0.4), 0 0 60px rgba(53, 224, 198, 0.12), inset 0 2px 0 rgba(255,255,255,0.45); }
  50% { box-shadow: 0 6px 38px rgba(53, 224, 198, 0.6), 0 0 90px rgba(53, 224, 198, 0.2), inset 0 2px 0 rgba(255,255,255,0.45); }
}
.title-play:hover { transform: translateY(-2px) scale(1.03); }
.title-play:active { transform: scale(0.95); }
.title-play .tri { font-size: 15px; }

.title-hint {
  font-size: 11px;
  color: var(--dim);
  letter-spacing: 1px;
  margin-bottom: 22px;
}

.title-lang {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 18px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.05);
  color: var(--mist);
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
}
.title-lang:hover { background: rgba(255, 255, 255, 0.1); color: var(--paper); }

.title-foot {
  position: absolute;
  bottom: 18px;
  font-size: 9.5px;
  letter-spacing: 2px;
  color: var(--dim);
  opacity: 0.55;
}

/* ============================================================
   Small screens / short screens
   ============================================================ */
@media (max-height: 660px) {
  .cash-num { font-size: 25px; }
  .dock-btn { padding: 7px 2px 6px; }
  .dock-icon { font-size: 19px; }
  .title-name { font-size: 25px; }
  .title-sign { padding: 18px 22px 16px; margin-bottom: 18px; }
}

/* ============================================================
   Small-width readability (≤375px)
   Boost HUD secondary text, shop descriptions, and button
   labels so they stay legible on compact phones.
   ============================================================ */
@media (max-width: 375px) {
  .hud-cps { font-size: 12px; padding: 4px 10px; }
  .hud-row-bottom { font-size: 11px; }
  .card-desc { font-size: 11.5px; line-height: 1.4; }
  .card-name { font-size: 14px; }
  .btn-buy { font-size: 12.5px; padding: 8px 18px; }
  .quest-copy b { font-size: 12.5px; }
  .intel-label { font-size: 10.5px; }
  .reputation-node-copy b { font-size: 11.5px; }
  .specialization-copy b { font-size: 11.5px; }
}

/* ============================================================
   Accessibility: Large Text mode
   Scales up all secondary/caption text globally via the
   .a11y-large-text root class toggled from Settings.
   ============================================================ */
.a11y-large-text {
  --a11y-scale: 1.22;
}
.a11y-large-text .hud-cps { font-size: calc(11px * var(--a11y-scale)); }
.a11y-large-text .hud-row-bottom { font-size: calc(10px * var(--a11y-scale)); }
.a11y-large-text .hud-tier { font-size: calc(11px * var(--a11y-scale)); }
.a11y-large-text .card-name { font-size: calc(13.5px * var(--a11y-scale)); }
.a11y-large-text .card-desc { font-size: calc(10.5px * var(--a11y-scale)); line-height: 1.45; }
.a11y-large-text .card-meta { font-size: calc(10px * var(--a11y-scale)); }
.a11y-large-text .card-price { font-size: calc(14px * var(--a11y-scale)); }
.a11y-large-text .btn-buy { font-size: calc(11.5px * var(--a11y-scale)); }
.a11y-large-text .quest-copy b { font-size: calc(11.5px * var(--a11y-scale)); }
.a11y-large-text .quest-prog { font-size: calc(9.5px * var(--a11y-scale)); }
.a11y-large-text .intel-label { font-size: calc(9.5px * var(--a11y-scale)); }
.a11y-large-text .intel-note { font-size: calc(10.5px * var(--a11y-scale)); }
.a11y-large-text .reputation-node-copy b { font-size: calc(10.5px * var(--a11y-scale)); }
.a11y-large-text .reputation-node-copy span { font-size: calc(9px * var(--a11y-scale)); }
.a11y-large-text .reputation-route-head { font-size: calc(11px * var(--a11y-scale)); }
.a11y-large-text .collection-line { font-size: calc(10px * var(--a11y-scale)); }
.a11y-large-text .specialization-copy b { font-size: calc(10.5px * var(--a11y-scale)); }
.a11y-large-text .specialization-copy span { font-size: calc(8.5px * var(--a11y-scale)); }
.a11y-large-text .dock-label { font-size: calc(10.5px * var(--a11y-scale)); }
.a11y-large-text .set-k { font-size: calc(13px * var(--a11y-scale)); }

/* ============================================================
   Accessibility: High Contrast mode
   Brightens muted text and strengthens borders/backgrounds
   so low-vision users can distinguish UI layers.
   ============================================================ */
.a11y-high-contrast {
  --mist: #d6def5;
  --dim: #9aa6cc;
}
.a11y-high-contrast .card-desc,
.a11y-high-contrast .quest-prog,
.a11y-high-contrast .quest-note,
.a11y-high-contrast .intel-note,
.a11y-high-contrast .specialization-note,
.a11y-high-contrast .reputation-node-copy span {
  color: var(--dim);
}
.a11y-high-contrast .hud-row-bottom,
.a11y-high-contrast .collection-line,
.a11y-high-contrast .specialization-copy span {
  color: var(--mist);
}
.a11y-high-contrast .hud-cps {
  border-color: rgba(53, 224, 198, 0.55);
  color: #4ef0d6;
}
.a11y-high-contrast .region-card,
.a11y-high-contrast .card,
.a11y-high-contrast .set-row {
  border-color: var(--line-strong);
}

/* ============================================================
   V1.5.3 — branded letterbox, power-save degrade, new panels
   ============================================================ */

/* Branded black bars: the area outside the FIT-scaled canvas (letterbox on
   wide/landscape screens) shows a deep navy gradient with a faint logo
   watermark instead of flat black. */
html, body {
  background:
    radial-gradient(1000px 620px at 50% -8%, rgba(53, 224, 198, 0.06), transparent 60%),
    radial-gradient(820px 620px at 88% 110%, rgba(177, 151, 255, 0.07), transparent 60%),
    var(--ink-950);
}
body::after {
  content: "\1F9FA  浣洗街 24 号";
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: clamp(38px, 11vw, 168px);
  font-weight: 800;
  letter-spacing: 0.05em;
  color: rgba(53, 224, 198, 0.05);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
/* M3 — 大屏/投屏 letterbox 观感增强（QA #6/#23）。
   仅在宽视口(≥1100px)生效：两侧黑边改用更丰富的夜景渐变 + 发光氛围，
   并给居中的竖屏画布一道柔和霓虹光晕，画布不再被"裸"夹在纯黑里。 */
@media (min-width: 1100px) {
  html, body {
    background:
      radial-gradient(1200px 700px at 18% 20%, rgba(53, 224, 198, 0.07), transparent 58%),
      radial-gradient(1000px 680px at 84% 16%, rgba(177, 151, 255, 0.08), transparent 58%),
      radial-gradient(900px 640px at 50% 104%, rgba(255, 190, 61, 0.045), transparent 58%),
      radial-gradient(640px 460px at 12% 88%, rgba(53, 224, 198, 0.05), transparent 60%),
      var(--ink-950);
  }
  #game-container {
    box-shadow: 0 0 70px rgba(56, 189, 248, 0.13), 0 0 26px rgba(53, 224, 198, 0.10);
  }
  body::after {
    font-size: clamp(96px, 13vw, 220px);
    color: rgba(53, 224, 198, 0.045);
    text-shadow: 0 0 90px rgba(53, 224, 198, 0.15);
  }
}
#game-container { background: transparent; position: relative; z-index: 1; }

/* ===== 极端横屏提示（竖屏专属游戏） =====
   M3 — 由"全屏遮挡"改为分级：
   · 常规横屏(高度≤520)：顶部一条细通知条提示可转回竖屏，游戏仍可玩
     （QA #9/#22/#27 希望横屏能玩，而非完全被挡）。
   · 极端矮横屏(高度≤390)：才退回全屏提示（这个高度竖屏 UI 已无法排版）。 */
.rotate-hint {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--ink-950);
  color: var(--paper);
  pointer-events: auto;
}
.rotate-hint-inner { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 24px; }
.rotate-hint-icon { font-size: 56px; animation: rotate-nudge 1.6s ease-in-out infinite; }
.rotate-hint-title { font-family: var(--font-display); font-size: 22px; font-weight: 700; margin: 0; }
.rotate-hint-sub { font-size: 12px; color: var(--dim); letter-spacing: 0.4px; }
@keyframes rotate-nudge {
  0%, 100% { transform: rotate(-12deg); }
  50% { transform: rotate(78deg); }
}
/* 常规横屏：顶部细通知条，不遮游戏可继续玩 */
@media (max-height: 520px) and (orientation: landscape) {
  .rotate-hint {
    display: flex;
    inset: env(safe-area-inset-top, 0) 0 auto 0;
    height: 40px;
    align-items: center;
    background: linear-gradient(90deg, #0d1225, #13203a);
    border-bottom: 1px solid rgba(53, 224, 198, 0.25);
    pointer-events: none;
    padding: 0 10px;
    box-sizing: border-box;
  }
  .rotate-hint .rotate-hint-inner { flex-direction: row; gap: 8px; padding: 0; width: 100%; }
  .rotate-hint .rotate-hint-icon { font-size: 18px; animation-duration: 1.2s; }
  .rotate-hint .rotate-hint-title { font-size: 13px; }
  .rotate-hint .rotate-hint-sub { font-size: 11px; }
}
/* 极端矮横屏：回归全屏遮挡 */
@media (max-height: 390px) and (orientation: landscape) {
  .rotate-hint {
    display: flex;
    inset: 0;
    height: auto;
    align-items: center;
    justify-content: center;
    text-align: center;
    background: var(--ink-950);
    color: var(--paper);
    pointer-events: auto;
    box-sizing: border-box;
    border-bottom: none;
  }
  .rotate-hint .rotate-hint-inner { flex-direction: column; gap: 10px; padding: 24px; }
  .rotate-hint .rotate-hint-icon { font-size: 56px; animation-duration: 1.6s; }
  .rotate-hint .rotate-hint-title { font-size: 22px; }
  .rotate-hint .rotate-hint-sub { font-size: 12px; }
}

/* Power-saving mode: drop the heaviest decorative motion to spare battery. */
body.power-save .prestige-confetti { display: none !important; }
body.power-save .prestige-halo { display: none !important; }
body.power-save .cash-float { animation-duration: 120ms !important; }

/* ===== M3 成就庆祝弹窗（QA #26）=====
   非阻塞浮层：居中弹出奖杯卡片，图标回弹 + 轻量彩纸，自动消隐/点击跳过。
   容器 pointer-events:none，只有卡片接收点击，绝不打断点击循环。 */
.achievement-pop {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.achievement-pop-card {
  pointer-events: auto;
  background: linear-gradient(165deg, rgba(20, 30, 55, 0.92), rgba(9, 14, 29, 0.94));
  border: 1px solid rgba(53, 224, 198, 0.4);
  border-radius: 20px;
  padding: 22px 34px 24px;
  text-align: center;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55), 0 0 40px rgba(53, 224, 198, 0.18);
  backdrop-filter: blur(6px);
  max-width: min(82vw, 320px);
  animation: ach-card-in 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.achievement-pop-icon {
  font-size: 58px;
  line-height: 1;
  animation: ach-icon-pop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.achievement-pop-title {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.28em;
  color: var(--teal);
  margin-top: 10px;
  text-transform: uppercase;
}
.achievement-pop-name {
  font-size: 19px;
  font-weight: 800;
  color: var(--paper);
  margin-top: 4px;
}
.achievement-pop-desc {
  font-size: 12.5px;
  color: var(--dim);
  margin-top: 6px;
}
.achievement-confetti {
  position: fixed;
  top: -12px;
  width: 7px;
  height: 16px;
  border-radius: 2px;
  opacity: 0;
  animation: ach-confetti-fall 1.6s ease-in forwards;
  pointer-events: none;
}
@keyframes ach-card-in {
  from { transform: scale(0.72) translateY(14px); opacity: 0; }
  to   { transform: scale(1) translateY(0); opacity: 1; }
}
@keyframes ach-icon-pop {
  0%   { transform: scale(0.2) rotate(-14deg); }
  60%  { transform: scale(1.25) rotate(5deg); }
  100% { transform: scale(1) rotate(0deg); }
}
@keyframes ach-confetti-fall {
  0%   { transform: translateX(0) translateY(0) rotate(0deg); opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translateX(var(--ach-drift, 0px)) translateY(70vh) rotate(720deg); opacity: 0; }
}
body.power-save .achievement-confetti { display: none !important; }

/* MAX bulk-purchase confirmation */
.max-confirm-sheet .feature-emblem { color: #ffbe3d; }
.max-confirm-sheet .feature-title { color: var(--gold); }

/* League "Street Legend" status when all rivals are surpassed */
.league-legend {
  margin: 2px 0 9px;
  padding: 9px 10px;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(255, 190, 61, 0.15), rgba(255, 122, 168, 0.10));
  border: 1px solid rgba(255, 190, 61, 0.42);
  font-size: 13px;
  font-weight: 800;
  color: var(--gold);
  text-align: center;
}
