/* =====================================================================
   Tower Day — tabletop tactics
   The board is a physical object sitting on a dark table. Everything
   around it stays quiet so the board is the only loud thing on screen.
   ===================================================================== */

:root {
  /* Palette — six values, all of them doing a job */
  --table:      #172a2e;  /* the surface the board rests on */
  --felt:       #2f4f43;  /* buildable ground */
  --felt-lit:   #3c6353;  /* hover / cursor */
  --sand:       #c9a66b;  /* the lane enemies walk */
  --bone:       #edeae3;  /* pieces, primary text */
  --signal:     #f2c14e;  /* targeting, active state, gold */
  --threat:     #d64550;  /* enemies, leaks */

  --table-lift: #1e373c;  /* panels raised off the table */
  --edge:       #2c4950;
  --muted:      #9db1ae;

  /* Spacing scale */
  --s-1: 0.25rem; --s-2: 0.5rem;  --s-3: 0.75rem; --s-4: 1rem;
  --s-6: 1.5rem;  --s-8: 2rem;    --s-12: 3rem;

  --radius: 0.5rem;
  --radius-sm: 0.375rem;

  --font-display: "Bricolage Grotesque", Georgia, serif;
  --font-ui: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

/* Stacking order, defined in one place.
 *
 * These were picked ad hoc as each panel was added, and the Incoming sheet
 * ended up BELOW the scrim that's meant to sit behind it — it opened and was
 * immediately greyed out. Named steps make the ordering checkable instead of
 * a set of magic numbers scattered across a stylesheet. */
:root {
  --z-palette: 30;   /* fixed palette strip */
  --z-dock: 31;      /* fixed bottom dock */
  --z-scrim: 50;     /* dimmer behind any sheet */
  --z-sheet: 60;     /* menu drawer and Incoming sheet, both ABOVE the scrim */
}

/* Global, and deliberately !important.
 *
 * The user-agent rule is only `[hidden] { display: none }`, so ANY author rule
 * with an explicit display outranks it — regardless of specificity. This bit
 * three separate times here (#live-controls, .board, .streak-wrap), each time
 * as "the JavaScript set .hidden and nothing happened". Fixing the class of
 * bug once beats discovering it a fourth time. */
[hidden] { display: none !important; }

body {
  margin: 0;
  padding: var(--s-4) var(--s-4) var(--s-12);
  min-height: 100vh;
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--bone);
  background-color: var(--table);
}

/* ===== Accessibility helpers ===== */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -4rem;
  padding: var(--s-2) var(--s-4);
  color: var(--table);
  background-color: var(--signal);
  border-radius: var(--radius-sm);
  transition: top 0.2s ease;
}
.skip-link:focus { top: var(--s-4); }

:focus-visible {
  outline: 3px solid var(--signal);
  outline-offset: 2px;
}

/* ===== Masthead ===== */

.masthead {
  max-width: 1400px;
  margin: 0 auto var(--s-6);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--edge);
}

.masthead-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
}

.nav { display: flex; gap: var(--s-2); }

.nav-btn {
  padding: var(--s-2) var(--s-4);
  font: inherit;
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--bone);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
  transition: all 0.2s ease;
}
.nav-btn:hover { border-color: var(--muted); }

