:root {
  --bg-0: #07080d;
  --bg-1: #11141d;
  --bg-2: #1b2030;
  --accent: #5cf2c4;
  --accent-2: #6fb3ff;
  --neon: #b6ff3b;
  --warn: #ffb454;
  --danger: #ff4d4d;
  --money: #6dff8e;
  --ink: #e6e9ef;
  --ink-dim: #8a92a3;
  --pixel-font: 'Press Start 2P', monospace;
  --body-font: 'VT323', 'Press Start 2P', monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--bg-0);
  color: var(--ink);
  font-family: var(--body-font);
  font-size: 18px;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  touch-action: none;
  image-rendering: pixelated;
}

#app {
  position: fixed;
  inset: 0;
}

#game {
  display: block;
  width: 100%;
  height: 100%;
  cursor: crosshair;
  background: #1a1a1a;
}

/* ============ Overlays ============ */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(4, 6, 12, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 10;
  padding: 24px;
  overflow-y: auto;
}
.overlay.hidden { display: none; }

.panel {
  background: var(--bg-1);
  border: 3px solid var(--neon);
  padding: 28px 24px 24px;
  max-width: 480px;
  width: 100%;
  text-align: center;
  box-shadow: 0 0 30px rgba(182, 255, 59, 0.25), 6px 6px 0 #000;
  position: relative;
}
.panel-wide { max-width: 920px; }

.title {
  font-family: var(--pixel-font);
  font-size: 26px;
  letter-spacing: 2px;
  margin-bottom: 12px;
  color: var(--neon);
  text-shadow: 2px 2px 0 #000;
}
.subtitle {
  color: var(--ink-dim);
  margin-bottom: 22px;
  font-size: 18px;
}

/* ============ Key-art landing ============ */
/* The game is pixel art. The landing is not — it is box art, and box art is
   allowed to be a painting. Screenshots keep the promise honest; this sells
   the fantasy. No pixel frame, no Game Boy chrome. */
.title-screen {
  background: #05050a;
  padding: 0;
  align-items: stretch;
  justify-content: stretch;
}
.title-flicker, .title-scanlines { display: none; }

.hero-shell {
  position: relative;
  width: 100%;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scroll-behavior: smooth;
}
/* The fold: sign-in fills the first screen, the pitch begins below it. */
.hero-inner { min-height: 100vh; }
.hero-art {
  position: absolute; inset: 0;
  background-image: url('../assets/landing/hero_city.jpg');
  background-size: cover;
  background-position: center 38%;
  image-rendering: auto;          /* painted art must NOT be nearest-neighbour */
  z-index: 0;
}
/* Two gradients, not one: a vertical wash so the lower third can hold text,
   and a left-weighted wash so the copy column never fights the skyline. */
.hero-vignette {
  position: absolute; inset: 0;
  background:
    linear-gradient(105deg, rgba(5,5,10,0.94) 0%, rgba(5,5,10,0.86) 32%,
                    rgba(5,5,10,0.45) 58%, rgba(5,5,10,0.25) 100%),
    linear-gradient(180deg, rgba(5,5,10,0.55) 0%, transparent 30%,
                    transparent 55%, rgba(5,5,10,0.9) 100%);
  z-index: 1;
}
.hero-inner {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 48px;
  align-items: center;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 48px 40px;
}
.hero-copy { flex: 1 1 560px; min-width: 0; max-width: 680px; }

.hero-kicker {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 4px;
  color: #ffb454;
  border-left: 3px solid #ff336e;
  padding-left: 10px;
  margin-bottom: 14px;
}

/* The wordmark: heavy condensed display type, tight, with a hard offset
   shadow. Reads as a crime-movie title card rather than a console splash. */
