/* Rack Five — the gameplay screen. The most important surface in the product. */

.game {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px calc(clamp(12px, 2.4vw, 24px) + env(safe-area-inset-right))
    calc(12px + env(safe-area-inset-bottom)) calc(clamp(12px, 2.4vw, 24px) + env(safe-area-inset-left));
  position: relative;
}

/* ── HUD ─────────────────────────────────────────────────────────────────── */

.hud {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  background: var(--t-panel);
  border: 1px solid var(--t-line);
  border-radius: var(--t-rad);
  padding: 11px 16px;
}
.hud-diff {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--t-acc);
  border: 1px solid var(--t-line-2);
  border-radius: 4px;
  padding: 4px 10px;
}
.hud-turn { font-size: 14px; color: var(--t-muted); }
.hud-turn strong { font-family: var(--t-fd); color: var(--t-text); font-variant-numeric: tabular-nums; }
.hud-budget {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: 15px;
  flex-wrap: wrap;
}
.hud-budget strong {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-variant-numeric: tabular-nums;
}
.hud-budget .op { color: var(--t-dimmer); }
.hud-budget .total { color: var(--t-acc-hi); }
.budget-bar {
  flex: 1 1 60px;
  min-width: 56px;
  height: 6px;
  border-radius: 999px;
  background: var(--t-inset);
  display: flex;
  overflow: hidden;
}
.budget-bar .seg-placed { background: var(--t-acc); }
.budget-bar .seg-loose { background: var(--t-acc-soft); }
.hud-group { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.hud-group.baseline { align-items: baseline; gap: 6px; }
.refresh-dots { display: flex; gap: 4px; }
.refresh-dots span { width: 11px; height: 11px; border-radius: 999px; }
.refresh-dots span.left { background: var(--t-acc); box-shadow: 0 0 8px rgba(217, 165, 76, 0.6); }
.refresh-dots span.spent { background: var(--t-inset); box-shadow: inset 0 0 0 1px var(--t-line); }
.hud-value {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 19px;
  color: var(--t-acc-hi);
  font-variant-numeric: tabular-nums;
}
.hud-clock-wrap { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.hud-clock {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 26px;
  font-variant-numeric: tabular-nums;
  color: var(--t-text);
}
.hud-clock.is-low { color: var(--t-warn); }
.hud-clock.is-low.pulse { animation: r5glow 1.6s ease infinite; }

/* ── Main two-column area ────────────────────────────────────────────────── */

/* Side by side above the breakpoint. `nowrap` matters: a wrapping flex line is
   sized by its tallest child's content, which would let the board push the
   scorecard off-screen instead of each column scrolling inside itself. */
.game-main {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-wrap: nowrap;
  gap: 12px;
  align-items: stretch;
}
.play-col {
  flex: 1 1 520px;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* The scorecard is a list of short rows — it never needs to grow past a
   comfortable reading width. Capping it (flex-grow: 0) means every pixel of
   extra window width goes to the play column instead, which is what actually
   needs it: more width there means more rack columns, fewer rack rows, and a
   shorter board that leaves the build bar and slots on screen without
   scrolling. Letting this column soak up half the window (its old flex: 1 1
   330px) was starving the rack of exactly the space it needed. */
.card-col {
  flex: 0 1 360px;
  max-width: 400px;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* The scorecard docks to the right, matching the design's intent, and drops
   below the board only when there isn't enough width for both side by side.
   The limit is 1100px rather than 900px because iPad Safari reports ~915px wide.
   At 900px it fell through to the desktop layout and squeezed the board into a
   465px column — seven tiles a row, six rows deep, with the build bar pushed off
   the bottom. Stacked, the board gets the full width instead, the whole rack and
   the build bar sit on screen together, and the scorecard gets the full width too
   rather than being crushed into a 370px gutter, one tap away on the jump bar.

   The second test is on *height*, not aspect. An earlier version required
   portrait, which read sensibly but excluded the case it most needed to cover: an
   iPad in landscape is about 915x700, so it is under the width limit and still
   wider than it is tall, and it fell through to the cramped two-column layout.
   Height is the honest question, because the only viewport that genuinely cannot
   afford to stack is one too short to show a stacked rack and build bar together
   — a phone on its side, at ~390px. Everything taller has the room. */
@media (max-width: 1100px) and (min-height: 501px) {
  .game-main {
    flex-direction: column;
    overflow: auto;
  }
  .game-main .play-col { flex: none; overflow: visible; }
  .game-main .card-col { flex: none; max-width: none; min-height: 420px; }
}

/* ── Loose rack ──────────────────────────────────────────────────────────── */

.rack-panel { background: var(--t-panel); border: 1px solid var(--t-line); border-radius: var(--t-rad); padding: 13px 15px; }
/* Three zones: title, the rank reference, the sort control. The middle zone
   takes the slack and centres itself in it, so the chips sit between the two
   ends rather than crowding either. It wraps to its own line before anything
   overlaps. */
.rack-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
  margin-bottom: 10px;
}
.rank-inline {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 4px 8px;
  min-width: 0;
}
.rank-inline .chips { display: flex; flex-wrap: wrap; gap: 4px; }
.rack-title {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--t-muted);
}
.rack-select-note { font-size: 12px; font-weight: 600; color: var(--t-acc-hi); }
.segmented {
  display: inline-flex;
  overflow: hidden;
  border: 1px solid var(--t-line);
  border-radius: var(--t-btn-rad);
}
.segmented button {
  display: inline-flex;
  align-items: center;
  padding: 7px 13px;
  font-size: 13px;
  color: var(--t-muted);
}
.segmented button.is-on {
  background: var(--t-acc-soft);
  color: var(--t-acc-hi);
  box-shadow: inset 0 0 0 1px var(--t-acc);
  font-weight: 600;
}
/* Bounded so a big rack (Easy's 45 tiles) can never push the build bar and
   word slots below the fold. The "LOOSE RACK" header and sort control above
   this stay put; only the tile grid itself scrolls, and only if it has to —
   at typical widths every tile fits and this never engages. */
.rack-grid {
  display: grid;
  /* Fixed tracks with explicitly sized rows, not `1fr` columns plus
     `aspect-ratio` on the tile. That pairing is circular — the tile's height
     depends on a column width that is itself flexible — and the engines resolve
     it differently: Chromium sizes the auto row from the aspect ratio, Safari
     sizes it from the tile's `min-height` and then lets the taller tile spill
     into the row beneath, which is why the rack rendered as overlapping tiles on
     iPad and iPhone Safari. A track that is a known width and a row that is the
     same known height cannot disagree anywhere.
     `justify-content: space-between` spreads the leftover width across the
     column *tracks*, so every row — including a short final one — still lines up
     on the same columns. */
  --rack-tile: 60px;
  grid-template-columns: repeat(auto-fill, var(--rack-tile));
  grid-auto-rows: var(--rack-tile);
  justify-content: space-between;
  gap: 7px;
  max-height: min(46vh, 340px);
  overflow-y: auto;
  overflow-x: hidden;
  padding: 2px 2px 4px;
  margin: -2px -2px -4px;
  scrollbar-gutter: stable;
  /* Scrolling the rack to its end must not then start dragging the page or the
     column behind it. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.rack-grid .tile {
  /* The track supplies both dimensions now. `min-height` in particular has to go:
     it is the value Safari was sizing the row from. */
  min-height: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  /* The rack is a scroll container, so the tiles have to split the gesture with
     it: a vertical drag scrolls the rack (the only way to reach the tiles below
     the fold on a phone), a sideways drag reorders. Without this the browser
     claims every touch drag for panning and fires pointercancel, which kills the
     reorder gesture outright. `touch-action` is inert for mouse input, so the
     desktop drag is unaffected. */
  touch-action: pan-y;
}
/* Proportional to the tile, not to the window. The letter belongs to the tile it
   sits in, and the old viewport term made that accidental: a 60px tile got a
   27px letter on a desktop and a 22px one on an iPad purely because the window
   was narrower. Now every 60px tile looks the same everywhere, and a tile the
   fitter has shrunk to 48px gets a letter that still fits inside it rather than
   a 27px one overflowing its own box.
   0.45 is chosen to land on exactly 27px at the 60px tile the desktop layout was
   tuned around, so that case does not move. */
.rack-grid .tile .tl {
  font-size: calc(var(--rack-tile, 60px) * 0.45 * var(--tile-letter-scale, 1));
}
/* The value keeps its 10px — smaller stops being readable, and the player is
   reading it to decide a word — but its inset scales, so it sits the same
   proportional distance into the corner at every tile size instead of creeping
   toward the letter. At 60px these resolve to today's 6px and 3px exactly. */
.rack-grid .tile .tv {
  right: calc(var(--rack-tile, 60px) * 0.1);
  bottom: calc(var(--rack-tile, 60px) * 0.05);
}
/* Hover-capable pointers only: iOS leaves :hover latched on the last tile you
   touched, so an unqualified lift would strand tiles in the raised state. */
@media (hover: hover) {
  .rack-grid .tile:hover { transform: translateY(-2px); }
}
.rack-grid .tile.is-marked {
  box-shadow: inset 0 1px 0 var(--t-tile-hi), 0 0 0 3px var(--t-acc), 0 6px 14px rgba(0, 0, 0, 0.5);
  transform: translateY(-3px);
  opacity: 0.6;
}
.rack-grid .tile.is-marked::after {
  content: '✕';
  position: absolute;
  top: 3px;
  left: 5px;
  font-size: 11px;
  font-weight: 700;
  color: var(--t-tile-text);
}
.rack-grid .tile.is-dragging { opacity: 0.45; }
.rack-grid .tile.is-drop-target { box-shadow: inset 0 1px 0 var(--t-tile-hi), 0 0 0 3px var(--t-acc-hi); }
.rack-empty { font-size: 13px; color: var(--t-dim); padding: 12px 2px; }

/* A tablet or laptop is shorter than the desktop window this cap was tuned for,
   and at 340px the rack plus its header can leave no room for the build bar — you
   cannot see the word you are assembling while you tap the letters into it.
   Trading rack height for that is the right way round: the rack is a uniform grid
   that scrolls without losing your place, and §19.1's tap flow puts every letter
   one tap from the bar regardless.
   Keyed on height alone rather than `pointer: coarse`. Pointer type is the wrong
   question — a short window needs this whoever is pointing at it — and it also
   cannot be verified in a desktop browser, which reports `fine` no matter how the
   viewport is sized. At the usual desktop heights the rack's content is shorter
   than either cap, so this changes nothing there. */
@media (max-height: 820px) {
  .rack-grid { max-height: min(38vh, 300px); }
}

/* A phone in portrait: 60px tracks leave room for only four columns and then
   scatter ~60px of slack through the gaps. A slightly smaller tile fits five —
   six on the larger handsets — which reads as a rack rather than as four lonely
   letters, and stays well clear of the 44px touch-target floor.
   This is the no-JS fallback. When fitRack runs it writes --rack-tile inline and
   supersedes this, having measured what actually fits rather than guessed. */
@media (max-width: 430px) {
  .rack-grid { --rack-tile: 56px; }
}

/* A phone in portrait is the tightest case that matters, and it is short of
   exactly one thing: height. The rack's wrapped header carries no game state and
   costs more than two rows of letters, so it collapses here and the board gets
   the difference. (The nav does the same, one block further down, at the wider
   breakpoint where it starts needing two lines.)
   The HUD deliberately does not: it is live state — turn, budget, refreshes,
   clock — and hiding what the player is playing against behind a tap would be a
   real loss for 47px. It keeps its single sideways-scrolling line. */
@media (max-width: 700px) and (max-aspect-ratio: 1 / 1) {
  /* Narrower gutters buy the rack ~14px, and at phone widths 14px is worth a
     whole extra column of tiles — which is worth a whole row of height. */
  .rack-panel { padding: 11px 8px; }
  .rack-head {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    gap: 10px;
    margin-bottom: 8px;
  }
  .rack-head::-webkit-scrollbar { display: none; }
  .rack-head > * { flex: none; }
  .rank-inline { flex-wrap: nowrap; justify-content: flex-start; }
  .rank-inline .chips { flex-wrap: nowrap; }

  /* Let the rack have the height the two collapses above just freed. The generic
     caps exist to stop the rack crowding out the rest of the board, but on a
     phone the fitter already enforces a better version of that rule: it reserves
     the build-bar tile row before sizing anything, so the word being assembled
     cannot be pushed off screen no matter how tall this allows the rack to get.
     With the old 38vh here the cap, not the reserve, was the binding constraint —
     it held a 667px phone to four rows where five fit. Raised, the reserve takes
     over and the word slots become the thing you scroll to, which is the order
     the game actually wants. */
  .rack-grid { max-height: min(62vh, 460px); }
}

/* ── Length becomes rank chips ───────────────────────────────────────────── */

.rank-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 2px 7px;
  border-radius: var(--t-rad-sm);
  background: var(--t-acc-soft);
  border: 1px solid var(--t-line);
}
.rank-chip .l { font-size: 10px; color: var(--t-muted); }
.rank-chip .r { font-family: var(--t-fd); font-weight: var(--t-fwd); font-size: 14px; color: var(--t-acc-hi); }
.rank-chip.is-live { border-color: var(--t-acc); background: var(--t-acc-soft); box-shadow: 0 0 0 1px var(--t-acc); }

/* ── Build bar ───────────────────────────────────────────────────────────── */

.build-bar {
  background: linear-gradient(180deg, var(--t-acc-soft), var(--t-panel));
  border: 1px solid var(--t-line-2);
  border-radius: var(--t-rad);
  padding: 12px 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}
.build-tiles {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  min-height: 54px;
  align-items: center;
}
.build-tile {
  position: relative;
  width: 54px;
  height: 54px;
  display: grid;
  place-items: center;
  border-radius: var(--t-rad-sm);
  cursor: grab;
  /* The build bar is a single non-scrolling row, so it can claim the whole
     gesture in both axes. */
  touch-action: none;
  user-select: none;
  -webkit-touch-callout: none;
  transform: translateY(-2px);
  background: var(--t-tile);
  box-shadow: inset 0 1px 0 var(--t-tile-hi), 0 0 0 1px var(--t-line-2), 0 5px 10px rgba(0, 0, 0, 0.5);
}
.build-tile.is-blank {
  background: var(--t-blank);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55), 0 0 0 2px var(--t-blank-bd), 0 5px 10px rgba(0, 0, 0, 0.5);
}
.build-tile.is-dragging { opacity: 0.55; cursor: grabbing; }
.build-tile .tl {
  font-family: var(--t-fd);
  font-weight: 600;
  font-size: calc(23px * var(--tile-letter-scale, 1));
  line-height: 1;
  color: var(--t-tile-text);
  pointer-events: none;
}
.build-tile.is-blank .tl { color: var(--t-blank-text); }
.build-tile .tv {
  position: absolute;
  right: 5px;
  bottom: 2px;
  font-size: 9px;
  font-weight: 600;
  color: var(--t-tile-val);
  pointer-events: none;
}
/* ── Red tile ────────────────────────────────────────────────────────────── */
/* The star is not decoration. Colour alone cannot carry "this tile scores
   differently", so the marker has to survive a greyscale render. */