.nav-btn-primary {
  color: var(--table);
  background-color: var(--signal);
  border-color: var(--signal);
}
.nav-btn-primary:hover { background-color: #ffd166; border-color: #ffd166; }



/* ===== Layout ===== */

.layout {
  display: grid;
  gap: var(--s-6);
  max-width: 1400px;
  margin: 0 auto;
}

/* Wave preview | board | controls. The preview goes FIRST in the source so
   it reads before the board on a phone — knowing what's coming is the thing
   you want before you start placing, not after. */
@media (min-width: 1100px) {
  .layout {
    grid-template-columns: 17rem minmax(0, 1fr) 19rem;
    align-items: start;
  }
}

/* ===== Wave preview ===== */

.waves-panel {
  padding: var(--s-4);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.wave-list {
  display: grid;
  gap: var(--s-2);
  margin: var(--s-3) 0 0;
  padding: 0;
  list-style: none;
  counter-reset: wave;
}

.wave-row {
  display: grid;
  grid-template-columns: 2rem 1fr;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

.wave-icon { width: 2rem; height: 2rem; display: block; }

.wave-name { font-size: 0.8125rem; font-weight: 600; }
.wave-trait { display: block; font-size: 0.6875rem; color: var(--muted); }
.wave-count {
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--signal);
}

/* Two waves of the same enemy back to back read as one longer wave. */
.wave-row.is-overlap { border-left: 2px solid var(--signal); }

/* ===== Board ===== */

.board-frame {
  /* fit-content, or the frame stays full column width while the canvas
     inside it is sized by the height cap — which leaves a visible slab of
     empty panel beside the board. */
  width: fit-content;
  margin-inline: auto;
  padding: var(--s-2);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.board {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  cursor: pointer;
  touch-action: manipulation; /* stops double-tap zoom eating placements */
}

.status {
  margin: var(--s-3) 0 0;
  min-height: 1.5rem;
  font-size: 0.9375rem;
  color: var(--muted);
}

/* ===== Controls ===== */

.controls { display: grid; gap: var(--s-4); }

/* Wrapping the resource row, palette and actions in a plain <div> dropped
   them out of .controls' grid, so its gap no longer applied and the last
   palette row sat flush against "Run the wave". */
#live-controls { display: grid; gap: var(--s-4); }

.resource-row {
  display: flex;
  gap: var(--s-6);
}

.resource { margin: 0; display: flex; align-items: baseline; gap: var(--s-2); }

.resource-value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--signal);
  font-variant-numeric: tabular-nums;
}

.resource-label { font-size: 0.8125rem; color: var(--muted); }

/* Tower palette */

.palette { display: grid; gap: var(--s-2); }

.piece {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  font: inherit;
  text-align: left;
  color: var(--bone);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
  transition: all 0.2s ease;
}

.piece:hover { border-color: var(--muted); }

.piece[aria-checked="true"] {
  border-color: var(--signal);
  background-color: #24424a;
}

.piece:disabled { opacity: 0.4; cursor: not-allowed; }

.piece-glyph {
  display: block;
  width: 2.5rem;
  height: 2.5rem;
  background-color: var(--felt);
  border-radius: 50%;
}

.piece-name { font-weight: 600; }
.piece-stat { display: block; font-size: 0.8125rem; font-weight: 400; color: var(--muted); }
.piece-count { font-variant-numeric: tabular-nums; color: var(--muted); }

/* Buttons */

.actions { display: grid; gap: var(--s-2); }

.btn {
  padding: var(--s-3) var(--s-4);
  font: inherit;
  font-weight: 600;
  color: var(--bone);
  background-color: transparent;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn:hover { border-color: var(--muted); }

.btn-primary {
  color: var(--table);
  background-color: var(--signal);
  border-color: var(--signal);
}
.btn-primary:hover { background-color: #ffd166; border-color: #ffd166; }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; background-color: var(--signal); }

.btn-quiet { color: var(--muted); border-color: transparent; }
.btn-quiet:hover { color: var(--bone); }

.speed { display: flex; gap: var(--s-2); }

.speed-btn {
  flex: 1;
  padding: var(--s-2);
  font: inherit;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  background-color: transparent;
  border: 1px solid var(--edge);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.2s ease;
}
.speed-btn.is-active { color: var(--table); background-color: var(--bone); border-color: var(--bone); }

/* Result */

.result {
  padding: var(--s-4);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.result-title {
  margin: 0 0 var(--s-3);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
}
.result-title[data-cleared="false"] { color: var(--threat); }
.result-title[data-cleared="true"] { color: var(--signal); }

.result-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr));
  gap: var(--s-3);
  margin: 0 0 var(--s-4);
}
.result-grid dt { font-size: 0.75rem; color: var(--muted); }
.result-grid dd {
  margin: var(--s-1) 0 0;
  font-size: 1.125rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.share {
  margin: 0 0 var(--s-3);
  padding: var(--s-3);
  font-family: var(--font-ui);
  font-size: 0.875rem;
  line-height: 1.4;
  white-space: pre-wrap;
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

/* ===== Footer ===== */

.footer {
  max-width: 1200px;
  margin: var(--s-8) auto 0;
  font-size: 0.8125rem;
  color: var(--muted);
  text-align: center;
}

/* Suggestions – Feedback – a JJO production.
 * Flex rather than inline text so the row wraps as whole items on a narrow
 * screen instead of splitting "JJO production" across two lines. */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: var(--s-1) var(--s-2);
  margin: var(--s-2) 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Two of the three are buttons (they open a form, they don't go anywhere)
 * styled to read exactly like the link beside them. */
.footer-link {
  padding: 0;
  font: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
}
.footer-links a { color: var(--muted); }
.footer-link,
.footer-links a {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.2em;
  transition: color 0.15s ease, text-decoration-color 0.15s ease;
}
.footer-link:hover,
.footer-link:focus-visible,
.footer-links a:hover,
.footer-links a:focus-visible {
  color: var(--bone);
  text-decoration-color: currentColor;
}
.footer-sep { opacity: 0.5; }

/* Desktop has the real footer; this copy exists for the phone drawer. */
.nav-footer { display: none; }

/* ===== Feedback form ===== */
.field-area {
  min-height: 7rem;
  line-height: 1.45;
  resize: vertical;
}
.field-optional { opacity: 0.7; }

/* Honeypot. Off-screen rather than display:none — some bots skip fields
 * they can tell are hidden that way. */
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.feedback-done { text-align: center; padding: var(--s-2) 0; }
.feedback-thanks {
  margin: 0 0 var(--s-4);
  font-family: var(--font-display);
  font-size: 1.125rem;
  color: var(--bone);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}


/* ===== Name panel ===== */

.name-panel,
.leaderboard {
  padding: var(--s-4);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.panel-title {
  margin: 0 0 var(--s-2);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
}

.panel-note {
  margin: 0 0 var(--s-3);
  font-size: 0.8125rem;
  color: var(--muted);
}

.field-label {
  display: block;
  margin-bottom: var(--s-1);
  font-size: 0.75rem;
  color: var(--muted);
}

.field {
  width: 100%;
  padding: var(--s-2) var(--s-3);
  margin-bottom: var(--s-2);
  font: inherit;
  color: var(--bone);
  background-color: var(--table);
  border: 1px solid var(--edge);
  border-radius: var(--radius-sm);
  transition: border-color 0.2s ease;
}

.field:focus { border-color: var(--signal); }

.field-error {
  margin: 0 0 var(--s-2);
  min-height: 1.25rem;
  font-size: 0.8125rem;
  color: var(--threat);
}

/* ===== Leaderboard dialog ===== */

.dialog {
  width: min(34rem, calc(100vw - 2rem));
  max-height: min(42rem, calc(100vh - 3rem));
  padding: var(--s-4);
  overflow-y: auto;
  color: var(--bone);
  background-color: var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.dialog::backdrop {
  background-color: rgba(10, 20, 22, 0.72);
}

.dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-2);
}

.dialog-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
}

.dialog-close {
  width: 2rem;
  height: 2rem;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--muted);
  background-color: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.2s ease;
}
.dialog-close:hover { color: var(--bone); border-color: var(--edge); }

.dialog-foot {
  margin: var(--s-4) 0 0;
  font-size: 0.75rem;
  color: var(--muted);
}

/* Table scrolls inside its own container so the dialog never scrolls
   sideways on a narrow screen. */
.lb-scroll {
  overflow-x: auto;
  margin: 0 calc(-1 * var(--s-1));
}

.lb-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
}

.lb-table th {
  padding: var(--s-2) var(--s-2);
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--muted);
  text-align: left;
  border-bottom: 1px solid var(--edge);
}

