/* web/style.css -- dark, monospace, surveillance-console. No art assets anywhere. */

:root {
  --bg: #0b0906;
  --bg-2: #15110d;
  --bg-3: #1e1813;
  --line: #2e2620;
  --fg: #efe6da;
  --fg-dim: #a59684;
  --fg-faint: #776a5c;
  --accent: #19e0c8;
  --warn: #ffc93b;
  --danger: #ff4d5e;
  --water: #4fb6da;
  --bolt: #ffe66d;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --radius: 4px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font: 13px/1.5 var(--mono);
  -webkit-text-size-adjust: 100%;
}

.launch-body { min-height: 100vh; }

/* The play page never scrolls. The arrow keys belong to the game, and on a scrollable
   page the browser takes them the moment the panels overflow -- which no amount of
   preventDefault reliably fixes once focus lands on a select or a button. */
.play-body {
  /* dvh first: on a phone `vh` includes the collapsible address bar, so a 100vh layout is
     taller than what is actually on screen and the board slides off the bottom. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}

.play-body #game {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* The board must never be draggable or zoomable: every gesture belongs to the game. */
.play-body canvas {
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.play-body .stage { flex: 1 1 auto; min-height: 0; }
.play-body .panels { max-height: 100%; overflow-y: auto; }

.screen { display: block; }
.screen[hidden] { display: none; }

b { font-weight: 600; }
.muted { color: var(--fg-faint); font-weight: 400; }

/* ------------------------------- launch ------------------------------- */

#launch {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 16px;
}

.launch-inner { width: 100%; max-width: 620px; }

.logo {
  font-size: 54px;
  letter-spacing: 0.34em;
  margin: 0 0 6px;
  font-weight: 700;
  color: var(--fg);
  text-shadow: 0 0 28px rgba(25, 224, 200, 0.22);
}

.logo.small {
  font-size: 13px;
  letter-spacing: 0.3em;
  margin: 0;
  text-shadow: none;
  color: var(--fg-dim);
}

.tagline { color: var(--fg-dim); margin: 0 0 28px; max-width: 48ch; }

.slots { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }

@media (max-width: 560px) { .slots { grid-template-columns: 1fr; } }

.slot {
  appearance: none;
  display: block;
  text-decoration: none;
  text-align: left;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--fg);
  padding: 16px;
  cursor: pointer;
  font: inherit;
  transition: border-color 120ms, background 120ms, transform 120ms;
}

.slot:hover, .slot:focus-visible {
  border-color: var(--accent);
  background: var(--bg-3);
  outline: none;
  transform: translateY(-1px);
}

.slot h2 { margin: 0 0 10px; font-size: 18px; letter-spacing: 0.16em; }
.slot .slot-meta { color: var(--fg-dim); display: grid; gap: 3px; }
.slot .slot-meta span { display: flex; justify-content: space-between; gap: 12px; }
.slot .slot-meta b { color: var(--fg); }
.slot .slot-hint { margin: 12px 0 0; color: var(--fg-faint); font-size: 12px; }

.storage-note { color: var(--warn); min-height: 1.5em; margin: 14px 0 0; font-size: 12px; }

.brief {
  margin-top: 26px;
  border-top: 1px solid var(--line);
  padding-top: 14px;
}

.brief summary {
  cursor: pointer;
  color: var(--fg-dim);
  letter-spacing: 0.1em;
}

.brief summary:hover { color: var(--fg); }
.brief-body { color: var(--fg-dim); margin-top: 12px; }
.brief-body p { margin: 0 0 10px; }

.k { padding: 0 4px; border-radius: 2px; color: var(--bg); font-weight: 600; }
.k.key { background: var(--warn); }
.k.portal { background: var(--accent); }
.k.alien { background: var(--danger); }
.k.bolt { background: var(--bolt); }
.k.rubble { background: #6f6454; color: #efe6da; }
.k.water { background: var(--water); }

/* -------------------------------- game -------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
  flex-wrap: wrap;
}

.spacer { flex: 1 1 auto; }

.chip { color: var(--fg-dim); }
.chip b { color: var(--fg); }

/* ---- the keys tab: the one readout a player needs at a glance ---- */
.keytab {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 5px 12px 5px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-3);
  transition: border-color 160ms, background 160ms;
}