.tile.is-red,
.build-tile.is-red {
  background: var(--t-red);
  box-shadow: inset 0 1px 0 var(--t-red-bd), 0 0 0 2px var(--t-red-bd), 0 5px 10px rgba(0, 0, 0, 0.5);
}
.tile.is-red .tl,
.build-tile.is-red .tl { color: var(--t-red-text); }
.tile.is-red .tv,
.build-tile.is-red .tv { color: var(--t-red-val); }
.tile.is-red::before,
.build-tile.is-red::before {
  content: '★';
  position: absolute;
  top: 2px;
  left: 5px;
  font-size: 10px;
  line-height: 1;
  color: var(--t-red-val);
  pointer-events: none;
}

.build-hint { font-size: 14px; color: var(--t-dim); }
.build-readout { flex: 1; min-width: 150px; }
.build-word {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 21px;
  letter-spacing: 0.1em;
  min-height: 26px;
}
.build-meta { font-size: 12px; color: var(--t-muted); }
.build-meta .rank { color: var(--t-acc-hi); font-weight: 600; }
.build-tip { font-size: 11px; color: var(--t-dim); margin-top: 2px; }

/* ── Banners ─────────────────────────────────────────────────────────────── */

.banner {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-start;
  padding: 11px 15px;
  border-radius: var(--t-rad-sm);
  background: var(--t-warn-soft);
  border: 1px solid var(--t-warn);
}
.banner b { font-family: var(--t-fd); font-weight: 700; font-size: 13px; color: var(--t-warn); white-space: nowrap; }
.banner span { font-size: 13px; line-height: 1.45; color: var(--t-text); text-wrap: pretty; }
.banner.ok { background: var(--t-acc-soft); border-color: var(--t-line-2); }
.banner.ok b { color: var(--t-acc); }