.lb-table td {
  padding: var(--s-2) var(--s-2);
  border-bottom: 1px solid rgba(44, 73, 80, 0.5);
}

.lb-num { text-align: right; font-variant-numeric: tabular-nums; }
.lb-table th.lb-num { text-align: right; }

.lb-table tr.is-you td {
  color: var(--signal);
  font-weight: 600;
  background-color: rgba(242, 193, 78, 0.07);
}

.lb-name-cell {
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.is-anon { color: var(--muted); font-style: italic; }

.lb-empty {
  padding: var(--s-4) var(--s-2);
  color: var(--muted);
  text-align: center;
}

.name-panel {
  margin-top: var(--s-4);
  padding: var(--s-4);
  background-color: var(--table);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

.credit { margin: var(--s-1) 0 0; font-size: 0.75rem; color: var(--muted); }
.credit a { color: var(--muted); }
.credit a:hover { color: var(--bone); }

.result-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}

/* One button left to show means it should take the full width. */
.result-actions.single { grid-template-columns: 1fr; }

.dialog-narrow { width: min(24rem, calc(100vw - 2rem)); }

/* Wider than the submit dialog so all five stats fit on one row. auto-fit was
   wrapping the fifth onto its own line and leaving it looking orphaned. */
.dialog-result { width: min(34rem, calc(100vw - 2rem)); }

.dialog-result .result-grid { grid-template-columns: repeat(5, 1fr); }

@media (max-width: 520px) {
  .dialog-result .result-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Centred under the action buttons; left-aligned read as an afterthought. */
.dialog-result .share { text-align: center; }
.dialog-result .btn-quiet { justify-self: center; }

/* ===== Archive ===== */

.archive-list {
  display: grid;
  gap: var(--s-1);
  margin: var(--s-3) 0 0;
  padding: 0;
  list-style: none;
  max-height: 22rem;
  overflow-y: auto;
}

.archive-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-2) var(--s-3);
  font: inherit;
  font-size: 0.875rem;
  text-align: left;
  color: var(--bone);
  background-color: var(--table);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.2s ease;
}
.archive-row:hover { border-color: var(--muted); }