.wordmark {
  font-family: 'Anton', 'Barlow Condensed', var(--body-font);
  font-weight: 400;
  font-size: clamp(58px, 9vw, 132px);
  line-height: 0.86;
  letter-spacing: -1px;
  margin: 0 0 10px;
  display: flex;
  flex-direction: column;
  text-transform: uppercase;
}
.wordmark-1 { color: #ff2f6a; text-shadow: 5px 5px 0 #000, 0 0 44px rgba(255,47,106,0.55); }
.wordmark-2 { color: #ffc83c; text-shadow: 5px 5px 0 #000, 0 0 44px rgba(255,200,60,0.45); margin-left: 0.06em; }

.hero-tag {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600;
  font-size: clamp(17px, 2vw, 23px);
  letter-spacing: 1.5px;
  color: #e8e2d4;
  text-shadow: 0 2px 10px rgba(0,0,0,0.9);
  margin: 0 0 30px;
  max-width: 36ch;      /* the line fits on one row; don't orphan "rest." */
}

.btn-play {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 20px 46px;
  font-family: 'Anton', var(--body-font);
  font-size: 30px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #14030a;
  background: linear-gradient(180deg, #ffe14d 0%, #ffb01f 55%, #ff8a1f 100%);
  border: none;
  border-radius: 2px;
  cursor: pointer;
  box-shadow: 6px 6px 0 rgba(0,0,0,0.85), 0 0 40px rgba(255,150,31,0.35);
  transition: transform 90ms ease, box-shadow 90ms ease, filter 90ms ease;
}
.btn-play:hover {
  filter: brightness(1.07);
  transform: translate(-2px, -2px);
  box-shadow: 8px 8px 0 rgba(0,0,0,0.85), 0 0 60px rgba(255,180,60,0.5);
}
.btn-play:active { transform: translate(3px, 3px); box-shadow: 2px 2px 0 rgba(0,0,0,0.85); }
.btn-play-arrow { font-size: 20px; }

.hero-reassure {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 2px;
  color: #9a9384;
  margin-top: 16px;
  text-transform: uppercase;
}

.hero-marquee {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 26px 0 0;
  padding: 0;
}
.hero-marquee li {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 2px;
  color: #ffd98a;
  border: 1px solid rgba(255,180,84,0.35);
  background: rgba(0,0,0,0.45);
  padding: 6px 11px;
  text-transform: uppercase;
}

.hero-secondary { margin-top: 22px; }
.hero-secondary.hidden { display: none; }
.btn-link {
  background: none; border: none;
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600; font-size: 17px; letter-spacing: 1px;
  color: #9a9384; cursor: pointer; padding: 4px 0;
  text-decoration: underline; text-underline-offset: 5px;
  text-transform: uppercase;
}
.btn-link:hover { color: #ffc83c; }

/* ---- The pitch below the fold ----
   Everything here is optional reading: the sign-in above is always one click
   from playing. Alternating rows so the eye zig-zags down the page. */
.pitch {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 20px 40px 90px;
}
.pitch-row {
  display: flex;
  align-items: center;
  gap: 46px;
  padding: 54px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.pitch-row.reverse { flex-direction: row-reverse; }
.pitch-text { flex: 1 1 320px; min-width: 0; }
.pitch-row img {
  flex: 1 1 460px;
  width: 50%;
  max-width: 560px;
  height: auto;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.65);
  image-rendering: pixelated;      /* these are pixel-art frames — keep them crisp */
}
.pitch-text h2 {
  font-family: 'Anton', var(--body-font);
  font-size: clamp(26px, 3.2vw, 40px);
  line-height: 1.05;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #ffc83c;
  margin-bottom: 14px;
}
.pitch-text p {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.45;
  color: #cdc7ba;
  margin-bottom: 10px;
}
.pitch-note {
  font-size: 16px !important;
  color: #8e8878 !important;
  border-left: 3px solid rgba(255, 47, 106, 0.6);
  padding-left: 12px;
}
.pitch-cta {
  text-align: center;
  padding: 56px 0 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.pitch-cta-copy {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600; font-size: 15px; letter-spacing: 2px;
  color: #8e8878; text-transform: uppercase; margin-bottom: 16px;
}
.pitch-cta-btn {
  font-family: 'Anton', var(--body-font) !important;
  font-size: 26px !important;
  letter-spacing: 3px;
  padding: 16px 44px !important;
}
@media (max-width: 860px) {
  .pitch { padding: 12px 20px 70px; }
  .pitch-row, .pitch-row.reverse { flex-direction: column; gap: 22px; padding: 38px 0; }
  .pitch-row img { width: 100%; max-width: none; }
}
/* Once the player is picking a character the pitch is irrelevant. */
body.cs-picking .pitch { display: none; }

/* Actual-gameplay strip. Painted key art over a pixel game is a promise you
   have to keep — showing the real thing right under it is how you keep it. */
.hero-shots {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 40px 44px;
}
.hero-shots-label {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 700; font-size: 12px; letter-spacing: 3px;
  color: #7d7566; text-transform: uppercase; margin-bottom: 8px;
}
.hero-shots-row { display: flex; gap: 10px; max-width: 780px; }
.hero-shots-row img {
  width: 33.33%;
  height: auto;
  display: block;
  border: 2px solid rgba(255,255,255,0.10);
  image-rendering: pixelated;      /* these ARE pixel art — keep them crisp */
  box-shadow: 0 8px 22px rgba(0,0,0,0.6);
}

/* Once the player is picking a character the pitch is over: give the grid
   the full width and get the marketing out of its way. */
body.cs-picking .hero-panels,
body.cs-picking .hero-shots,
body.cs-picking .hero-kicker { display: none; }
body.cs-picking .hero-copy { max-width: none; flex: 1 1 auto; }
body.cs-picking .wordmark { font-size: clamp(40px, 5vw, 64px); flex-direction: row; gap: 0.18em; }
body.cs-picking .hero-tag { display: none; }
body.cs-picking .hero-inner { align-items: flex-start; padding-top: 32px; }

/* Box-art panel grid — the classic crime-game cover. */
.hero-panels {
  flex: 0 0 380px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.hero-panel {
  aspect-ratio: 1;
  background-size: cover;
  background-position: center;
  image-rendering: auto;
  border: 3px solid #0a0a0f;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.10), 0 12px 34px rgba(0,0,0,0.75);
}
.hero-panel[data-art="panel_driver"] { background-image: url('../assets/landing/panel_driver.jpg'); }
.hero-panel[data-art="panel_heist"]  { background-image: url('../assets/landing/panel_heist.jpg'); }
.hero-panel[data-art="panel_chase"]  { background-image: url('../assets/landing/panel_chase.jpg'); }
.hero-panel[data-art="panel_empire"] { background-image: url('../assets/landing/panel_empire.jpg'); }

@media (max-width: 1000px) {
  .hero-inner { flex-direction: column; gap: 30px; padding: 32px 22px; align-items: flex-start; }
  .hero-panels { flex: 1 1 auto; width: 100%; max-width: 460px; grid-template-columns: repeat(4, 1fr); }
  .hero-copy { max-width: none; }
}

/* ============ Gate cards (ID check, cloud save) ============ */
/* These sit on the key art, so they wear the same type as the hero — a
   pixel-font form under an Anton wordmark reads as two different products. */
.gate-card {
  margin: 0 0 4px;
  padding: 24px 26px 20px;
  max-width: 540px;
  text-align: left;
  background: rgba(8, 6, 12, 0.82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 180, 84, 0.28);
  border-left: 4px solid #ff2f6a;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.7);
}
/* On the landing the sign-in card IS the call to action, so it carries more
   weight than the same card does mid-flow. */
.gate-card-hero { max-width: 600px; margin-bottom: 18px; }
.gate-card-hero .gate-card-label { font-size: 30px; }
.gate-card-hero .gate-row .btn { font-size: 22px; padding: 14px 34px; }

.gate-card-label {
  font-family: 'Anton', var(--body-font);
  font-size: 26px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: #ffc83c;
  margin-bottom: 8px;
}
.gate-card-copy {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: 0.4px;
  line-height: 1.35;
  color: #a9a294;
  margin-bottom: 18px;
}
.gate-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
}
.gate-input {
  flex: 1 1 150px;
  min-width: 0;
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 1px;
  padding: 13px 14px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 2px;
  outline: none;
}
.gate-input::placeholder { color: #6d6659; }
.gate-input:focus { border-color: #ffc83c; box-shadow: 0 0 0 3px rgba(255, 200, 60, 0.16); }
/* The gate's own submit button — same family as PLAY, one size down. */
.gate-row .btn,
.gate-row .btn-primary {
  flex: 0 0 auto;
  font-family: 'Anton', var(--body-font);
  font-size: 19px;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding: 13px 26px;
  color: #14030a;
  background: linear-gradient(180deg, #ffe14d 0%, #ffb01f 55%, #ff8a1f 100%);
  border: none;
  border-radius: 2px;
  cursor: pointer;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.75);
  transition: transform 90ms ease, filter 90ms ease;
}
.gate-row .btn:hover { filter: brightness(1.07); transform: translate(-1px, -1px); }
.gate-row .btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 rgba(0,0,0,0.75); }
.gate-back { display: block; margin-top: 16px; font-size: 15px; }

.cs-char-head {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}
.cs-char-head .hidden { display: none; }

.mp-status {
  font-family: var(--body-font);
  font-size: 15px;
  color: var(--ink-dim);
  margin-top: 10px;
}
.mp-status.online { color: #5cf2c4; }
.mp-status.error  { color: var(--danger); }
.mp-server-label { display: none; }
body.dev-mode .mp-server-label {
  display: flex;
  gap: 8px;
  align-items: center;
  font-family: var(--body-font);
  font-size: 12px;
  color: var(--ink-dim);
  margin-top: 8px;
}
.mp-server-input {
  font-family: monospace;
  font-size: 12px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink-dim);
  padding: 2px 6px;
  width: 240px;
}

/* MP debug overlay (top-left during gameplay) */
.mp-debug {
  position: absolute;
  top: 60px;
  left: 18px;
  background: rgba(0, 0, 0, 0.75);
  border-left: 3px solid #5cf2c4;
  padding: 6px 10px;
  font-family: monospace;
  font-size: 11px;
  color: #5cf2c4;
  line-height: 1.5;
  white-space: pre;
  z-index: 4;
  pointer-events: none;
}
.mp-debug.hidden { display: none; }

.menu-buttons {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 18px;
}

.btn {
  font-family: var(--pixel-font);
  font-size: 12px;
  letter-spacing: 1px;
  padding: 12px 18px;
  background: var(--bg-2);
  color: var(--ink);
  border: 2px solid var(--ink-dim);
  cursor: pointer;
  transition: transform 60ms, background 60ms, border-color 60ms;
}
.btn:hover:not(:disabled) { transform: translate(-2px, -2px); border-color: var(--accent); }
.btn:active:not(:disabled) { transform: translate(1px, 1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-primary { background: var(--neon); color: #000; border-color: var(--neon); }
.btn-primary:hover:not(:disabled) { background: #d2ff63; border-color: #d2ff63; }
.btn-small { font-size: 10px; padding: 8px 12px; }
.btn-icon {
  background: rgba(0, 0, 0, 0.6);
  color: var(--neon);
  border: 2px solid var(--neon);
  width: 40px; height: 40px;
  font-size: 22px;
  cursor: pointer;
  font-family: var(--pixel-font);
}

/* ============ Character select ============ */
.char-section { margin: 18px 0 8px; text-align: left; }
.char-section-label {
  font-family: var(--pixel-font);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--accent);
  margin-bottom: 8px;
}
.char-flavor {
  font-size: 16px;
  color: var(--ink-dim);
  margin-bottom: 10px;
  font-style: italic;
}
.char-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 10px;
}
.char-card {
  background: var(--bg-2);
  border: 2px solid #333;
  padding: 10px 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--ink);
  font-family: var(--body-font);
  font-size: 16px;
  transition: border-color 80ms, transform 80ms;
}
.char-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.char-card.picked {
  border-color: var(--neon);
  box-shadow: 0 0 0 1px var(--neon), 0 0 16px rgba(182, 255, 59, 0.4);
}
.char-card img {
  width: 64px; height: 64px;
  object-fit: contain;
  image-rendering: pixelated;
}
.char-card .char-name {
  font-family: var(--pixel-font);
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--ink);
}
.char-card .char-tag {
  font-size: 12px;
  color: var(--ink-dim);
}

/* ============ HUD ============ */
.hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}
.hud.hidden { display: none; }
.hud > * { pointer-events: auto; }

.hud-row {
  position: absolute;
  left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  gap: 16px;
  pointer-events: none;
}
.hud-row > * { pointer-events: auto; }
.hud-top { top: 0; }
.hud-bottom { bottom: 0; }

.hud-stats {
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
}
.stat-block {
  background: rgba(0, 0, 0, 0.65);
  border: 2px solid var(--neon);
  padding: 6px 10px;
  min-width: 90px;
  text-align: center;
}
.stat-label {
  font-family: var(--pixel-font);
  font-size: 8px;
  letter-spacing: 1px;
  color: var(--neon);
  margin-bottom: 4px;
}
.cash-value {
  font-family: var(--pixel-font);
  font-size: 14px;
  color: var(--money);
}
.empire-value {
  font-family: var(--pixel-font);
  font-size: 11px;
  color: var(--accent-2);
}
.hp-bar {
  width: 120px;
  height: 12px;
  background: #2a0a0a;
  border: 1px solid #000;
  overflow: hidden;
}
.hp-fill {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, var(--danger), #ff8a8a);
  transition: width 100ms;
}
.wanted-stars {
  font-family: var(--pixel-font);
  font-size: 14px;
  color: var(--warn);
  letter-spacing: 2px;
  min-height: 18px;
}

.weapon-bar {
  display: flex;
  gap: 6px;
  background: rgba(0, 0, 0, 0.65);
  border: 2px solid var(--neon);
  padding: 6px;
}
.weapon-slot {
  width: 56px;
  padding: 6px 4px;
  background: var(--bg-2);
  border: 1px solid #333;
  text-align: center;
  font-family: var(--pixel-font);
  font-size: 8px;
  color: var(--ink-dim);
  cursor: pointer;
}
.weapon-slot.active {
  border-color: var(--neon);
  background: #1a2a14;
  color: var(--neon);
}
.weapon-slot .wkey {
  display: block;
  font-size: 9px;
  color: var(--accent);
  margin-bottom: 3px;
}
.ammo-value {
  font-family: var(--pixel-font);
  font-size: 14px;
  color: var(--neon);
  background: rgba(0, 0, 0, 0.65);
  border: 2px solid var(--neon);
  padding: 8px 12px;
}

.interact-prompt {
  position: absolute;
  left: 50%;
  bottom: 110px;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.85);
  border: 2px solid var(--neon);
  padding: 12px 18px;
  font-family: var(--pixel-font);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--neon);
  text-align: center;
  pointer-events: none;
  white-space: nowrap;
}
.interact-prompt.hidden { display: none; }
.interact-prompt .ik {
  display: inline-block;
  background: var(--neon);
  color: #000;
  padding: 2px 6px;
  margin-right: 6px;
}

.feed {
  position: absolute;
  right: 18px;
  top: 90px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
  pointer-events: none;
}
.feed-msg {
  font-family: var(--pixel-font);
  font-size: 10px;
  background: rgba(0, 0, 0, 0.7);
  border-left: 3px solid var(--neon);
  padding: 6px 10px;
  color: var(--ink);
  animation: feedSlide 240ms ease-out;
}
.feed-msg.money { border-left-color: var(--money); color: var(--money); }
.feed-msg.warn { border-left-color: var(--warn); color: var(--warn); }
.feed-msg.danger { border-left-color: var(--danger); color: var(--danger); }
@keyframes feedSlide {
  from { transform: translateX(40px); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

.prop-body {
  text-align: left;
  font-size: 18px;
  color: var(--ink);
  margin-bottom: 8px;
}
.prop-body .pl {
  display: flex; justify-content: space-between;
  padding: 4px 0;
  border-bottom: 1px dashed #333;
}
.prop-body .pl-k { color: var(--ink-dim); }
.prop-body .pl-v { color: var(--accent); }
.prop-body .pl-v.money { color: var(--money); }

.pause-stats {
  margin-top: 16px;
  font-size: 16px;
  color: var(--ink-dim);
  text-align: left;
}
.pause-stats .pl { display: flex; justify-content: space-between; padding: 2px 0; }

/* ============ Broker panel ============ */
.broker-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 14px;
  border-bottom: 2px solid #333;
}
.broker-tab {
  font-family: var(--pixel-font);
  font-size: 11px;
  letter-spacing: 1px;
  padding: 10px 14px;
  background: transparent;
  color: var(--ink-dim);
  border: 2px solid transparent;
  border-bottom: none;
  cursor: pointer;
}
.broker-tab.active {
  background: var(--bg-2);
  color: var(--neon);
  border-color: var(--neon);
}
.broker-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
  text-align: left;
  max-height: 380px;
  overflow-y: auto;
}
.broker-offer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--bg-2);
  border: 2px solid #333;
  padding: 10px 14px;
  gap: 12px;
}
.broker-offer:hover { border-color: var(--accent); }

/* Plot build-options menu (THE BURBS) — multiple buttons, one per build kind. */
.prop-build-menu {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 10px 0;
}
.prop-build-menu:empty { display: none; }
.btn-build {
  background: var(--bg-2);
  border: 2px solid var(--accent);
  color: var(--ink);
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 0.5px;
  padding: 8px 12px;
  text-align: left;
  cursor: pointer;
}
.btn-build:hover:not(:disabled) { background: var(--accent); color: #000; }
.btn-build:disabled { opacity: 0.5; cursor: not-allowed; }
/* One line standing in for the heavy-industry builds a small plot can't take. */
.build-locked-note {
  margin-top: 6px;
  padding: 6px 8px;
  font-size: 11px;
  line-height: 1.35;
  letter-spacing: 0.04em;
  color: var(--dim, #8b8b93);
  border: 1px dashed rgba(255,255,255,0.16);
  border-radius: 3px;
  text-transform: uppercase;
}

/* ===== Lucky Sevens slot machine panel ===== */
.slot-reels {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin: 18px 0 14px;
}
.slot-reel {
  width: 96px;
  height: 96px;
  background: #0a0a0a;
  border: 3px solid #c89b2a;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--pixel-font);
  font-size: 56px;
  color: #ffd84a;
  text-shadow: 0 0 6px #ff3d6e, 0 0 14px #ff3d6e;
  box-shadow: inset 0 0 12px #000, 0 0 12px rgba(255,61,110,0.4);
  user-select: none;
}
.slot-reel-img {
  width: 80px;
  height: 80px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.slot-reel.spinning {
  animation: slotSpin 60ms linear infinite;
}
@keyframes slotSpin {
  0%   { transform: translateY(0); filter: blur(1px); }
  50%  { transform: translateY(-8px); filter: blur(2px); }
  100% { transform: translateY(0); filter: blur(1px); }
}
.slot-result {
  font-family: var(--pixel-font);
  font-size: 13px;
  letter-spacing: 1px;
  color: #ffd84a;
  margin: 4px 0 12px;
  min-height: 18px;
}
.slot-result.win  { color: #79ff63; text-shadow: 0 0 8px #79ff63; }
.slot-result.lose { color: #888; }
.slot-result.jackpot {
  color: #ff3d6e;
  text-shadow: 0 0 10px #ff3d6e, 0 0 20px #ffd84a;
  font-size: 16px;
  animation: jackpotPulse 0.5s ease-in-out infinite alternate;
}
@keyframes jackpotPulse {
  from { transform: scale(1); }
  to   { transform: scale(1.08); }
}
.slot-bets {
  display: flex;
  gap: 6px;
  justify-content: center;
  margin-bottom: 10px;
}
.slot-bet {
  background: var(--bg-2);
  border: 2px solid #444;
  color: var(--ink);
  padding: 6px 14px;
  font-family: var(--pixel-font);
  font-size: 11px;
  cursor: pointer;
}
.slot-bet:hover { border-color: var(--accent); }
.slot-bet.active {
  background: var(--neon);
  color: #000;
  border-color: var(--neon);
}
.slot-stats {
  display: flex;
  gap: 16px;
  justify-content: center;
  margin-bottom: 14px;
}
.slot-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.slot-stat-k {
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--ink-dim);
}
.slot-stat-v {
  font-family: var(--pixel-font);
  font-size: 14px;
  color: var(--ink);
}
.broker-offer-info { flex: 1; }
.broker-offer-title {
  font-family: var(--pixel-font);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--ink);
  margin-bottom: 4px;
}
.broker-offer-meta {
  font-size: 15px;
  color: var(--ink-dim);
}
.broker-offer-pay {
  font-family: var(--pixel-font);
  font-size: 14px;
  color: var(--money);
  margin-right: 10px;
}
.broker-offer-btn {
  font-family: var(--pixel-font);
  font-size: 10px;
  padding: 8px 12px;
  background: var(--neon);
  color: #000;
  border: 2px solid var(--neon);
  cursor: pointer;
}
.broker-offer-btn:hover { background: #d2ff63; }
.broker-empty {
  color: var(--ink-dim);
  font-style: italic;
  padding: 18px;
  text-align: center;
}

/* ============ Mission tracker (HUD top-left) ============ */
.mission-tracker {
  position: absolute;
  top: 92px;
  left: 18px;
  background: rgba(0, 0, 0, 0.78);
  border: 2px solid var(--neon);
  padding: 10px 14px;
  min-width: 220px;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  pointer-events: auto;
  box-shadow: 0 0 14px rgba(182, 255, 59, 0.2);
}
.mission-tracker.hidden { display: none; }
.mt-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.mt-title {
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--neon);
}
.mt-payout {
  font-family: var(--pixel-font);
  font-size: 12px;
  color: var(--money);
}
.mt-objective {
  font-size: 16px;
  color: var(--ink);
}
.mt-timer {
  font-family: var(--pixel-font);
  font-size: 10px;
  color: var(--warn);
}
.mt-abandon {
  align-self: flex-start;
  font-family: var(--pixel-font);
  font-size: 8px;
  padding: 4px 8px;
  margin-top: 4px;
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid var(--ink-dim);
  cursor: pointer;
}
.mt-abandon:hover { color: var(--danger); border-color: var(--danger); }

.mt-progress {
  width: 100%;
  height: 8px;
  background: #2a2a2a;
  border: 1px solid #000;
  overflow: hidden;
}
.mt-progress.hidden { display: none; }
.mt-progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--neon), #d2ff63);
  transition: width 80ms linear;
}

/* ============ Minimap ============ */
.minimap {
  position: absolute;
  top: 92px;
  right: 18px;
  background: rgba(4, 6, 12, 0.78);
  border: 2px solid var(--neon);
  box-shadow: 0 0 14px rgba(182, 255, 59, 0.2);
  image-rendering: pixelated;
  pointer-events: none;
}
.minimap.hidden { display: none; }

.minimap-key {
  position: absolute;
  top: 92px;
  right: 244px;             /* sit immediately left of the minimap */
  background: rgba(4, 6, 12, 0.78);
  border: 2px solid var(--neon);
  box-shadow: 0 0 14px rgba(182, 255, 59, 0.2);
  padding: 6px 8px;
  font-family: var(--pixel-font);
  font-size: 8px;
  letter-spacing: 0.5px;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 3px;
  pointer-events: none;
  line-height: 1.1;
}
.minimap-key.hidden { display: none; }
.mk-title {
  color: var(--neon);
  margin-bottom: 2px;
  letter-spacing: 1px;
}
.mk-row {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.mk-sw {
  display: inline-block;
  width: 10px;
  height: 8px;
  border: 1px solid #000;
  flex-shrink: 0;
}
.mk-sw.mk-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
}
.mk-sw.mk-arrow {
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  border: none;
  width: 12px;
}

/* ============ Map transition fade ============ */
.transition-fade {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  z-index: 30;
  transition: opacity 500ms ease-in-out;
}
.transition-fade.on { opacity: 1; }
.transition-fade.hidden { display: none; }

/* ============ Flight fade — black overlay + plane silhouette ============ */
.flight-fade {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  z-index: 32;
  transition: opacity 400ms ease-in-out;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.flight-fade.on { opacity: 1; }
.flight-fade.hidden { display: none; }
.flight-banner {
  position: absolute;
  top: 35%;
  font-family: var(--pixel-font);
  font-size: 18px;
  letter-spacing: 2px;
  color: var(--neon);
  text-shadow: 0 0 8px rgba(182, 255, 59, 0.45);
  text-align: center;
  width: 100%;
}
.flight-plane {
  position: absolute;
  top: 55%;
  left: -200px;
  width: 192px;
  height: auto;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 8px rgba(108, 255, 142, 0.55));
}
.flight-fade.flying .flight-plane {
  animation: flightCross 2000ms linear forwards;
}
@keyframes flightCross {
  from { transform: translateX(0);                }
  to   { transform: translateX(calc(100vw + 400px)); }
}

/* ============ Airport ticket panel ============ */
.airport-ticket {
  background: #0c1018;
  border: 2px solid var(--accent);
  padding: 14px 18px;
  margin: 12px 0;
  text-align: left;
  font-family: var(--body-font);
  color: var(--ink);
  position: relative;
}
.airport-ticket::before {
  content: '✈';
  position: absolute;
  top: 8px; right: 12px;
  font-size: 28px;
  color: var(--accent);
  opacity: 0.5;
}
.airport-ticket-route {
  font-family: var(--pixel-font);
  font-size: 14px;
  letter-spacing: 1px;
  color: var(--neon);
  margin-bottom: 8px;
}
.airport-ticket-fare {
  font-family: var(--pixel-font);
  font-size: 22px;
  color: #ffd84a;
  margin: 6px 0;
}
.airport-ticket-meta {
  font-size: 13px;
  color: var(--ink-dim);
}

/* ============ Phone (GPS) ============ */
.phone-frame {
  background: var(--bg-1);
  border: 4px solid var(--neon);
  box-shadow: 0 0 30px rgba(182, 255, 59, 0.3), 6px 6px 0 #000;
  width: min(95vw, 920px);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
}
.phone-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 14px;
  background: var(--bg-2);
  border-bottom: 2px solid var(--neon);
}
.phone-title {
  font-family: var(--pixel-font);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--neon);
}
.phone-x {
  font-family: var(--pixel-font);
  font-size: 16px;
  background: transparent;
  border: 2px solid var(--ink-dim);
  color: var(--ink);
  cursor: pointer;
  width: 30px; height: 30px;
}
.phone-x:hover { border-color: var(--danger); color: var(--danger); }
.phone-body {
  display: flex;
  gap: 12px;
  padding: 12px;
  align-items: stretch;
}
.phone-map {
  background: rgba(4, 6, 12, 0.78);
  image-rendering: pixelated;
  flex: 1;
  cursor: crosshair;
}
.phone-side {
  width: 260px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-family: var(--body-font);
}
.phone-search {
  font-family: var(--body-font);
  font-size: 16px;
  padding: 8px 10px;
  background: var(--bg-2);
  color: var(--ink);
  border: 2px solid #333;
}
.phone-search:focus { outline: none; border-color: var(--neon); }
.phone-list {
  flex: 1;
  overflow-y: auto;
  max-height: 360px;
  border: 1px solid #333;
}
.phone-list-item {
  display: flex;
  justify-content: space-between;
  padding: 6px 10px;
  border-bottom: 1px solid #1d2030;
  cursor: pointer;
  font-size: 15px;
  color: var(--ink);
}
.phone-list-item:hover { background: var(--bg-2); }
.phone-list-item.active { background: #1c3220; color: var(--neon); }
.place-name { display: flex; flex-direction: column; gap: 1px; }
.place-addr { font-size: 12px; color: var(--ink-dim); letter-spacing: 0.5px; }
.phone-list-item .meta {
  color: var(--ink-dim);
  font-size: 13px;
}
.phone-gps {
  font-family: var(--pixel-font);
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--accent);
  padding: 6px 0;
  border-top: 1px solid #333;
}