/* ── Word slots ──────────────────────────────────────────────────────────── */

.slots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 9px;
}
.slot {
  display: flex;
  flex-direction: column;
  padding: 11px 13px;
  min-height: 150px;
  border-radius: var(--t-rad);
  text-align: left;
  background: var(--t-inset);
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.5);
}
.slot.is-provisional {
  background: var(--t-acc-soft);
  border: 2px dashed var(--t-acc);
  box-shadow: none;
}
.slot.is-provisional:hover { background: var(--t-panel-2); }
.slot.is-permanent {
  background: var(--t-panel-2);
  border: 2px solid var(--t-acc);
  box-shadow: none;
  cursor: default;
}
.slot-head { display: flex; align-items: center; gap: 6px; }
.slot-n {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-dim);
}
.slot-money {
  margin-left: auto;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--t-acc-hi);
}
.slot-letters { display: flex; gap: 2px; flex-wrap: wrap; margin: 7px 0 auto; }
.slot-letters span {
  width: 24px;
  height: 28px;
  border-radius: 4px;
  display: grid;
  place-items: center;
  font-family: var(--t-fd);
  font-weight: 600;
  font-size: 13px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  background: var(--t-tile);
  color: var(--t-tile-text);
}
.slot-letters span.blank { background: var(--t-blank); color: var(--t-blank-text); }
/* The placed word has to keep saying which letter was the red one — the tile is
   gone from the rack by now, and the multiplier it carries is the reason the
   category pays what it does. Too small for the rack tile's corner star, so the
   marker is a ring the star sits on top of. */