.keytab-icon {
  width: 13px; height: 13px;
  flex: none;
  border-radius: 50% 50% 40% 40%;
  background: var(--warn);
  box-shadow: 0 0 9px rgba(255, 201, 59, 0.55);
  position: relative;
}
.keytab-icon::after {
  content: "";
  position: absolute;
  left: 5px; top: 10px;
  width: 3px; height: 8px;
  background: var(--warn);
}

.keytab-text b { font-size: 14px; }
.keytab-text i { font-style: normal; color: var(--fg-dim); }

.keytab[data-state="open"] {
  border-color: var(--accent);
  background: rgba(25, 224, 200, 0.10);
}
.keytab[data-state="open"] .keytab-icon {
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 12px rgba(25, 224, 200, 0.7);
}
.keytab[data-state="open"] .keytab-icon::after { display: none; }
.keytab[data-state="open"] .keytab-text i { color: var(--accent); }

#hud-profile[data-degraded="yes"]::after {
  content: " (not saved)";
  color: var(--warn);
  font-weight: 400;
}

.field { display: flex; align-items: center; gap: 6px; color: var(--fg-dim); }

select, .btn {
  font: inherit;
  background: var(--bg-3);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 9px;
  cursor: pointer;
}

select:hover, .btn:hover { border-color: var(--accent); }
.btn.ghost { background: transparent; color: var(--fg-dim); }
.btn.ghost:hover { color: var(--fg); }
.btn.danger:hover { border-color: var(--danger); color: var(--danger); }

.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px;
  padding: 16px;
  align-items: start;
}

@media (max-width: 1040px) {
  .stage { grid-template-columns: minmax(0, 1fr); }
}

/* ---- phones and small tablets ---- */
@media (max-width: 820px) {
  .topbar {
    gap: 8px;
    padding: 7px 10px;
    padding-top: max(7px, env(safe-area-inset-top));
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .topbar::-webkit-scrollbar { display: none; }
  .topbar > * { flex: none; }

  .keytab { padding: 4px 9px 4px 7px; }
  .keytab-text i { display: none; }     /* the count is the part that matters */

  .stage { padding: 8px; gap: 8px; }
  .statusbar { gap: 11px; padding: 6px 9px; font-size: 11px; }
  .stat b { font-size: 12px; }
  .stat:nth-child(n + 5) { display: none; }   /* elapsed, status, boost, gun, lightning */

  /* The readouts become a sheet rather than a column: on a phone they are five panels
     of diagnostics competing with the board for the only scarce resource, height. */
  .panels {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    max-height: 72vh;
    max-height: 72dvh;
    overflow-y: auto;
    padding: 12px 12px max(16px, env(safe-area-inset-bottom));
    background: var(--bg-2);
    border-top: 1px solid var(--line);
    transform: translateY(101%);
    transition: transform 180ms ease;
  }

  body.panels-open .panels { transform: translateY(0); }
  body.panels-open .touch-layer { display: none; }

  .keyhint { display: none; }
}

@media (max-width: 820px) and (orientation: portrait) {
  /* The board is 1.6:1; in portrait it is a strip. The hint covers the screen. */
  .act { width: 72px; height: 72px; }
}

/* ---- the outcome overlay on a small screen ---- */
@media (max-width: 820px), (max-height: 600px) and (pointer: coarse) {
  .overlay { align-items: flex-start; padding: 10px; }
  .overlay-card { padding: 14px; margin: 0 auto; }
  .overlay-card h2 { font-size: 17px; margin-bottom: 4px; }
  .overlay-card > p { font-size: 12.5px; margin-bottom: 10px; }

  /*
   * The buttons come BEFORE the breakdown on a phone.
   *
   * Fifteen rows of score itemisation is desktop content; on a phone it pushes the only
   * two controls that matter off the bottom of the screen. Reordering costs nothing and
   * means "enter district N" is the first thing under the headline, every time.
   */
  .overlay-actions { order: 3; margin-bottom: 12px; }
  .overlay-stats { order: 4; }

  .overlay-actions .btn { flex: 1; padding: 10px 8px; font-size: 13px; }
  .overlay-stats { grid-template-columns: 1fr; gap: 2px; font-size: 11.5px; text-align: left; }
  .overlay-stats span { gap: 10px; align-items: baseline; }
  /* nowrap is right on a wide screen and wrong here: these values are phrases like
     "par 7s, took 7.4s", and forbidding them to wrap pushes them out of the card. */
  .overlay-stats span b { white-space: normal; text-align: right; }

  /* The thumb controls must not sit on top of the card. */
  body.overlay-open .touch-layer { display: none; }
}

/* ---- landscape phone: height is the only scarce resource ---- */
@media (pointer: coarse) and (max-height: 700px) {
  /* Every row of chrome costs 32 tiles of board width. The top bar already carries the
     district, the tier, the keys and the wallet, so the status strip below the board is
     duplicating what is on screen and charging height for it. The rest of the readouts
     live in the sheet behind `readouts`. */
  .statusbar { display: none; }

  .topbar {
    padding: 4px 8px;
    padding-top: max(4px, env(safe-area-inset-top));
    gap: 7px;
    font-size: 11.5px;
  }

  .topbar .logo.small { display: none; }
  .keytab { padding: 2px 8px 2px 6px; }
  .keytab-text b { font-size: 12.5px; }
  .wallet { padding: 2px 8px; }

  .stage { padding: 4px 6px; }
  .act { width: 64px; height: 64px; }
  .act-glyph { font-size: 19px; }
  .stick { width: 96px; height: 96px; margin: -48px 0 0 -48px; }
  .knob { width: 40px; height: 40px; }
}

.board { min-width: 0; }

.canvas-wrap {
  position: relative;
  display: inline-block;
  line-height: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  max-width: 100%;
}

canvas { display: block; image-rendering: pixelated; }

.statusbar {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 10px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
}

.stat { display: flex; flex-direction: column; gap: 1px; }
.stat i { font-style: normal; color: var(--fg-faint); font-size: 11px; letter-spacing: 0.08em; }
.stat b { font-size: 14px; }

#hud-alert[data-state="alert"] { color: var(--danger); }
#hud-alert[data-state="hidden"] { color: var(--water); }
#hud-alert[data-state="calm"] { color: var(--fg-faint); }
#hud-boost[data-state="on"] { color: var(--bolt); }
#hud-boost[data-state="off"] { color: var(--fg-faint); }

/* ------------------------------- panels ------------------------------- */

.panels { display: grid; gap: 12px; }

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 12px;
}