.archive-tag-current {
  color: var(--bone);
  background-color: var(--edge);
}

.archive-tag {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--table);
  background-color: var(--signal);
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
}

/* ===== Left column extras ===== */

.panel-subtitle {
  margin: var(--s-4) 0 var(--s-2);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.speed-group { margin-top: var(--s-2); }

/* ===== Out of runs ===== */

.spent-panel {
  padding: var(--s-4);
  background-color: var(--table-lift);
  border: 1px solid var(--signal);
  border-radius: var(--radius);
}

.spent-title {
  margin: 0 0 var(--s-1);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 700;
  color: var(--signal);
}

.spent-note { margin: 0 0 var(--s-3); font-size: 0.8125rem; color: var(--muted); }

.countdown {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: var(--s-2);
  margin: var(--s-4) 0;
  padding: var(--s-3);
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

.countdown-label { font-size: 0.6875rem; color: var(--muted); }

.countdown-value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
  /* Fixed width, or the layout twitches every second as digits change. */
  font-feature-settings: "tnum";
}

/* ===== Nav clock ===== */






/* ===== Result dialog ===== */

/* "Submit score" stays on one line; "Run again" breaks before its count so
   the two buttons match height without either wrapping awkwardly. */
.result-actions .btn { line-height: 1.25; }
.btn-sub { font-size: 0.75rem; font-weight: 400; opacity: 0.8; }
.result-actions .btn-primary { white-space: nowrap; }

/* ===== Status bar ===== */

/* Sits between the header and the board, where it's actually read. As a small
   line under the board it was the least prominent thing on the page, which is
   the wrong place for the one element that says what to do next. */
/* A HUD readout, not a browser notice. The previous version — round "i" icon,
   left accent rule — is the visual language of a cookie banner, which is the
   last thing a game should look like. */
.statusbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  max-width: 1400px;
  margin: 0 auto var(--s-6);
  padding: var(--s-3) var(--s-4);
  background:
    linear-gradient(90deg, rgba(242,193,78,0.10), transparent 32%),
    var(--table-lift);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 rgba(237,234,227,0.05);
}

/* A forward chevron rather than an icon — it reads as "next", which is what
   the bar is for. */