.slot-letters span.is-red {
  position: relative;
  background: var(--t-red);
  color: var(--t-red-text);
  box-shadow: 0 0 0 1.5px var(--t-red-bd), 0 1px 3px rgba(0, 0, 0, 0.35);
}
.slot-letters span.is-red::after {
  content: '★';
  position: absolute;
  top: -1px;
  right: 1px;
  font-size: 7px;
  line-height: 1;
  color: var(--t-red-val);
}
.slot-figures { display: flex; align-items: baseline; gap: 6px; }
.slot-rank {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 26px;
  line-height: 1;
  color: var(--t-acc-hi);
}
.slot-cap { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--t-dim); }
.slot-tv { margin-left: auto; font-family: var(--t-fd); font-weight: var(--t-fwd); font-size: 15px; }
.slot-empty { margin: auto 0; font-size: 14px; color: var(--t-dim); }
.slot-status {
  margin-top: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--t-acc);
}
.slot.is-empty .slot-status { color: var(--t-dimmer); }

/* ── Progress strip ──────────────────────────────────────────────────────── */

.progress-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 12px 15px;
  border-radius: var(--t-rad);
  background: var(--t-panel);
  border: 1px solid var(--t-line);
}
.progress-count {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 20px;
  color: var(--t-acc-hi);
}
.progress-next { flex: 1 1 200px; font-size: 13px; line-height: 1.45; color: var(--t-muted); text-wrap: pretty; }