/* Phone-map legend — explains every color on the map. */
.phone-legend {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #333;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--body-font);
  font-size: 12px;
  color: var(--ink);
}
.phone-legend-h {
  font-family: var(--pixel-font);
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--ink-dim);
  margin: 6px 0 2px;
}
.phone-legend-h:first-child { margin-top: 0; }
.phone-legend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 1.3;
}
.lk-swatch {
  display: inline-block;
  width: 14px;
  height: 10px;
  border: 1px solid #000;
  flex-shrink: 0;
}
.lk-swatch.lk-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.lk-swatch.lk-arrow {
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  border: none;
}
.phone-foot {
  padding: 8px 14px;
  font-size: 13px;
  color: var(--ink-dim);
  background: var(--bg-2);
  border-top: 1px solid var(--neon);
}
.phone-foot .ik {
  background: var(--neon);
  color: #000;
  padding: 1px 5px;
  margin: 0 2px;
}

.phone-tabs {
  display: flex;
  gap: 4px;
}
.phone-tab {
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 1px;
  padding: 6px 12px;
  background: transparent;
  color: var(--ink-dim);
  border: 2px solid transparent;
  cursor: pointer;
}
.phone-tab.active {
  background: var(--bg-1);
  color: var(--neon);
  border-color: var(--neon);
  border-bottom-color: var(--bg-1);
}
/* The frame is a max-height flex column, but the tab body had no overflow and
   no min-height, so a long list (RIDE in a big city) grew past the frame and
   rendered outside its own border. `min-height: 0` is the part that matters:
   without it a flex child refuses to shrink below its content and can never
   scroll. */