.statusbar-marker {
  flex-shrink: 0;
  width: 0;
  height: 0;
  border-top: 0.4rem solid transparent;
  border-bottom: 0.4rem solid transparent;
  border-left: 0.6rem solid var(--signal);
  animation: nudge 2.4s ease-in-out infinite;
}

@keyframes nudge {
  0%, 100% { transform: translateX(0); opacity: 1; }
  50% { transform: translateX(3px); opacity: 0.65; }
}

@media (prefers-reduced-motion: reduce) {
  .statusbar-marker { animation: none; }
}

.statusbar-tag {
  flex-shrink: 0;
  padding-right: var(--s-3);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--signal);
  border-right: 1px solid var(--edge);
}


.statusbar-text {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--bone);
}

/* ===== Masthead ===== */

.slogan {
  margin: var(--s-1) 0 0;
  font-family: var(--font-display);
  font-size: 0.9375rem;
  font-weight: 600;
  font-style: italic;
  letter-spacing: 0.01em;
  color: var(--muted);
}

.masthead-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-3);
}

/* Right-aligned so the date, countdown and buttons form one clean edge. */




@media (max-width: 720px) {
  .masthead-inner { align-items: flex-start; }
  .masthead-right { width: 100%; justify-content: space-between; }
    }



.nav-btn[aria-pressed="true"] 
/* ===== How to play ===== */

.howto-dots {
  display: flex;
  justify-content: center;
  gap: var(--s-2);
  margin: 0 0 var(--s-4);
  padding: 0;
  list-style: none;
}

.howto-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background-color: var(--edge);
  transition: background-color 0.2s ease;
}
.howto-dot.is-active { background-color: var(--signal); }

.howto-art {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: var(--s-4);
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

.howto-heading {
  margin: 0 0 var(--s-2);
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 600;
}

.howto-body {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--bone);
}

.howto-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
  margin-top: var(--s-4);
}

/* ===== Streak ===== */





/* ===== Field comparison ===== */

.field-line {
  margin: 0 0 var(--s-3);
  padding: var(--s-2) var(--s-3);
  font-size: 0.8125rem;
  color: var(--muted);
  text-align: center;
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

.field-line strong { color: var(--bone); font-weight: 600; }

/* ===== Masthead ===== */

.logo {
  display: block;
  width: auto;
  height: clamp(3rem, 7vw, 4.5rem);
}

.meta-row {
  display: flex;
  align-items: stretch;
  gap: var(--s-4);
}

.meta-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-left: var(--s-4);
  text-align: right;
  border-left: 1px solid var(--edge);
}
.meta-item:first-child { border-left: none; padding-left: 0; }

.meta-label {
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.meta-value {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--bone);
  white-space: nowrap;
}

.meta-mono { font-variant-numeric: tabular-nums; }
.meta-accent { color: var(--signal); }

.meta-unit {
  font-family: var(--font-ui);
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--muted);
}

@media (max-width: 860px) {
  .masthead-inner { flex-direction: column; align-items: flex-start; }
  .masthead-right { align-items: flex-start; width: 100%; }
  .nav { flex-wrap: wrap; }
  .meta-row { flex-wrap: wrap; }
  .meta-item { text-align: left; }
}

.replay-canvas {
  display: block;
  margin: var(--s-3) auto;
  max-width: 100%;
  border-radius: var(--radius-sm);
}

/* The replay sizes its own canvas to fit, so the dialog never needs to
   scroll. overflow stays visible rather than auto, which prevents a
   scrollbar appearing for a stray pixel of rounding. */
#replay-dialog { overflow: visible; }

/* ==================================================================== */
/* Mobile: app layout                                                   */
/* ==================================================================== */
/*
 * On a phone the previous layout stacked three full-width columns, so placing
 * one tower meant scrolling past the board to the palette, then back up. The
 * board is the game; it should never leave the screen.
 *
 * Below 900px: the board stays put, and everything you tap repeatedly moves
 * into a fixed dock along the bottom.
 */

.dock { display: none; }