/* ── Action row ──────────────────────────────────────────────────────────── */

/* Refresh and Hint share a line and split it. Left to their intrinsic widths they
   wrapped onto two rows inside the ~370px scorecard column, spending twice the
   height on two buttons for no reason — `min-width: 0` is what lets them shrink
   below their content instead of forcing the wrap. They still wrap on a phone,
   where one per line is genuinely the right answer. */
.action-row { flex: none; display: flex; flex-wrap: wrap; gap: 8px; }
.action-row > * { flex: 1 1 auto; min-width: 0; }
.action-row .btn, .action-row .btn-outline, .action-row .btn-ghost {
  min-height: 50px;
  justify-content: center;
  text-align: center;
}

/* Tighten the nav below the width where it starts to crowd. This part only makes
   it narrower — dropping the decorative theme name, trimming the type and the
   padding — which is often enough on its own to keep it on a single line, and
   never makes it taller. Height is untouched: it is the tap target. */
@media (max-width: 1100px) {
  /* This overrides the base nav padding, so it has to carry the insets too. */
  .nav {
    padding: calc(10px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right)) 8px
      calc(12px + env(safe-area-inset-left));
    gap: 8px 10px;
  }
  .nav-brand { font-size: 15px; }
  .nav-item { font-size: 13px; padding: 0 11px; }
  .nav-theme-name { display: none; }

  /* The HUD needs roughly 1000px for one line and wrapped to 93px on an iPad —
     a tenth of the screen, spent on a status strip. Everything stays present and
     in the same order; it simply scrolls sideways in one line, as it already did
     on a phone. */
  .hud {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 14px;
    padding: 9px 12px;
    scrollbar-width: none;
  }
  .hud::-webkit-scrollbar { display: none; }
  .hud > * { flex: none; }
  .hud-clock-wrap { margin-left: 6px; }
}