.panel h3 {
  margin: 0 0 10px;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-faint);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.status {
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--fg-faint);
  font-weight: 400;
  text-align: right;
}

.status[data-state="ready"] { color: var(--accent); }
.status[data-state="loading"] { color: var(--warn); }
.status[data-state="template"] { color: var(--fg-dim); }

.dispatch { margin: 0; color: var(--fg); min-height: 4.5em; }
.dispatch[data-source="model"]::before { content: "▸ "; color: var(--accent); }
.dispatch[data-source="template"]::before { content: "▸ "; color: var(--fg-faint); }

/* prediction bars */
.bars { display: grid; gap: 3px; }

.bar-row { display: grid; grid-template-columns: 2em 1fr 2.8em; gap: 7px; align-items: center; }
.bar-label { color: var(--fg-faint); font-size: 11px; }
.bar-track { background: var(--bg-3); height: 9px; border-radius: 2px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--fg-faint); transition: width 110ms linear; }
.bar-val { color: var(--fg-faint); font-size: 11px; text-align: right; }

.bar-row[data-top="yes"] .bar-fill { background: var(--danger); }
.bar-row[data-top="yes"] .bar-val { color: var(--danger); }
.bar-row[data-here="yes"] .bar-label { color: var(--water); }
.bar-row[data-here="yes"] .bar-label::after { content: "◂"; margin-left: 2px; }

.drivers, .spawns, .traits { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 4px; }
.drivers li, .spawns li { color: var(--fg-dim); font-size: 12px; }
.drivers b, .spawns b { color: var(--fg); }