@media (max-width: 900px) {
  /* NO PAGE SCROLL on mobile.
   *
   * This removes the cause rather than compensating for it: if the page can't
   * scroll, the browser never collapses its toolbar, so the viewport height
   * never changes and the board can't be re-fitted mid-session. Everything is
   * sized to fit, and every panel that could overflow (sheets, dialogs)
   * scrolls internally. */
  html, body {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
  }

  /* PINNED, not just unscrollable.
   *
   * `overflow: hidden` alone wasn't enough on iOS, for two reasons that
   * compounded:
   *
   *  1. The base body rule has `min-height: 100vh`, and on iOS 100vh is the
   *     height with the toolbar COLLAPSED — taller than what's visible. So the
   *     page was always a toolbar's worth taller than the screen.
   *  2. iOS will still move a page with overflow hidden — a swipe that starts
   *     on the page, or a dialog taking focus. Once moved, nothing moved it
   *     back, and the header sat half under the status bar.
   *
   * A fixed body has no document to scroll: it IS the viewport. game.js adds
   * a small safety net for the one case this can't cover (the keyboard). */
  body {
    position: fixed;
    inset: 0;
    min-height: 0;
    padding-bottom: 9.5rem;   /* room for the fixed dock */
  }

  .layout { gap: var(--s-3); }

  /* Palette scrolls sideways inside the dock rather than stacking. */
  .controls {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 5.9rem;
    z-index: var(--z-palette);
    padding: var(--s-2) var(--s-3);
    margin: 0;
    background-color: var(--table);
    border-top: 1px solid var(--edge);
  }

  #live-controls { gap: var(--s-2); }

  /* The dock carries these instead. */
  .controls .resource-row,
  .controls .actions { display: none; }

  .palette {
    display: flex;
    gap: var(--s-2);
    overflow-x: auto;
    padding-bottom: var(--s-1);
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }

  .piece {
    flex: 0 0 auto;
    grid-template-columns: 2rem 1fr;
    width: 9.5rem;
    padding: var(--s-2);
    scroll-snap-align: start;
  }

  .piece-stat { font-size: 0.6875rem; }
  .piece-count { grid-column: 2; font-size: 0.6875rem; }

  .dock {
    display: grid;
    gap: var(--s-2);
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-dock);
    padding: var(--s-2) var(--s-3) calc(var(--s-3) + env(safe-area-inset-bottom));
    background-color: var(--table-lift);
    border-top: 1px solid var(--edge);
  }

  .dock-row { display: flex; align-items: center; gap: var(--s-2); }
  .dock-actions .btn { flex: 1; padding: var(--s-3); }
  .dock-meta { justify-content: space-between; }

  .dock-chip {
    padding: var(--s-1) var(--s-3);
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--bone);
    background-color: var(--table);
    border: 1px solid var(--edge);
    border-radius: 999px;
    cursor: pointer;
  }

  /* The winning-run button on a past board. Gold edge so it reads as the one
   * thing worth tapping in that row, not as another label. */
  .dock-chip-accent {
    color: var(--signal);
    border-color: var(--signal);
  }
  .dock-chip:disabled { opacity: 0.5; cursor: default; }

  .dock-stat { font-size: 0.8125rem; color: var(--muted); }
  .dock-stat strong {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    color: var(--signal);
  }

  /* Incoming becomes a sheet, opened from the dock. */
  .waves-panel {
    position: fixed;
    inset: auto 0 0 0;
    z-index: var(--z-sheet);
    max-height: 70vh;
    overflow-y: auto;
    border-radius: var(--radius) var(--radius) 0 0;
    transform: translateY(101%);
    transition: transform 0.24s ease;
  }
  .waves-panel.is-open { transform: translateY(0); }

  .sheet-close {
    position: absolute;
    top: var(--s-2);
    right: var(--s-3);
    width: 2rem;
    height: 2rem;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--muted);
    background: transparent;
    border: none;
    cursor: pointer;
  }

  .speed-group { margin-top: var(--s-3); }

  /* Header shrinks so the board gets the room. */
  .logo { height: 2.5rem; }
  .slogan { display: none; }
  .masthead { padding-bottom: var(--s-2); margin-bottom: var(--s-3); }
  .statusbar { margin-bottom: var(--s-3); padding: var(--s-2) var(--s-3); }
  .statusbar-text { font-size: 0.8125rem; }
  .footer { display: none; }
}