/* Where the nav cannot hold one line, the screen links move into a sheet rather
   than wrapping onto a second.
   Wrapping was the first attempt and it looked broken on a tablet: the wordmark
   sat far left, the run controls far right, and the links dropped underneath,
   leaving a wide empty band across the top of the screen that read as a mistake
   and took ~44px from the board to do it. One line and a Menu button — which also
   names the screen you are on, so the bar still answers "where am I?" — is both
   tidier and shorter.
   The two conditions are an OR: narrow in any orientation needs this, and so does
   a portrait tablet, which is wide enough that the nav *nearly* fits and wraps
   into a ragged second line anyway. */
@media (max-width: 950px), (max-width: 1100px) and (max-aspect-ratio: 1 / 1) {
  .nav-items { display: none; }
  .nav-menu-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    min-height: 38px;
    padding: 0 13px;
    border: 1px solid var(--t-line-2);
    border-radius: var(--t-btn-rad);
    font-size: 13px;
    font-weight: 600;
    color: var(--t-acc-hi);
  }
  .nav-brand { font-size: 14px; letter-spacing: 0.16em; }
  .nav-quit-btn { font-size: 12px; padding: 0 10px; }
  /* The sheet carries the theme switch. A second copy in the bar is what pushed
     the row onto a second line in the first place. Abandon run stays visible:
     it is destructive and belongs in the open, not buried in a menu. */
  .nav-theme-btn { display: none; }
  .nav-theme-name { display: none; }
}

/* Phone-only extras on top of the tablet treatment above. */
@media (max-width: 700px) {
  /* The one HUD item worth dropping rather than scrolling past: the same numbers
     are spelled out in words immediately to its left. */
  .budget-bar { display: none; }
  .hud-clock { font-size: 22px; }
  .slots { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .slot { min-height: 132px; }
}

/* A phone held sideways: wide enough for two columns, but only ~350px of usable
   height for the whole board. Everything stays present — the vertical rhythm is
   simply compressed so the slots, the rack and the build bar can be on screen
   together, which is the minimum needed to build a word without scroll-hunting.
   Keyed on height, so no desktop window of ordinary proportions sees it. */
@media (max-height: 500px) and (min-aspect-ratio: 1 / 1) {
  /* The nav wraps to three lines at this width and would take a third of the
     screen. One line that scrolls sideways instead, as it already does on a
     narrow phone. */
  .nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    gap: 12px;
    padding: calc(7px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right)) 7px
      calc(12px + env(safe-area-inset-left));
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav > * { flex: none; }
  .nav-items { flex-wrap: nowrap; }
  .game { gap: 7px; padding-top: 7px; }
  .hud {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 14px;
    padding: 7px 12px;
    scrollbar-width: none;
  }
  .hud::-webkit-scrollbar { display: none; }
  .hud > * { flex: none; }
  .budget-bar { display: none; }
  .game-main { gap: 9px; }
  .play-col { gap: 8px; }
  .slots { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 7px; }
  .slot { min-height: 96px; padding: 8px 10px; }
  /* One or two rows of tiles, scrolled — the rack is the one part of the board
     that reads fine at a reduced height, because it is a uniform grid. */
  .rack-grid { max-height: 130px; }
  .rack-panel { padding: 9px 11px; }
  /* The rack header wraps to three lines in a column this narrow — 109px, more
     than the tile grid below it. One sideways-scrolling line instead, the same
     answer the nav and the HUD already use, so the rank reference stays present
     rather than being hidden on the device most likely to need it. */
  .rack-head {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    margin-bottom: 7px;
  }
  .rack-head::-webkit-scrollbar { display: none; }
  .rack-head > * { flex: none; }
  .rank-inline { flex-wrap: nowrap; justify-content: flex-start; }
  .rank-inline .chips { flex-wrap: nowrap; }
  /* 50px is generous; 44px is the floor the rest of the app holds to. */
  .action-row .btn, .action-row .btn-outline, .action-row .btn-ghost { min-height: 44px; }
}