/* dossier gauges */
.trait-row { display: grid; grid-template-columns: 1fr 72px 3.2em; gap: 8px; align-items: center; font-size: 12px; }
.trait-name { color: var(--fg-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trait-gauge { position: relative; height: 8px; background: var(--bg-3); border-radius: 2px; }
.trait-gauge::before {
  content: ""; position: absolute; left: 50%; top: -1px; bottom: -1px;
  width: 1px; background: var(--line);
}
.trait-gauge i { position: absolute; top: 0; bottom: 0; border-radius: 2px; }
.trait-gauge i[data-sign="pos"] { background: var(--warn); }
.trait-gauge i[data-sign="neg"] { background: var(--water); }
.trait-z { text-align: right; color: var(--fg-faint); }

.keyhint { margin: 0; font-size: 11.5px; line-height: 1.7; }
.keyhint b { color: var(--fg-dim); }

.panel.compact .kv { display: flex; justify-content: space-between; color: var(--fg-dim); gap: 10px; }
.panel.compact .kv b { text-align: right; }
.panel.compact .kv b { color: var(--fg); }
.panel-actions { margin-top: 10px; }

/* ------------------------------ overlay ------------------------------ */

/*
 * FIXED to the viewport, not absolute inside .canvas-wrap.
 *
 * It used to be absolutely positioned inside the canvas wrapper, which has
 * `overflow: hidden` to keep the board's rounded corners. On a landscape phone the card
 * -- title, body, fifteen rows of score breakdown and two buttons -- is far taller than
 * the board, so it was centred, overflowed, and then CLIPPED. The title was cut off at
 * the top and "enter district N" was rendered outside the visible box entirely, which is
 * why the next district was unreachable.
 *
 * Fixed positioning takes it out of that clip, and `overflow-y: auto` means a card taller
 * than the screen scrolls instead of being silently truncated.
 */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(7, 9, 12, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow-y: auto;
  overscroll-behavior: contain;
  line-height: 1.5;
  padding: 16px;
  padding-top: max(16px, env(safe-area-inset-top));
  padding-bottom: max(16px, env(safe-area-inset-bottom));
}

.overlay[hidden] { display: none; }

.overlay-card {
  display: flex;
  flex-direction: column;
  text-align: center;
  max-width: 420px;
  width: 100%;
  margin: auto;
  border: 1px solid var(--line);
  background: var(--bg-2);
  border-radius: var(--radius);
  padding: 22px;
}

/* Explicit order so the phone rule below only has to move one thing. */
.overlay-card h2 { order: 1; }
.overlay-card > p { order: 2; }
.overlay-stats { order: 3; }
.overlay-actions { order: 4; }

.overlay-card h2 { margin: 0 0 8px; letter-spacing: 0.16em; font-size: 20px; }
.overlay-card p { margin: 0 0 14px; color: var(--fg-dim); }

.overlay-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 16px;
  margin-bottom: 16px;
  font-size: 12px;
}

.overlay-stats span { display: flex; justify-content: space-between; color: var(--fg-dim); }
.overlay-stats b { color: var(--fg); }

.overlay-actions { display: flex; gap: 8px; justify-content: center; }

.won h2 { color: var(--accent); }
.lost h2 { color: var(--danger); }

/* ======================= thumb controls (touch only) ====================== */

.desktop-only { display: initial; }
.touch-only { display: none; }

body.touch .desktop-only { display: none; }
body.touch .touch-only { display: inline-flex; }

.touch-layer {
  position: fixed;
  inset: 0;
  z-index: 40;
  /* The overlay itself must never eat taps meant for the board; only the controls do. */
  pointer-events: none;
  padding: 0 max(10px, env(safe-area-inset-left)) max(10px, env(safe-area-inset-bottom))
           max(10px, env(safe-area-inset-right));
}

.touch-layer[hidden] { display: none; }

/* Left half is the move zone: the stick appears wherever the thumb lands. */
.stick-zone {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 48%;
  height: 62%;
  pointer-events: auto;
  touch-action: none;
}

.stick {
  position: absolute;
  width: 112px;
  height: 112px;
  margin: -56px 0 0 -56px;
  border-radius: 50%;
  border: 1.5px solid rgba(239, 230, 218, 0.22);
  background: rgba(10, 9, 7, 0.28);
  opacity: 0;
  transition: opacity 120ms;
}

.stick.live { opacity: 1; }

.knob {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 46px;
  margin: 0;
  border-radius: 50%;
  background: rgba(239, 230, 218, 0.30);
  border: 1.5px solid rgba(239, 230, 218, 0.5);
  transform: translate(-50%, -50%);
}

.stick-hint {
  position: absolute;
  left: 14px;
  bottom: 12px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  color: var(--fg-faint);
  opacity: 0.5;
  pointer-events: none;
}

.stick-zone:active .stick-hint { opacity: 0; }

/* Right: two translucent action buttons, stacked so both sit under one thumb. */
.act-stack {
  position: absolute;
  right: max(14px, env(safe-area-inset-right));
  bottom: max(18px, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column-reverse;
  gap: 14px;
  pointer-events: auto;
}

.act {
  position: relative;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  border: 1.5px solid rgba(239, 230, 218, 0.26);
  background: rgba(10, 9, 7, 0.34);
  color: var(--fg);
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  touch-action: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform 90ms, background 120ms, border-color 120ms;
}

.act-glyph { font-size: 22px; line-height: 1; }
.act-label { font-size: 9.5px; letter-spacing: 0.14em; color: var(--fg-dim); }

.act.pressed { transform: scale(0.92); }

.act-run { border-color: rgba(255, 230, 109, 0.4); }
.act-run .act-glyph { color: var(--bolt); }
.act-run.active {
  background: rgba(255, 230, 109, 0.18);
  border-color: var(--bolt);
  box-shadow: 0 0 18px rgba(255, 230, 109, 0.3);
}

.act-stun { border-color: rgba(79, 182, 218, 0.4); }
.act-stun .act-glyph { color: var(--water); }
.act-stun.empty { opacity: 0.4; }

.act-count {
  position: absolute;
  top: 6px;
  right: 9px;
  font-size: 11px;
  font-weight: 700;
  color: var(--water);
}

.act-stun.empty .act-count { color: var(--fg-faint); }

/* Portrait on a phone gives a postage stamp; 32x20 wants landscape. */
.rotate-hint {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 32px;
  text-align: center;
  background: rgba(7, 6, 5, 0.93);
  color: var(--fg);
}

.rotate-hint[hidden] { display: none; }
.rotate-hint b { font-size: 17px; letter-spacing: 0.1em; }
.rotate-hint p { color: var(--fg-dim); max-width: 34ch; margin: 10px auto 0; }

/* ===================================================================== */
/* the hub: district grid and shop                                       */
/* ===================================================================== */

.hub-body { min-height: 100vh; }

.hubbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 5;
}

.hub { max-width: 1080px; margin: 0 auto; padding: 24px 16px 72px; }
.hub-note { color: var(--fg-dim); max-width: 74ch; margin: 0 0 20px; }

.tabs { display: flex; gap: 4px; }

.tab {
  font: inherit;
  background: transparent;
  color: var(--fg-dim);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 5px 12px;
  cursor: pointer;
  letter-spacing: 0.08em;
}

.tab:hover { color: var(--fg); }
.tab.active { color: var(--bg); background: var(--fg-dim); border-color: var(--fg-dim); }

/* ---- wallet ---- */

.wallet {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-3);
  color: var(--fg-dim);
}