@media (min-width: 901px) {
  .sheet-close { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .waves-panel { transition: none; }
}

/* ==================================================================== */
/* Mobile: compact header                                               */
/* ==================================================================== */

.menu-toggle { display: none; }
.mini-clock { display: none; }
.nav-links { display: contents; }

@media (max-width: 900px) {
  .menu-toggle {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    background-color: var(--table-lift);
    border: 1px solid var(--edge);
    border-radius: var(--radius);
    cursor: pointer;
  }

  .menu-bars,
  .menu-bars::before,
  .menu-bars::after {
    display: block;
    width: 1.05rem;
    height: 2px;
    background-color: var(--bone);
    border-radius: 2px;
  }
  .menu-bars { position: relative; }
  .menu-bars::before,
  .menu-bars::after { content: ""; position: absolute; left: 0; }
  .menu-bars::before { top: -6px; }
  .menu-bars::after { top: 6px; }

  /* ONE header row: logo, live clock, menu. Everything else is in the sheet. */
  .masthead {
    padding-bottom: var(--s-2);
    margin-bottom: var(--s-3);
  }
  .masthead-inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    gap: var(--s-2);
  }
  .masthead-right {
    flex-direction: row;
    align-items: center;
    gap: var(--s-2);
    width: auto;
  }
  .logo { height: 2.25rem; }
  .slogan { display: none; }

  .mini-clock {
    display: block;
    font-family: var(--font-display);
    font-size: 0.875rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
  }

  /* The menu is a RIGHT-HAND DRAWER. Incoming stays a bottom sheet: it's a
     reference you glance at while looking at the board, so it belongs near
     the board. The menu is navigation — it takes over. Different jobs,
     different gestures. */
  .nav {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-sheet);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    width: min(19rem, 84vw);
    overflow-y: auto;
    padding: calc(var(--s-6) + env(safe-area-inset-top))
             var(--s-4)
             calc(var(--s-6) + env(safe-area-inset-bottom));
    background-color: var(--table-lift);
    border-left: 1px solid var(--edge);
    box-shadow: -14px 0 34px rgba(0, 0, 0, 0.5);
    transform: translateX(101%);
    transition: transform 0.24s ease;
  }
  .nav.is-open { transform: translateX(0); }

  .nav-links { display: grid; gap: var(--s-2); }

  /* Pinned to the bottom of the drawer by margin-top:auto — the drawer is a
   * flex column, so this takes up whatever space the buttons leave. */
  .nav .nav-footer {
    display: block;
    margin-top: auto;
    padding-top: var(--s-4);
    border-top: 1px solid var(--edge);
    text-align: center;
  }
  .nav .nav-footer .footer-links { margin: 0 0 var(--s-2); font-size: 0.875rem; }
  /* The drawer is too narrow for all three on one line, and letting it wrap
   * naturally stranded a dash at the end of the first line. Break on purpose:
   * the two forms together, the credit centred beneath. */
  .nav .nav-footer .footer-sep-jjo { display: none; }
  .nav .nav-footer .footer-jjo { flex-basis: 100%; }
  .nav .nav-footer .credit { font-size: 0.6875rem; line-height: 1.5; }
  .nav .nav-btn {
    padding: var(--s-3);
    font-size: 0.9375rem;
    text-align: left;
  }

  /* Stacked in a narrow drawer: side by side, the labels wrap and collide. */
  .nav .meta-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-3);
    margin-bottom: var(--s-2);
    padding-bottom: var(--s-4);
    border-bottom: 1px solid var(--edge);
  }
  .nav .meta-item {
    align-items: flex-start;
    text-align: left;
    padding-left: 0;
    border-left: none;
  }

  .sheet-close {
    position: absolute;
    top: calc(var(--s-2) + env(safe-area-inset-top));
    right: var(--s-3);
  }

  /* A scrim, so the sheet reads as modal and a stray tap closes it. */
  .scrim {
    position: fixed;
    inset: 0;
    z-index: var(--z-scrim);
    background-color: rgba(10, 20, 22, 0.6);
  }

  .statusbar { padding: var(--s-2) var(--s-3); gap: var(--s-2); }
  .statusbar-tag { display: none; }
  .statusbar-text { font-size: 0.75rem; line-height: 1.35; }

  .piece {
    width: 7rem;
    grid-template-columns: 1.75rem 1fr;
    gap: var(--s-2);
    padding: var(--s-2);
  }
  .piece-glyph { width: 1.75rem; height: 1.75rem; }
  .piece-name { font-size: 0.8125rem; }
  .piece-stat { display: none; }
  .piece-count { grid-column: 2; font-size: 0.6875rem; }

  .controls { bottom: var(--dock-h, 5.9rem); }
}