/* ── Narrow-screen jump bar ──────────────────────────────────────────────── */

.jump-bar { display: none; }

/* Matches the stacking rule exactly: the bar exists to reach a scorecard that
   has dropped below the board, so on a sideways phone — where both columns are
   on screen at once — it would only cover the board it is meant to reach. */
@media (max-width: 1100px) and (min-height: 501px) {
  .jump-bar {
    position: fixed;
    left: 50%;
    /* Clear of the iPhone home indicator, which otherwise sits directly over
       these buttons and competes with them for the swipe. */
    bottom: calc(14px + env(safe-area-inset-bottom));
    transform: translateX(-50%);
    z-index: 50;
    display: inline-flex;
    overflow: hidden;
    max-width: calc(100vw - 24px);
    border-radius: 999px;
    background: var(--t-toast);
    border: 1px solid var(--t-line-2);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
  }
  .jump-bar button {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 16px;
    font-size: 13px;
    color: var(--t-muted);
    white-space: nowrap;
  }
  .jump-bar button + button {
    border-left: 1px solid var(--t-line);
    color: var(--t-acc-hi);
    font-weight: 600;
  }
  .game { padding-bottom: calc(68px + env(safe-area-inset-bottom)); }
}

/* ── Scorecard ───────────────────────────────────────────────────────────── */

.scorecard {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--t-panel);
  border: 1px solid var(--t-line-2);
  border-radius: var(--t-rad);
}
.sc-header {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px;
  background: var(--t-toast);
  border-bottom: 1px solid var(--t-line);
}
.sc-header-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.sc-title {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--t-muted);
}
.sc-sub { font-size: 12px; color: var(--t-dim); }
.sc-take-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-dim);
}
.sc-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  min-height: 40px;
  border-radius: var(--t-rad-sm);
  font-size: 13px;
  border: 1px solid var(--t-line);
  color: var(--t-dim);
}
.sc-chip.qualifies {
  border: 1px solid var(--t-line-2);
  background: var(--t-acc-soft);
  color: var(--t-acc-hi);
}
.sc-chip.is-selected {
  border: 2px solid var(--t-acc);
  background: var(--t-acc-soft);
  color: var(--t-acc-hi);
  font-weight: 600;
}
.sc-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sc-status { font-size: 13px; line-height: 1.45; color: var(--t-muted); text-wrap: pretty; }
.sc-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  font-size: 11px;
  color: var(--t-dim);
}
.sc-legend span { display: inline-flex; align-items: center; gap: 6px; }
.sc-legend i {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  display: block;
}
.sc-legend i.scored { border-left: 4px solid var(--t-ok); background: var(--t-inset); }
.sc-legend i.open { border: 1px solid var(--t-line-2); background: var(--t-acc-soft); }
.sc-sections { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; }
.sc-section-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-acc);
  margin-bottom: 8px;
}
.sc-rows { display: flex; flex-direction: column; gap: 5px; }
.sc-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--t-rad-sm);
  text-align: left;
  background: var(--t-panel);
  border: 1px solid var(--t-line);
}
.sc-row .nm { font-weight: 600; font-size: 14px; }
.sc-row .ht { font-size: 11px; color: var(--t-dim); }
.sc-row .st {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--t-acc-hi);
}
.sc-row .vl {
  margin-left: auto;
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 17px;
  color: var(--t-dimmer);
  font-variant-numeric: tabular-nums;
}
.sc-row.qualifies { background: var(--t-acc-soft); border: 1px solid var(--t-line-2); }
.sc-row.qualifies .vl { color: var(--t-acc-hi); }
.sc-row.is-selected {
  background: var(--t-acc-soft);
  color: var(--t-acc-hi);
  border: 2px solid var(--t-acc);
  box-shadow: 0 0 0 3px var(--t-acc-soft);
  padding: 8px 11px;
}
.sc-row.is-selected .vl { color: var(--t-acc-hi); }
.sc-row.is-scored {
  background: var(--t-inset);
  color: var(--t-muted);
  border: 1px solid transparent;
  border-left: 4px solid var(--t-ok);
  cursor: default;
}
.sc-row.is-scored .st { color: var(--t-ok); }
.sc-row.is-scored .vl { color: var(--t-text); }
.sc-bonus {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  padding: 9px 12px;
  border-radius: var(--t-rad-sm);
  border: 1px dashed var(--t-line-2);
  font-size: 13px;
}
.sc-bonus .amt { margin-left: auto; font-family: var(--t-fd); font-weight: var(--t-fwd); color: var(--t-acc-hi); }
/* Solid border and a bigger figure than the bonus row — this is the running
   headline number, not a progress note. */