.wallet b { color: var(--warn); font-size: 14px; }

.coin-pip {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--warn);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.35);
  flex: none;
}

.coin-run { font-style: normal; color: #7fc96b; }

/* ---- district grid ---- */

.block-head {
  grid-column: 1 / -1;
  margin: 22px 0 2px;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 600;
}

.block-head:first-child { margin-top: 0; }

.district-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 10px;
}

.district {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 94px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(160deg, var(--d-tint, var(--bg-3)), var(--bg-2));
  color: var(--fg);
  text-decoration: none;
  transition: transform 120ms, border-color 120ms, box-shadow 120ms;
}

a.district:hover, a.district:focus-visible {
  border-color: var(--d-accent);
  box-shadow: 0 0 0 1px var(--d-accent), 0 6px 20px var(--d-glow);
  transform: translateY(-2px);
  outline: none;
}

.district .d-num {
  font-size: 26px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--d-accent);
}

.district .d-state { color: var(--fg-dim); font-size: 11.5px; }
.district .d-best { color: var(--fg-faint); font-size: 11.5px; margin-top: auto; }

.district .d-flag {
  position: absolute;
  top: 9px; right: 9px;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bg);
  background: var(--d-accent);
  padding: 1px 5px;
  border-radius: 2px;
}

.district.locked {
  opacity: 0.4;
  background: var(--bg-2);
  cursor: not-allowed;
}

.district.locked .d-num { color: var(--fg-faint); }

/* ---- shop ---- */

.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 12px;
}