.phone-view {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.phone-view.hidden { display: none; }
/* Keep the scrollbar in the same visual language as everything else. */
.phone-view::-webkit-scrollbar { width: 10px; }
.phone-view::-webkit-scrollbar-track { background: var(--bg-0); }
.phone-view::-webkit-scrollbar-thumb {
  background: var(--bg-2);
  border: 2px solid var(--bg-0);
}
.phone-view::-webkit-scrollbar-thumb:hover { background: #2c3448; }

.career-wrap {
  display: flex;
  gap: 12px;
  padding: 12px;
  align-items: stretch;
  max-height: 70vh;
}
.career-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.career-jobs { flex: 1.2; }
.career-box {
  background: var(--bg-2);
  border: 2px solid #333;
  padding: 12px 14px;
}
.career-h {
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--accent);
  margin-bottom: 8px;
}
.career-big {
  font-family: var(--pixel-font);
  font-size: 14px;
  letter-spacing: 1px;
  color: var(--neon);
  margin-bottom: 4px;
}
.career-sub {
  font-size: 15px;
  color: var(--ink-dim);
  margin-bottom: 4px;
}
.career-bar {
  width: 100%;
  height: 8px;
  background: #11141d;
  border: 1px solid #000;
  overflow: hidden;
  margin: 6px 0;
}
.career-bar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent-2), var(--neon));
}
.career-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}
.career-job-list {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #333;
  max-height: 60vh;
}
.career-job-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid #1d2030;
  font-size: 15px;
  gap: 8px;
}
.career-job-item.locked { opacity: 0.5; }
.career-job-item.active { background: #1c3220; }
.career-job-info { flex: 1; min-width: 0; }
.career-job-name {
  font-family: var(--pixel-font);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--ink);
  margin-bottom: 3px;
}
.career-job-meta {
  font-size: 13px;
  color: var(--ink-dim);
}
.career-job-pay {
  font-family: var(--pixel-font);
  font-size: 11px;
  color: var(--money);
  margin-right: 6px;
}
.career-job-btn {
  font-family: var(--pixel-font);
  font-size: 9px;
  padding: 6px 10px;
  background: var(--neon);
  color: #000;
  border: 2px solid var(--neon);
  cursor: pointer;
}
.career-job-btn:hover:not(:disabled) { background: #d2ff63; }
.career-job-btn:disabled {
  background: transparent;
  color: var(--ink-dim);
  border-color: var(--ink-dim);
  cursor: not-allowed;
}

/* HUD "on the clock" wage indicator. */
.wage-stat .stat-label { color: var(--money); }
.wage-stat .wage-value { color: var(--money); font-family: var(--pixel-font); font-size: 14px; }
.wage-stat.hidden { display: none; }

/* GPS HUD readout — only visible while a waypoint is active. */
.gps-stat .stat-label { color: #ffea4d; }
.gps-stat .gps-value {
  color: #ffea4d;
  font-family: var(--pixel-font);
  font-size: 10px;
  line-height: 1.4;
  letter-spacing: 0.5px;
  text-shadow: 1px 1px 0 #000;
}
.gps-stat .gps-dist { color: #fff7c0; font-size: 13px; }
.gps-stat.hidden { display: none; }

.weather-value {
  font-family: var(--pixel-font);
  font-size: 11px;
  letter-spacing: 1px;
}
.weather-value.clear  { color: #ffe48a; }
.weather-value.cloudy { color: #a6b0c5; }
.weather-value.rain   { color: #7eb6ff; }
.weather-value.storm  { color: #c89eff; }
.weather-value.fog    { color: #cfd4dd; }
.weather-value.snow   { color: #e8f0ff; }

/* ===== Walkthrough / onboarding ===== */
.cs-step.hidden { display: none; }

.hud-buttons { display: flex; gap: 8px; }

.hud-hints {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--body-font);
  font-size: 13px;
  letter-spacing: 1px;
  color: var(--ink-dim);
  opacity: 0.55;
  pointer-events: none;
  white-space: nowrap;
}
.hud-hints kbd,
.tour-body kbd {
  font-family: var(--pixel-font);
  font-size: 10px;
  padding: 2px 5px;
  margin: 0 2px;
  background: #000;
  border: 1px solid #5cf2c4;
  border-radius: 3px;
  color: #5cf2c4;
}

.tour-panel { max-width: 420px; text-align: center; }
.tour-body {
  font-family: var(--body-font);
  font-size: 18px;
  line-height: 2;
  margin: 16px 0;
}
.tour-body kbd { font-size: 12px; padding: 3px 7px; }
.tour-dots { display: flex; justify-content: center; gap: 8px; margin-bottom: 14px; }
.tour-dot {
  width: 8px; height: 8px;
  background: #333;
  border-radius: 50%;
}
.tour-dot.active { background: #5cf2c4; }

/* ===== RIDE app (MAD CABS) ===== */
.ride-header {
  font-family: var(--pixel-font);
  font-size: 10px;
  color: #ffb454;
  letter-spacing: 1px;
  margin: 10px 12px 8px;
}
.ride-list { display: flex; flex-direction: column; gap: 6px; padding: 0 12px 12px; }
.ride-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--pixel-font);
  font-size: 11px;
  padding: 12px 14px;
  background: #0d1017;
  color: var(--ink);
  border: 2px solid #2a3040;
  cursor: pointer;
}
.ride-row:hover:not(:disabled) { border-color: #5cf2c4; }
.ride-row:disabled { opacity: 0.45; cursor: default; }
.ride-dest { color: #5cf2c4; }
.ride-fare { color: var(--money); }
.ride-fare.broke { color: var(--danger); }

/* ===== Casino tables (blackjack + roulette) ===== */
.bj-hands { margin: 14px 0 8px; display: flex; flex-direction: column; gap: 10px; }
.bj-hand { display: flex; align-items: baseline; gap: 12px; justify-content: center; }
.bj-hand-k {
  font-family: var(--pixel-font);
  font-size: 10px;
  color: var(--ink-dim);
  letter-spacing: 1px;
  min-width: 70px;
  text-align: right;
}
.bj-cards { font-family: var(--pixel-font); font-size: 15px; color: var(--ink); letter-spacing: 2px; }
.ru-wheel {
  font-family: var(--pixel-font);
  font-size: 40px;
  margin: 16px auto 8px;
  width: 110px;
  padding: 14px 0;
  border: 3px solid var(--ink-dim);
  color: var(--ink);
  background: #000;
}
.ru-wheel.red   { color: #ff5c5c; border-color: #ff5c5c; }
.ru-wheel.black { color: #e6e9ef; border-color: #e6e9ef; }
.ru-wheel.green { color: #6dff8e; border-color: #6dff8e; }
.ru-choices { display: flex; gap: 8px; justify-content: center; align-items: center; flex-wrap: wrap; margin: 10px 0; }
.ru-choice {
  font-family: var(--pixel-font);
  font-size: 10px;
  padding: 8px 12px;
  background: #0d1017;
  color: var(--ink);
  border: 2px solid #2a3040;
  cursor: pointer;
}
.ru-choice.active { border-color: #b6ff3b; color: #b6ff3b; }
.ru-choice[data-pick="red"]   { color: #ff5c5c; }
.ru-choice[data-pick="black"] { color: #cfd4dd; }
.ru-straight { font-family: var(--pixel-font); font-size: 10px; color: var(--ink-dim); }
.ru-straight input {
  width: 64px;
  font-family: var(--pixel-font);
  font-size: 11px;
  padding: 6px;
  background: #000;
  color: #fff;
  border: 2px solid #2a3040;
}
.ride-section {
  font-family: var(--pixel-font);
  font-size: 9px;
  color: var(--ink-dim);
  letter-spacing: 1px;
  margin: 10px 2px 2px;
  /* Pixel type at its default line-height overlaps itself the moment a section
     header runs to two lines — which the freight board's does, because it has
     to say what you can carry as well as what is on offer. */
  line-height: 1.6;
}
.ride-meta { font-family: var(--body-font); font-size: 13px; color: var(--ink-dim); margin-left: auto; margin-right: 14px; }
.btn.hidden { display: none; }

/* ===== BAG tab ===== */
.bag-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--pixel-font);
  font-size: 10px;
  padding: 10px 12px;
  background: #0d1017;
  border: 2px solid #2a3040;
}
.bag-name { color: var(--ink); }
.bag-meta { font-family: var(--body-font); font-size: 14px; color: var(--ink-dim); }
.bag-total .bag-name { color: var(--money); }
.bag-total .bag-meta { color: var(--money); }
.wanted-stars.hard { color: var(--danger); text-shadow: 0 0 8px rgba(255, 77, 77, 0.6); }
.clock-value {
  font-family: var(--pixel-font);
  font-size: 11px;
  color: #9ecbff;
  letter-spacing: 1px;
}

/* ===== County lockup ===== */
.prison-year {
  font-family: var(--pixel-font);
  font-size: 22px;
  color: #ffb454;
  margin: 18px 0 10px;
  letter-spacing: 2px;
}
.prison-progress { margin: 0 auto 14px; max-width: 320px; display: block; height: 10px; background: #000; border: 2px solid #2a3040; }
.prison-progress .mt-progress-fill { background: #ffb454; height: 100%; }
.prison-note { font-family: var(--body-font); font-size: 15px; color: var(--ink-dim); margin: 6px 0; }
.prison-fine { font-size: 13px; }

/* ===== The sally port lock ===== */
/* `.hidden` is per-component in this sheet, never global — the two stages of
   this panel need their own rule or they both draw at once. */
#sallyChoice.hidden, #sallyLock.hidden { display: none; }
/* The barrel is the whole game: a pick sweeping a bar, five sweet spots you
   never see, and a readout that tells you a SIDE and nothing else. */
.lock-pins {
  display: flex; justify-content: center; gap: 10px; margin: 16px 0 12px;
}
.lock-pin {
  width: 16px; height: 16px; background: #0d1017; border: 2px solid #2a3040;
}
.lock-pin.set { background: var(--neon); border-color: var(--neon); box-shadow: 0 0 8px rgba(182,255,59,0.6); }
.lock-barrel {
  position: relative; height: 46px; background: #0d1017;
  border: 2px solid #2a3040; overflow: hidden;
  /* Tick marks, so the eye has something to aim by without being told
     anything true about where the pin is. */
  background-image: repeating-linear-gradient(90deg,
    #0d1017 0 9.5%, #171c28 9.5% 10%);
  cursor: pointer;
}
.lock-pick {
  position: absolute; top: 0; bottom: 0; left: 0; width: 3px;
  margin-left: -1px; background: var(--accent);
  box-shadow: 0 0 10px var(--accent);
}
.lock-barrel.jam { animation: lock-jam 220ms steps(2, end) 2; }
.lock-barrel.seat { border-color: var(--neon); }
@keyframes lock-jam {
  0%   { transform: translateX(0); border-color: var(--danger); }
  50%  { transform: translateX(-6px); border-color: var(--danger); }
  100% { transform: translateX(0); border-color: var(--danger); }
}
.lock-meta {
  display: flex; justify-content: space-between; align-items: center;
  font-family: var(--pixel-font); font-size: 10px; color: var(--ink-dim);
  letter-spacing: 1px; margin: 8px 2px 4px;
}
#lockStrikes { color: var(--danger); letter-spacing: 3px; }
#lockSay.good { color: var(--neon); }
#lockSay.bad  { color: var(--danger); }
body.mobile .lock-barrel { height: 62px; }
body.mobile #lockSetBtn { padding: 14px 12px; }

/* ===== THE BIG BOARD (stock exchange) ===== */
.market-panel { max-width: 1180px; text-align: left; }
.market-head { display: flex; align-items: flex-start; gap: 20px; justify-content: space-between; }
.market-title { font-size: 22px; margin-bottom: 4px; }
.market-sub { font-family: var(--body-font); font-size: 14px; color: var(--ink-dim); }
.market-port { display: flex; gap: 20px; margin-left: auto; }
.market-port-row { text-align: right; }
.market-port-row span {
  display: block; font-family: var(--pixel-font); font-size: 8px;
  color: var(--ink-dim); letter-spacing: 1px; margin-bottom: 3px;
}
.market-port-row b { font-family: var(--pixel-font); font-size: 13px; color: var(--ink); }
.market-port-row b.up { color: #6dff8e; }
.market-port-row b.down { color: #ff6b6b; }

.market-body { display: flex; gap: 14px; margin-top: 14px; align-items: flex-start; }
.market-list { width: 288px; display: flex; flex-direction: column; gap: 3px; max-height: 380px; overflow-y: auto; }
.mkt-row {
  display: flex; align-items: center; gap: 8px; width: 100%;
  font-family: var(--pixel-font); font-size: 10px;
  padding: 8px 9px; background: #0d1017; color: var(--ink);
  border: 2px solid #2a3040; cursor: pointer; text-align: left;
}
.mkt-row:hover { border-color: #4a5468; }
.mkt-row.sel { border-color: #5cf2c4; background: #111a20; }
.mkt-dot { width: 9px; height: 9px; border-radius: 2px; flex: none; display: inline-block; margin-right: 5px; }
.mkt-tick { width: 44px; color: var(--ink); }
.mkt-px { width: 62px; text-align: right; color: var(--ink-dim); }
.mkt-ch { width: 74px; text-align: right; font-size: 9px; }
.mkt-ch.up, .up { color: #6dff8e; }
.mkt-ch.down, .down { color: #ff6b6b; }
.mkt-own {
  margin-left: auto; font-size: 8px; color: #ffd84a;
  border: 1px solid #ffd84a; padding: 1px 4px;
}

.market-main { flex: 1; min-width: 0; }
.market-chart-head { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 6px; }
.market-sel-name { font-family: var(--pixel-font); font-size: 12px; color: var(--ink); }
.market-sel-sector { font-family: var(--body-font); font-size: 14px; color: var(--ink-dim); margin-top: 4px; }
.market-sel-price b { font-family: var(--pixel-font); font-size: 20px; color: var(--ink); }
.market-chg { display: block; text-align: right; font-family: var(--body-font); font-size: 15px; margin-top: 3px; }
.market-chart { width: 100%; background: #0a0d13; border: 2px solid #2a3040; display: block; }
.market-hint { font-family: var(--body-font); font-size: 13px; color: var(--ink-dim); margin-top: 5px; }

.market-trade { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.market-trade-row { display: flex; align-items: center; gap: 8px; }
.market-trade-k {
  font-family: var(--pixel-font); font-size: 9px; color: var(--ink-dim);
  letter-spacing: 1px; width: 74px;
}
.market-qty {
  font-family: var(--pixel-font); font-size: 11px; padding: 7px 8px; width: 92px;
  background: #000; color: #fff; border: 2px solid #2a3040;
}
.market-held { font-family: var(--body-font); font-size: 14px; color: var(--ink-dim); }
.market-msg { font-family: var(--body-font); font-size: 15px; margin-top: 8px; min-height: 20px; }
.market-msg.ok { color: #6dff8e; }
.market-msg.bad { color: #ff6b6b; }

.market-positions { margin-top: 14px; border-top: 2px solid #2a3040; padding-top: 10px; }
.market-pos-head { font-family: var(--pixel-font); font-size: 9px; color: var(--ink-dim); letter-spacing: 1px; margin-bottom: 7px; }
.market-pos-list { display: flex; flex-direction: column; gap: 4px; max-height: 132px; overflow-y: auto; }
.mkt-pos {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--body-font); font-size: 15px; color: var(--ink);
  padding: 7px 10px; background: #0d1017; border: 2px solid #2a3040;
}
.mkt-pos .mkt-tick { font-family: var(--pixel-font); font-size: 10px; }
.mkt-pos span:nth-child(2) { flex: 1; color: var(--ink-dim); }
.mkt-mini {
  font-family: var(--pixel-font); font-size: 8px; padding: 5px 8px;
  background: #000; color: var(--ink); border: 2px solid #2a3040; cursor: pointer;
}
.mkt-mini:hover { border-color: #ff6b6b; color: #ff6b6b; }

/* ===== Net worth breakdown ===== */
.stat-clickable { cursor: pointer; }
.stat-clickable:hover .cash-value { text-shadow: 0 0 8px currentColor; }
.worth-panel { max-width: 900px; text-align: left; }
.worth-body { margin-top: 14px; max-height: 460px; overflow-y: auto; }
.worth-sec { margin-bottom: 14px; }
.worth-sec-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--pixel-font); font-size: 10px; color: #5cf2c4;
  letter-spacing: 1px; padding-bottom: 6px; border-bottom: 2px solid #2a3040; margin-bottom: 5px;
}
.worth-sec-head b { color: var(--ink); font-size: 12px; }
.worth-row {
  display: flex; align-items: baseline; gap: 12px;
  font-family: var(--body-font); font-size: 15px; color: var(--ink);
  padding: 6px 8px;
}
.worth-row:nth-child(even) { background: rgba(255,255,255,0.02); }
.worth-row > span:first-child { font-family: var(--pixel-font); font-size: 10px; width: 150px; flex: none; }
.worth-row > span:nth-child(2) { flex: 1; }
.worth-row > b { font-family: var(--pixel-font); font-size: 10px; margin-left: auto; }
.worth-dim { color: var(--ink-dim); }
.wanted-label {
  font-family: var(--pixel-font);
  font-size: 7px;
  letter-spacing: 1px;
  color: var(--ink-dim);
  margin-top: 3px;
}
.wanted-label.hard { color: var(--warn); }
.wanted-label.critical { color: var(--danger); text-shadow: 0 0 6px rgba(255,77,77,0.7); }

/* ===== Laying low ===== */
.hide-overlay {
  position: absolute; inset: 0;
  background: rgba(3, 5, 10, 0.88);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; z-index: 6; pointer-events: none;
}
.hide-overlay.hidden { display: none; }
.hide-title {
  font-family: var(--pixel-font); font-size: 22px; color: #5cf2c4;
  letter-spacing: 3px; text-shadow: 0 0 14px rgba(92,242,196,0.5);
}
.hide-bar { width: 300px; height: 8px; background: #000; border: 2px solid #2a3040; }
.hide-fill { height: 100%; width: 0%; background: #5cf2c4; }
.hide-count { font-family: var(--pixel-font); font-size: 13px; color: var(--ink); }
.hide-note { font-family: var(--body-font); font-size: 15px; color: var(--ink-dim); max-width: 420px; text-align: center; }
.sentence-value { font-family: var(--pixel-font); font-size: 11px; color: var(--warn); }
.sentence-obj { font-family: var(--pixel-font); font-size: 7px; color: var(--ink-dim); margin-top: 3px; letter-spacing: 1px; }
.stat-block.hidden { display: none; }

/* Street address under a property's name — the panel header reads like a
   listing rather than a category label. */
.prop-address {
  font-family: var(--pixel-font);
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--ink-dim);
  margin: -14px 0 18px;
}
.prop-address.hidden { display: none; }

/* One-time prompt to attach a recovery email, shown after the player owns
   something worth losing. Sits low so it never covers the action. */
.email-nudge {
  position: absolute;
  left: 50%; bottom: 96px;
  transform: translateX(-50%);
  z-index: 8;
  width: min(92vw, 560px);
  padding: 16px 18px;
  background: rgba(8, 6, 12, 0.92);
  border: 1px solid rgba(255, 180, 84, 0.35);
  border-left: 4px solid #ffc83c;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7);
}
.email-nudge.hidden { display: none; }
.email-nudge-copy {
  font-family: 'Barlow Condensed', var(--body-font);
  font-weight: 600; font-size: 17px; color: #e6e2d6; margin-bottom: 12px;
}
.email-nudge-row { display: flex; gap: 8px; align-items: stretch; flex-wrap: wrap; }
.email-nudge-row .gate-input { flex: 1 1 200px; font-size: 16px; padding: 10px 12px; }
.email-nudge-row .btn { font-size: 16px; padding: 10px 18px; }


/* ---- Shop list (gunsmith, and anything else that sells a catalogue) ---- */
.shop-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 46vh;
  overflow-y: auto;
  min-height: 0;                 /* flex children need this to scroll */
  margin: 10px 0;
  padding-right: 4px;
}
.shop-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 3px;
  background: rgba(255,255,255,0.02);
}
.shop-row.owned { border-color: rgba(120,220,140,0.35); }
.shop-name { flex: 1 1 auto; font-size: 13px; letter-spacing: 0.06em; }
.shop-stat { flex: 0 0 auto; font-size: 11px; color: var(--dim, #8b8b93); letter-spacing: 0.04em; }
.shop-price { flex: 0 0 auto; font-size: 12px; min-width: 78px; text-align: right; }
.shop-row .btn { flex: 0 0 auto; padding: 4px 12px; font-size: 11px; }

/* ============================================================
   MOBILE — the handheld shell
   ============================================================
   The controls get their OWN space below the screen rather than floating on
   top of the world. On a phone the viewport is the scarce resource, and a
   thumb parked over the bottom-left of the play area hides exactly the half
   of the street you are walking into.

   Nothing here applies unless touch-controls.js decides this is a handheld,
   so a laptop with a touchscreen is untouched. */

#touchControls { display: none; }

body.mobile #touchControls {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  justify-items: center;
  gap: 6px;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  /* 100dvh, not 100vh. On iOS Safari the URL bar is part of `vh` but not part
     of what you can actually see, so a vh-sized tray sits partly underneath
     the browser chrome and steals the difference from the world. */
  height: var(--tc-height, min(30dvh, 250px));
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom)) 10px;
  background: linear-gradient(180deg, #16161a 0%, #0e0e11 100%);
  border-top: 1px solid rgba(255,255,255,0.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
  z-index: 40;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* The play area shrinks to sit above the controls — the canvas reads its own
   CSS box for sizing, so this is the whole of "make the game smaller". */
body.mobile #game { height: calc(100dvh - var(--tc-height, min(30dvh, 250px))); }
body.mobile #hud  { bottom: calc(var(--tc-height, min(30dvh, 250px)) + 6px); }

/* The PAD is a full-height flex container filling its grid column, so giving
   it pointer-events meant the whole left and right edge of the screen ate
   touches — including over buttons belonging to other UI. Only the stick and
   the buttons themselves should capture anything. */
body.mobile .tc-pad {
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
}
body.mobile .tc-stick,
body.mobile .tc-btn { pointer-events: auto; }

.tc-stick {
  position: relative;
  /* Sized against the TRAY, not the viewport width. A vw-sized stick on a
     600px phone came out ~180px across — bigger than a thumb needs and wide
     enough that the right-hand one ran off the edge of the screen. */
  width: min(24vw, 22dvh, 104px);
  height: min(24vw, 22dvh, 104px);
  /* Both axes pinned. Inside a stretch-aligned flex column the width alone
     let it grow into an oval, and an oval thumbstick reads its own centre
     wrong. */
  flex: 0 0 auto;
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 42%, rgba(255,255,255,0.07), rgba(255,255,255,0.02) 60%),
    #1c1c21;
  border: 1px solid rgba(255,255,255,0.12);
  box-shadow: inset 0 2px 10px rgba(0,0,0,0.55);
  display: flex; align-items: center; justify-content: center;
}
.tc-stick.tc-fire { border-color: rgba(255,110,90,0.35); }

.stick-knob {
  width: 42%; height: 42%;
  border-radius: 50%;
  background: linear-gradient(180deg, #4a4a55, #2a2a31);
  border: 1px solid rgba(255,255,255,0.16);
  box-shadow: 0 3px 8px rgba(0,0,0,0.5);
  transition: transform 0.05s linear;
  pointer-events: none;
}
.tc-fire .stick-knob { background: linear-gradient(180deg, #a8493c, #6d2c24); }

.tc-cap {
  position: absolute; bottom: -17px; left: 0; right: 0;
  text-align: center; font-size: 9px; letter-spacing: 0.12em;
  color: rgba(255,255,255,0.32);
  pointer-events: none;
}

body.mobile .tc-mid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  max-width: 190px;
  /* Same reason as .tc-pad: the grid's gaps and padding are not buttons and
     should not eat touches meant for whatever is behind them. */
  pointer-events: none;
}

.tc-btn {
  appearance: none;
  min-width: 54px;
  padding: 7px 5px 5px;
  border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.14);
  background: linear-gradient(180deg, #2a2a31, #1a1a1f);
  color: #e8e8ee;
  font: 600 15px/1 inherit;
  letter-spacing: 0.06em;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  box-shadow: 0 2px 0 rgba(0,0,0,0.45);
}
/* The label used to be a dim 8px caption under a big keyboard letter. With the
   letter gone it IS the button, so it gets the size the letter had. */
.tc-btn small {
  font-size: 8px; letter-spacing: 0.14em;
  color: rgba(255,255,255,0.42); font-weight: 500;
}
.tc-btn { font-size: 13px; letter-spacing: 0.1em; justify-content: center; }
.tc-btn.held {
  background: linear-gradient(180deg, #3a3a45, #24242b);
  transform: translateY(1px);
  box-shadow: 0 1px 0 rgba(0,0,0,0.45);
}

/* Landscape: the screen is wide and short, so the shell goes down the sides
   and the play area keeps its full height. */
@media (orientation: landscape) {
  body.mobile #touchControls {
    --tc-height: auto;
    top: 0;
    height: 100dvh;
    grid-template-columns: auto 1fr auto;
    background: none;
    border-top: none;
    pointer-events: none;                 /* only the controls take touches */
    padding: 12px calc(12px + env(safe-area-inset-right)) 12px calc(12px + env(safe-area-inset-left));
  }
  body.mobile #touchControls .tc-mid { align-self: end; justify-self: center; }
  body.mobile #game { height: 100dvh; }
  body.mobile #hud { bottom: 8px; }
  .tc-stick { width: min(20vh, 116px); }
}

/* Panels are desktop-width by default and overflow a phone. */
@media (max-width: 780px) {
  .panel, .panel-wide { max-width: 94vw; padding: 14px; }
  .panel .title { font-size: 17px; }
  .shop-list { max-height: 52vh; }
  .shop-row { flex-wrap: wrap; gap: 6px; }
  .shop-stat { order: 3; width: 100%; }
  .menu-buttons { flex-wrap: wrap; gap: 6px; }
  .menu-buttons .btn { flex: 1 1 auto; }
}

/* ============ Landing page on a phone ============ */
/* The existing breakpoints stop at 860px, which is a small tablet. A 390px
   phone got a hero sized for a laptop: a wordmark wider than the screen and a
   sign-in form below the fold. */
@media (max-width: 560px) {
  .hero-inner { padding: 22px 16px 28px; gap: 20px; min-height: auto; }
  .hero-wordmark, .hero-title { font-size: clamp(46px, 17vw, 78px); line-height: 0.86; }
  .hero-kicker { font-size: 10px; letter-spacing: 2px; }
  .hero-tag { font-size: 15px; }

  /* Sign in without scrolling. It is the only thing on this page that
     matters, and on a phone it was under the fold behind the art. */
  .gate-card { padding: 16px 16px 14px; max-width: none; }
  .gate-card input { font-size: 16px; }   /* 16px stops iOS zooming the page */
  .menu-buttons { flex-direction: column; align-items: stretch; }

  .hero-panels { max-width: none; grid-template-columns: repeat(2, 1fr); gap: 6px; }
  .hero-marquee { flex-wrap: wrap; gap: 6px; }
  .hero-marquee li { font-size: 10px; }
  .pitch { padding: 8px 16px 48px; }
  .pitch h3 { font-size: 20px; }
  .pitch p { font-size: 14px; }
}

/* Once you are in the world the marketing page is just weight on the DOM.
   (.hero-shots was in this list and does not exist in the markup — a selector
   that matches nothing reads as a rule that works.) */
body.mobile .pitch { display: none; }

/* The pad only belongs on screen when there is a world to drive. On the title
   and character select it covers the one screen a new player has to read. */
body.mobile #touchControls.tc-idle { opacity: 0; pointer-events: none; }
/* ...and the play area only gives up its height once the pad is really there. */
body.mobile:not(.mobile-playing) #game { height: 100dvh; }

/* Keyboard hints on a device with no keyboard are noise, and they sit exactly
   where the action buttons go. The pad's own labels say the same thing. */
body.mobile .hud-hints { display: none; }

/* The weapon bar is a row of numbered keyboard slots. It stays — knowing what
   you are carrying matters — but the slot NUMBERS are meaningless without a
   keyboard, and at phone size the row has to shrink to fit at all. */
body.mobile #weaponBar { transform: scale(0.72); transform-origin: bottom left; }

/* ============================================================
   MOBILE HUD
   ============================================================
   The desktop HUD is eight stat blocks, a map with a legend, a feed and a
   weapon rack, laid out for 1400px+. Dropped onto a 390px phone it covered
   the world completely — you could not see your own character.

   The rule here: the world is the interface. Anything that is not HP, money
   or heat is either shrunk to a glance or moved into the phone, where there
   is a whole screen for it. */

/* These are gated on body.mobile ALONE, not on a width media query as well.
   The class already means "touch device with a small viewport" — that is the
   whole decision, made once, in one place. Double-gating on a breakpoint made
   the rules impossible to see anywhere except real hardware, which is how the
   minimap legend shipped still covering a phone screen. */
/* One thin strip instead of a wall of boxes. */
body.mobile .hud-top { padding: 4px 6px; gap: 4px; }
/* Scroll rather than clip. If the strip genuinely cannot fit — a long sentence
   plus a big balance — cutting the last chip in half is worse than letting the
   player push it. */
body.mobile .hud-stats { gap: 3px; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; }

body.mobile .stat-block {
  padding: 2px 6px;
  min-width: 0;
  border-radius: 3px;
}
body.mobile .stat-label { font-size: 7px; letter-spacing: 0.08em; opacity: 0.6; }
body.mobile .cash-value,
body.mobile .empire-value,
body.mobile .clock-value,
body.mobile .weather-value,
body.mobile .gps-value,
body.mobile .wage-value { font-size: 11px; }
body.mobile .hp-bar { width: 54px; height: 7px; }
body.mobile .wanted-stars { font-size: 10px; letter-spacing: -1px; }
body.mobile .wanted-label { display: none; }

/* The SENTENCE chip was the tallest thing in the strip — a wrapped value plus
   an objective line — so it set the height for the whole row and the chips
   beside it ended up underneath it. One line each, and the row stays a strip. */
body.mobile #sentenceValue { font-size: 11px; white-space: nowrap; }
/* The objective ("FIND A SHANK") is the third line of the tallest chip in a
   strip that already does not fit. Every step of it is signposted in the world
   anyway — the stash says "Pry up the brick", the gate says "FORCE THE GATE" —
   so on a phone it is a caption for something you are looking straight at. */
body.mobile #sentenceObj { display: none; }
/* Same height for every chip, so the strip is a strip. */
body.mobile .hud-stats { align-items: stretch; }
body.mobile .stat-block {
  display: flex; flex-direction: column; justify-content: center;
  /* Do not shrink below the content. `min-width: 0` above lets flex squeeze a
     chip narrower than its own value, and combined with the ellipsis rule
     below that turns "$34K" into "$3…" while there is still slack in the row.
     A chip is as wide as what it says. */
  flex: 0 0 auto;
}
/* Nothing in the strip may print outside its own chip. This is what put
   "$100,000" across the top of WANTED. */
body.mobile .stat-block > * {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}

/* Everything you do not need at a glance while driving lives in the phone.
   EMPIRE, SKY and the clock are all things you go and look at. */
body.mobile #empireValue, body.mobile #weatherBlock,
body.mobile #clockBlock, body.mobile #gpsBlock { display: none; }
body.mobile .stat-block:has(#empireValue) { display: none; }

/* The minimap is genuinely useful, but the LEGEND is a wall of text
   explaining colours you can read at a glance. */
body.mobile #minimapKey, body.mobile .minimap-key { display: none !important; }
/* 220x160 backing store — keep that 11:8 ratio. Forcing it square would
   distort the map, which is the same mistake as stretching the world. */
body.mobile #minimap, body.mobile .minimap {
  width: 110px !important;
  height: 80px !important;
  opacity: 0.85;
}

/* Notifications: a few lines at the edge, not a column down the screen. */
body.mobile #feed, body.mobile .feed {
  max-width: 62vw;
  font-size: 10px;
  line-height: 1.25;
  max-height: 84px;
  overflow: hidden;
  opacity: 0.9;
}
body.mobile .feed-msg { padding: 2px 6px; font-size: 10px; }

/* The ammo readout duplicates the weapon bar right next to it. */
body.mobile #ammoValue { font-size: 11px; }

body.mobile .mission-tracker { max-width: 56vw; font-size: 10px; padding: 6px 8px; }
body.mobile .mt-title { font-size: 11px; }

body.mobile .btn-icon { width: 34px; height: 34px; font-size: 15px; }

/* Developer telemetry never belongs over a phone screen. */
body.mobile #mpDebug { display: none !important; }


/* Ammo count under a carried weapon. Red when dry — the one thing you need to
   notice mid-fight. */
.wammo { font-size: 10px; color: #8fd48f; letter-spacing: 0.04em; }
.wammo-out { color: #ff6b5e; }

/* ---- Mobile HUD, second pass (from a real phone screenshot) ---- */

/* The big "FISTS ∞" readout duplicates the weapon slot two inches away, and
   at phone size it sat on top of the world. The slot already shows the gun
   and its rounds. */
body.mobile #ammoValue {
  font-size: 9px;
  padding: 2px 6px;
  opacity: 0.75;
}

/* The minimap and the notification feed were both pinned to the top-right and
   printed over each other. The map keeps the corner; the feed moves under it. */
body.mobile #feed {
  /* Top-left is the only corner nothing else claims: the map owns top-right,
     the weapon slots bottom-left, the ammo readout bottom-right. Parking it
     bottom-left put it through the weapon slots instead of the map.
     Anchored to the strip's own height rather than a measured constant — a
     hardcoded 40px cleared it by -1px here and would drift further the moment
     a phone renders the type any larger. */
  top: calc(var(--hud-strip-h, 42px) + 6px);
  bottom: auto;
  left: 6px;
  right: auto;
  /* The desktop feed hangs off the right edge, so its items are right-aligned.
     Moving it left without this leaves the text ragged against the wrong edge. */
  align-items: flex-start;
  max-width: 56vw;
  max-height: 56px;
}

/* NOTE: #weaponBar sits inside .hud-bottom and is laid out in flow, so a
   `bottom` offset on it does nothing at all. Anything that needs to move it
   has to move the row. */

/* Give the world every pixel the chrome is not using. */
body.mobile { --hud-strip-h: 42px; }
body.mobile .hud-top { padding: 3px 5px; min-height: var(--hud-strip-h); box-sizing: border-box; }
body.mobile .stat-block { padding: 1px 4px; }

/* ============================================================
   MOBILE, third pass — from phone screenshots
   ============================================================ */

/* THE CONTROLS WERE DRAWN OVER EVERY PANEL. The tray sits at z-index 40 and
   overlays are below it, so the sticks and buttons covered the BUY buttons in
   the gunsmith and the confirm button on a property. You could see the thing
   you wanted to press and not press it.
   While any panel is open there is nothing to drive, so the pad goes away. */
body.mobile:has(.overlay:not(.hidden)) #touchControls { display: none !important; }

/* Panel titles were sized for a desktop modal — "HILL TRADING CO. — GUNSMITH"
   wrapped to two lines of 26px pixel type and pushed the shop off the screen. */
body.mobile .panel .title,
body.mobile .title {
  font-size: 13px;
  letter-spacing: 1px;
  line-height: 1.25;
  margin-bottom: 6px;
  word-break: break-word;
}
/* The -14px top margin on .prop-address is tuned to pull the address up under
   a 26px desktop title. The mobile title is 13px, so the same -14px dragged the
   address on TOP of it — the commissary read "COMMISSARY" and "CASH ONLY"
   printed over each other. */
body.mobile .prop-address { font-size: 8px; margin: -2px 0 6px; }

/* Panels have to FIT, and their buttons have to be reachable. The gunsmith
   list ran off the bottom of the screen with no way to reach Close. */
body.mobile .panel,
body.mobile .panel-wide {
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
  padding: 12px;
}
body.mobile .shop-list { max-height: none; }
body.mobile .menu-buttons {
  position: sticky;
  bottom: 0;
  background: var(--panel-bg, #0d0d12);
  padding-top: 8px;
  margin-top: 4px;
}

body.mobile .shop-row { padding: 6px 8px; gap: 6px; }
body.mobile .shop-name { font-size: 11px; }
body.mobile .shop-stat { font-size: 8px; }
body.mobile .shop-price { font-size: 10px; min-width: 58px; }
body.mobile .shop-row .btn { padding: 5px 10px; font-size: 10px; }

body.mobile .pl { font-size: 10px; }
body.mobile .pl-k, body.mobile .pl-v { font-size: 10px; }
body.mobile .btn { font-size: 11px; padding: 8px 10px; }
body.mobile .btn-build { font-size: 10px; padding: 7px 8px; }

/* The interact prompt ran off both edges — "Buy BRENNAN BREAD CO. — $450,00"
   with the rest of the number somewhere past the bezel. */
body.mobile .interact-prompt {
  bottom: 8px;
  max-width: 88vw;
  font-size: 8px;
  padding: 6px 10px;
  letter-spacing: 0.5px;
  white-space: normal;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* The phone's own tabs (PHONE / MAPS / RIDE / FREIGHT / BANK) overflowed the
   screen width, so the last ones were unreachable. */
body.mobile .phone-tabs,
body.mobile .tabs {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  flex-wrap: nowrap;
}
body.mobile .phone-tabs button,
body.mobile .tabs button { font-size: 10px; padding: 6px 8px; white-space: nowrap; }
/* The scroll strip has to STOP before the close button, or the last tab slides
   under the × and cannot be tapped — which is what a sixth tab (STOCKS) did.
   `min-width: 0` is the part that matters: without it a flex item refuses to
   shrink below its content and the strip pushes × off the edge instead. */
body.mobile .phone-tabs { min-width: 0; flex: 1 1 auto; }
body.mobile .phone-x { flex: 0 0 auto; margin-left: 6px; }

/* The phone's footer is a keyboard legend — G, Shift+G, M, P. None of those
   keys exist on a phone, and it was eating a row of a small screen to say so.
   Same class of mistake as the WASD tutorial. */
body.mobile .phone-foot { display: none; }

/* The MAPS tab was a row: a 600x450 canvas with `flex: 1` beside a 260px side
   panel. On a phone the canvas kept its intrinsic 600px width, blew through
   the panel, and the player saw a hugely magnified corner of the map instead
   of the map. Stack it, and let the canvas take the width it is given while
   keeping its 4:3 backing-store ratio — stretching it would misplace every
   pin, which is the same mistake as stretching the world. */
body.mobile .phone-body {
  flex-direction: column;
  padding: 8px;
  gap: 8px;
  min-width: 0;
}
body.mobile .phone-map {
  flex: 0 0 auto;
  width: 100%;
  min-width: 0;
  height: auto;
  aspect-ratio: 600 / 450;
}
body.mobile .phone-side { width: 100%; min-width: 0; }
/* ...and the panel itself must not be wider than the screen. */
body.mobile .phone-panel, body.mobile #phonePanel .panel { max-width: 96vw; }

/* ---- Live progress: wages accruing, study advancing ----
   Both used to tick in total silence. You stood in a library or behind a bar
   with no sign anything was happening, and the only way to find out was to
   open the phone. */
.prog-sub {
  font-size: 8px;
  letter-spacing: 0.06em;
  color: var(--dim, #8b8b93);
  margin-top: 2px;
}
.prog-bar {
  width: 100%;
  height: 4px;
  margin-top: 3px;
  background: rgba(255, 255, 255, 0.10);
  border-radius: 2px;
  overflow: hidden;
}
.prog-fill {
  height: 100%;
  width: 0;
  background: var(--neon, #9fe870);
  /* Eased so it glides between frames rather than stepping. */
  transition: width 0.25s linear;
}

/* Not at the library — the bar is frozen and should look it. */
#studyBlock.stalled .prog-fill { background: #6b6b73; }
#studyBlock.stalled .prog-sub { color: #ffb454; }

/* One beat per dollar banked, so a shift has a pulse instead of a silently
   incrementing number. */
@keyframes wage-tick {
  0%   { box-shadow: 0 0 0 0 rgba(159, 232, 112, 0.55); }
  100% { box-shadow: 0 0 0 7px rgba(159, 232, 112, 0); }
}
.wage-stat.tick { animation: wage-tick 0.45s ease-out; }

/* Both blocks matter on a phone — they are the whole reason to stand still. */
body.mobile #wageBlock, body.mobile #studyBlock { display: none; }
body.mobile #wageBlock:not(.hidden), body.mobile #studyBlock:not(.hidden) {
  display: block;
}
body.mobile .prog-sub { font-size: 7px; }
body.mobile .prog-bar { height: 3px; }

/* ============================================================
   THE WHEEL — what actually happened to you
   ============================================================
   Drawn rather than generated: a conic-gradient of weighted segments is
   crisp at any size, animates on the compositor, and needs no asset. The
   segment ANGLES come from the same weights the sim rolls against, so what
   the wheel shows is the odds it is showing. */
.wheel-wrap {
  position: relative;
  width: 220px;
  height: 220px;
  margin: 6px auto 10px;
}
.wheel {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 4px solid var(--neon);
  box-shadow: 0 0 18px rgba(182, 255, 59, 0.25), inset 0 0 24px rgba(0, 0, 0, 0.6);
  /* 4s, heavily eased out: the whole point of a wheel is the slowing down. */
  transition: transform 4s cubic-bezier(0.12, 0.72, 0.06, 1);
  transform: rotate(0deg);
}
.wheel-needle {
  position: absolute;
  top: -10px; left: 50%;
  width: 0; height: 0;
  margin-left: -9px;
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 18px solid var(--neon);
  z-index: 2;
  filter: drop-shadow(0 2px 0 #000);
}
.fate-result {
  font-family: var(--pixel-font);
  font-size: 15px;
  letter-spacing: 1px;
  min-height: 22px;
  margin-bottom: 8px;
}
/* A 220px wheel is most of a phone's width. Give it the room it needs and
   nothing more. */
body.mobile .wheel-wrap { width: 60vw; height: 60vw; max-width: 220px; max-height: 220px; }
body.mobile .fate-result { font-size: 11px; }

/* Coloured wedges do not say what they mean. The legend is built from the same
   weights the wheel is drawn from, so it cannot drift out of step with it. */
.fate-legend {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 4px 10px; margin-bottom: 8px;
}
.fate-legend span {
  font-family: var(--pixel-font);
  font-size: 8px; letter-spacing: 0.5px;
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--ink-dim);
}
.fate-legend i {
  width: 8px; height: 8px; display: inline-block; border-radius: 2px;
}
body.mobile .fate-legend span { font-size: 7px; }

/* ============================ THE LINE ============================
   The front. Two colours and nothing else: everything on that map is mud,
   rust and grey, so the faction flash is the only thing carrying meaning and
   it has to survive being glanced at during a firefight. */
:root { --mill: #ff8c2a; --quarry: #5aaeff; }

.deploy-faction {
  font-family: var(--pixel-font);
  font-size: 9px; letter-spacing: 1px; margin-bottom: 3px;
}
.deploy-faction.is-mill   { color: var(--mill); }
.deploy-faction.is-quarry { color: var(--quarry); }

/* The scoreboard sits top-centre, under the stat row: it is glanced at, not
   read, so it goes where the eye already passes on its way back to the
   middle of the screen. */
/* This stylesheet has no global `.hidden` rule — every component declares its
   own, and a new one that forgets is a panel that can never be turned off.
   Both of these shipped without it for exactly one run, and the warzone
   scoreboard and the DOWN overlay sat on top of GRANDVIEW. */
.wz-board.hidden { display: none; }
.war-down.hidden { display: none; }

.wz-board {
  position: absolute; top: 96px; left: 50%; transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.78);
  border: 2px solid var(--bg-2);
  padding: 6px 10px; pointer-events: none;
  min-width: 260px;
}
.wz-tickets {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 5px;
}
.wz-ticket {
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--pixel-font); font-size: 8px; letter-spacing: 0.5px;
}
.wz-ticket b { font-size: 12px; }
.wz-mill,   .wz-mill b   { color: var(--mill); }
.wz-quarry, .wz-quarry b { color: var(--quarry); }
.wz-vs { color: var(--ink-dim); font-family: var(--pixel-font); font-size: 8px; }

.wz-points { display: flex; gap: 6px; }
.wz-point { flex: 1; }
.wz-pt-bar {
  height: 5px; background: var(--bg-2); position: relative; overflow: hidden;
}
/* Progress runs from the centre outward, so which way it is LEANING is
   readable without reading the number. */
.wz-pt-fill {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 0;
  background: var(--ink-dim); transition: width 0.2s linear, left 0.2s linear;
}
.wz-pt-fill.is-mill   { background: var(--mill); }
.wz-pt-fill.is-quarry { background: var(--quarry); }
.wz-point.is-contested .wz-pt-bar { animation: wz-pulse 0.8s ease-in-out infinite; }
@keyframes wz-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
.wz-pt-name {
  font-family: var(--pixel-font); font-size: 6px; letter-spacing: 0.5px;
  color: var(--ink-dim); margin-top: 3px; text-align: center;
}
.wz-point.is-mill   .wz-pt-name { color: var(--mill); }
.wz-point.is-quarry .wz-pt-name { color: var(--quarry); }
.wz-strength {
  font-family: var(--pixel-font); font-size: 6px; letter-spacing: 0.5px;
  color: var(--ink-dim); margin-top: 4px; text-align: center;
}

/* Going down. Deliberately not the fate wheel — a casualty is not a fate, and
   spinning for one would say the opposite of what the mode means. */
.war-down {
  position: absolute; inset: 0; display: flex;
  flex-direction: column; align-items: center; justify-content: center;
  background: rgba(20, 4, 4, 0.72); pointer-events: none; z-index: 40;
}
.wd-title {
  font-family: var(--pixel-font); font-size: 28px; letter-spacing: 4px;
  color: var(--danger); margin-bottom: 10px;
}
.wd-count {
  font-family: var(--pixel-font); font-size: 16px; color: var(--ink);
  margin-bottom: 12px;
}
.wd-note {
  font-family: var(--pixel-font); font-size: 8px; letter-spacing: 0.5px;
  color: var(--ink-dim); max-width: 320px; text-align: center; line-height: 1.8;
}

/* The recruiting office. */
.wz-terms {
  font-family: var(--pixel-font); font-size: 7px; letter-spacing: 0.5px;
  color: var(--ink-dim); line-height: 2.1; margin: 10px 0 12px;
}
.wz-sides { display: flex; gap: 8px; margin-bottom: 12px; }
.wz-side {
  flex: 1; background: var(--bg-1); border: 2px solid var(--bg-2);
  padding: 10px 8px; cursor: pointer; text-align: center;
}
.wz-side:hover { border-color: var(--ink-dim); }
.wz-side.is-mill   { border-left: 4px solid var(--mill); }
.wz-side.is-quarry { border-left: 4px solid var(--quarry); }
.wz-side-name {
  font-family: var(--pixel-font); font-size: 9px; letter-spacing: 1px;
  margin-bottom: 6px;
}
.wz-side.is-mill   .wz-side-name { color: var(--mill); }
.wz-side.is-quarry .wz-side-name { color: var(--quarry); }
.wz-side-count {
  font-family: var(--pixel-font); font-size: 7px; color: var(--ink-dim);
  line-height: 1.9;
}
/* Says which side the server would put you on if you did not choose. Shown
   because "auto-balanced" is otherwise invisible and reads as the game
   ignoring your click. */
.wz-side-hint {
  font-family: var(--pixel-font); font-size: 6px; color: var(--neon);
  margin-top: 5px; min-height: 8px;
}

body.mobile .wz-board { top: 78px; min-width: 200px; padding: 4px 7px; }
body.mobile .wz-ticket b { font-size: 10px; }
body.mobile .wd-title { font-size: 20px; }