.sc-total {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  padding: 10px 12px;
  border-radius: var(--t-rad-sm);
  border: 1px solid var(--t-line-2);
  background: var(--t-panel-2, var(--t-inset));
  font-size: 14px;
  font-weight: 600;
}
.sc-total .amt {
  margin-left: auto;
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 18px;
  color: var(--t-acc-hi);
}
.sc-footer {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  padding: 12px 16px;
  background: var(--t-toast);
  border-top: 2px solid var(--t-acc);
  animation: r5rise 0.18s ease;
}
.sc-footer .ft-text { flex: 1 1 240px; min-width: 0; }
.sc-footer .ft-kicker {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-acc);
}
.sc-footer .ft-cat {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 16px;
  color: var(--t-acc-hi);
}
.sc-footer .ft-help {
  font-size: 12px;
  line-height: 1.4;
  color: var(--t-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sc-footer .ft-warn { font-size: 12px; line-height: 1.4; color: var(--t-warn); margin-top: 2px; }

/* ── Modals specific to play ─────────────────────────────────────────────── */

.modal.blank-modal { width: min(560px, 100%); border-color: var(--t-blank-bd); }
.blank-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(48px, 1fr)); gap: 6px; }
.blank-grid button {
  min-height: 48px;
  display: grid;
  place-items: center;
  border-radius: var(--t-rad-sm);
  background: var(--t-blank);
  color: var(--t-blank-text);
  font-family: var(--t-fd);
  font-weight: 600;
  font-size: 19px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55), 0 2px 5px rgba(0, 0, 0, 0.4);
}
.blank-grid button:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55), 0 0 0 2px var(--t-acc); }
.hint-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(70px, 1fr)); gap: 7px; }
.hint-grid button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 0;
  border-radius: var(--t-rad-sm);
  border: 1px solid var(--t-line);
}
.hint-grid button:hover { border-color: var(--t-acc); background: var(--t-acc-soft); }
.hint-grid .n { font-family: var(--t-fd); font-weight: var(--t-fwd); font-size: 20px; }
.hint-grid .r { font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--t-dim); }
.hint-word {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 34px;
  letter-spacing: 0.1em;
  color: var(--t-acc-hi);
}
.modal.jumbo-modal {
  text-align: center;
  align-items: center;
  padding: 34px 28px;
  border: 2px solid var(--t-acc);
  box-shadow: 0 26px 70px rgba(0, 0, 0, 0.65);
  animation: r5pop 0.3s ease;
}
.jumbo-word-big {
  font-family: var(--t-fd);
  font-weight: var(--t-fwd);
  font-size: 46px;
  line-height: 1;
  color: var(--t-acc-hi);
  animation: r5glow 1.6s ease infinite;
}
.jumbo-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--t-acc);
}
.modal.timeout-modal { width: min(500px, 100%); border: 2px solid var(--t-warn); }
.modal.timeout-modal .modal-title { color: var(--t-warn); }
.summary-block {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 14px 16px;
  border-radius: var(--t-rad-sm);
  background: var(--t-panel);
}
.summary-block .line { display: flex; gap: 10px; font-size: 14px; align-items: baseline; }
.summary-block .line strong { margin-left: auto; }
.reassure {
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-muted);
  padding: 12px 14px;
  border-radius: var(--t-rad-sm);
  background: var(--t-panel);
}
.intent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 7px; }
.intent-grid button {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 11px 13px;
  border-radius: var(--t-rad-sm);
  border: 1px solid var(--t-line);
  text-align: left;
}
.intent-grid button:hover { border-color: var(--t-acc); background: var(--t-acc-soft); }
.intent-grid .n { font-weight: 600; font-size: 14px; }
.intent-grid .h { font-size: 11px; color: var(--t-dim); }
.feel-row { display: flex; flex-wrap: wrap; gap: 7px; }