@media (min-width: 901px) {
  .sheet-close { display: none; }
  .scrim { display: none; }
}

/* ===== Tower guide ===== */

.guide-list {
  display: grid;
  gap: var(--s-2);
  margin: var(--s-3) 0 0;
  padding: 0;
  list-style: none;
}

.guide-row {
  display: grid;
  grid-template-columns: 3rem 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  background-color: var(--table);
  border-radius: var(--radius-sm);
}

.guide-icon { width: 3rem; height: 3rem; }

.guide-name {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-weight: 600;
  font-size: 0.9375rem;
}

.guide-tag {
  padding: 0.1rem 0.4rem;
  font-family: var(--font-ui);
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--table);
  background-color: var(--signal);
  border-radius: 999px;
}

/* Towers not offered today stay legible but recede, so the list reads as
   "these are yours, these exist" at a glance. */
.guide-row:not(.is-available) { opacity: 0.55; }
.guide-note { display: block; font-size: 0.8125rem; color: var(--muted); }
.guide-good { display: block; font-size: 0.75rem; color: var(--signal); margin-top: 0.15rem; }

.guide-cost {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--signal);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .nav, .waves-panel { transition: none; }
}

/* ===== Stat lists ===== */

.stat-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem var(--s-3);
  margin: var(--s-2) 0 0;
  font-size: 0.75rem;
  line-height: 1.4;
}

.stat-list dt {
  color: var(--muted);
  white-space: nowrap;
}

.stat-list dd {
  margin: 0;
  color: var(--bone);
  font-variant-numeric: tabular-nums;
}

/* Incoming sits in a narrow column on desktop, so its stats stay small. */
.stat-list-compact { font-size: 0.6875rem; gap: 0.05rem var(--s-2); }

/* The guide has room; give the numbers a little air. */
.guide-row { align-items: start; }
.guide-row .stat-list { margin-top: var(--s-2); }

/* Mobile speed control. */
.dock-speed { display: none; }

@media (max-width: 900px) {
  .dock-speed {
    display: grid;
    place-items: center;
    flex: 0 0 3.5rem;
    padding: var(--s-3) 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--bone);
    background-color: var(--table);
    border: 1px solid var(--edge);
    border-radius: var(--radius);
    cursor: pointer;
  }
  .dock-speed-label {
    display: block;
    font-family: var(--font-ui);
    font-size: 0.5rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
  }
  /* The in-sheet speed buttons are now duplicated by the dock. */
  .waves-panel .speed-group { display: none; }
}

/* ===== Difficulty ===== */
/*
 * Colour runs cool-to-hot with difficulty. It carries the same information as
 * the word, for anyone scanning rather than reading — and the word is always
 * there, so colour is never the only channel.
 */
.difficulty-gentle   { color: #6fbf73; }
.difficulty-moderate { color: #9ed45c; }
.difficulty-tough    { color: #f2c14e; }
.difficulty-hard     { color: #f0803c; }
.difficulty-brutal   { color: #e2564f; }

/*
 * "est." sits after the word, italic so it reads as a qualifier on the rating
 * rather than part of it. It is the only place the header admits a number is a
 * guess, so it must not look like a unit ("days", "ET") beside it.
 */
#difficulty-wrap .meta-unit {
  margin-left: 0.15rem;
  font-style: italic;
}