.shop-item {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.shop-item h4 {
  margin: 0;
  font-size: 14px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}

.shop-item .price { color: var(--warn); font-size: 12px; font-weight: 600; }
.shop-item p { margin: 0; font-size: 12px; }
.shop-item .owned { color: var(--accent); font-size: 12px; }
.buy-row { display: flex; gap: 6px; margin-top: auto; }
.buy-row .btn:disabled { opacity: 0.35; cursor: not-allowed; border-color: var(--line); }

/* ===================================================================== */
/* the one-time difficulty chooser                                        */
/* ===================================================================== */

.chooser {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 20px;
}

.chooser h2 { margin: 0 0 6px; font-size: 18px; letter-spacing: 0.12em; }
.chooser p { margin: 0 0 16px; }

.tiers { display: grid; gap: 8px; }

.tier {
  appearance: none;
  display: grid;
  gap: 3px;
  text-align: left;
  font: inherit;
  cursor: pointer;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-3);
  color: var(--fg);
  transition: border-color 120ms, transform 120ms;
}

.tier:hover, .tier:focus-visible {
  border-color: var(--warn);
  transform: translateY(-1px);
  outline: none;
}

.tier-name { font-size: 15px; font-weight: 700; letter-spacing: 0.16em; }
.tier-speed { color: var(--danger); font-size: 12px; }
.tier-blurb { color: var(--fg-dim); font-size: 12px; }
.tier-mult { color: var(--warn); font-size: 11.5px; }

.tier[data-tier="ultra"] .tier-name { color: var(--danger); }

.chooser-actions { margin-top: 14px; }

.slot-new {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bg);
  background: var(--warn);
  padding: 2px 6px;
  border-radius: 2px;
  vertical-align: middle;
}

/* ===================================================================== */
/* in-district additions                                                  */
/* ===================================================================== */

#hud-bullets[data-state="ready"] { color: var(--water); }
#hud-bullets[data-state="empty"] { color: var(--danger); }
#hud-bullets[data-state="none"] { color: var(--fg-faint); }
#hud-bolt[data-state="on"] { color: var(--bolt); }
#hud-bolt[data-state="off"] { color: var(--fg-dim); }
#hud-bolt[data-state="none"] { color: var(--fg-faint); }

.k.safe { background: #15131a; color: #cfd8e3; box-shadow: inset 0 0 0 1px #3a3542; }

.touchpad .row.acts { margin-top: 10px; }
.touchpad .row.acts button { width: 94px; font-size: 14px; letter-spacing: 0.1em; }

.overlay-stats span b { white-space: nowrap; }

/* ---- launch slots with actions ---- */

.slot.empty { opacity: 0.92; }
.slot-actions { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.slot-actions .btn { text-decoration: none; }
.slot-note {
  margin: 10px 0 0;
  font-size: 11.5px;
  color: var(--fg-faint);
  letter-spacing: 0.04em;
}
.btn.ghost.danger { color: var(--fg-faint); }
.btn.ghost.danger:hover { color: var(--danger); border-color: var(--danger); }

/* ---- the sound toggle ---- */

.sound-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  color: var(--fg-dim);
}

.sound-btn:hover { color: var(--fg); }
.sound-btn[data-on="true"] { color: var(--accent); border-color: var(--line); }

/* A speaker drawn in CSS: a square body with a triangular cone. */
.sound-icon {
  position: relative;
  width: 13px;
  height: 12px;
  flex: none;
}

.sound-icon::before {
  content: "";
  position: absolute;
  left: 0; top: 3.5px;
  width: 4px; height: 5px;
  background: currentColor;
}

.sound-icon::after {
  content: "";
  position: absolute;
  left: 3px; top: 0;
  border: 6px solid transparent;
  border-right-width: 7px;
  border-right-color: currentColor;
}

/* Off: struck through, so the state is not carried by colour alone. */
.sound-btn[data-on="false"] .sound-icon {
  opacity: 0.55;
}

.sound-btn[data-on="false"] .sound-icon::before,
.sound-btn[data-on="false"] .sound-icon::after {
  filter: grayscale(1);
}

.sound-btn[data-on="false"]::after {
  content: "";
  position: absolute;
  margin-left: -42px;
  width: 17px;
  height: 1.5px;
  background: var(--danger);
  transform: rotate(-30deg);
  pointer-events: none;
}

.sound-btn { position: relative; }
