/* --------------------------------------------------------------------------
   style.css — regions, panels and stub widgets.
   The shell (viewport, stage, letterbox) lives inline in index.html.

   Layout contract, in stage design units (390 x 844):
     HUD   top     64px    day / clock / money / fame + day progress bar
     PLAY  middle  702px   the room and all panels
     NAV   bottom  78px    five tabs, thumb height

   Everything here is PLACEHOLDER except the region geometry and the tokens.
   Art and UI builders: keep the ids, replace the looks.
   -------------------------------------------------------------------------- */

:root {
  /* UI SWEEP (2026-08-15). Rubric 11's vertical budget is ~12 / 77 / 11.
     100 + 92 of 844 puts play at 77.3%. The old 64/78 gave the HUD 7.6% —
     too thin to carry two rows of pills, which is how the reference reads. */
  --hud-h: 100px;
  --nav-h: 92px;

  /* worn, warm, lived-in. Placeholder palette — the art builder owns the real one. */
  --ink:        #f3e3cd;
  --ink-dim:    #c3ac92;
  --ink-faint:  #8d7660;
  --bg-deep:    #1a110b;
  --bg-room:    #3a2a1e;
  --bg-panel:   #2a1c13;
  --bg-raised:  #402d20;
  --line:       #543a28;
  --accent:     #d2703a;   /* terracotta */
  --accent-2:   #7d9455;   /* nopal */
  --gold:       #e8b24c;
}

/* ------------------------------------------------------------------ HUD --- */

/* UI SWEEP (2026-08-15), rubric 9 + 13. The reference's HUD is not a band: it
   is COOL desaturated PILLS (measured mean #414747, h180 s4% l27%) floating on
   the room's own darkened top edge, white type with a soft shadow, one number
   per pill. The ground here is the room's deep warm brown — the value
   sandwich's dark top — so the pills read as chrome OVER the room, the way
   theirs do, rather than as a separate grey app bar. */
.hud {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  padding: 9px 10px;
  background: linear-gradient(#241811, #2b1d13);
  border-bottom: 2px solid #1a110b;
  z-index: 3;
}
.hud-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.hud-pill {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 999px;
  background: linear-gradient(#454d4d, #343b3b);
  border: 1px solid #2b3130;
  box-shadow: 0 2px 0 rgba(0, 0, 0, .35);
  color: #f2efe6;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .55);
  white-space: nowrap;
}
.hud-day    { font-size: 14px; font-weight: 800; letter-spacing: .02em; }
.hud-clock  { font-size: 12px; color: #c6ccc9; font-variant-numeric: tabular-nums; }
.hud-money  { font-size: 14px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.hud-bote   { font-size: 11px; color: #c6ccc9; font-variant-numeric: tabular-nums; }

/* EL ANTOJO — the ring on the stove, dark to orange (BIBLE §7). A conic fill
   driven by --antojo (0deg..360deg); the inner disc is punched out with a
   mask so it stays a ring. Never a number next to it, only the word. */
.hud-pill-antojo { padding: 4px 10px; }
.antojo-ring {
  width: 16px; height: 16px;
  border-radius: 50%;
  background:
    conic-gradient(var(--accent) var(--antojo, 0deg), #1c1712 var(--antojo, 0deg));
  -webkit-mask: radial-gradient(circle, transparent 0 4px, #000 4.5px);
  mask: radial-gradient(circle, transparent 0 4px, #000 4.5px);
  box-shadow: 0 0 0 1.5px #14100c;
}
.antojo-label {
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #a8afac;
}
.hud-title {
  flex: 1;
  /* min-width 0: without it the letterspaced title refuses to shrink and
     shoves the money pill off the right edge (seen the day the antojo pill
     landed — flex min-width defaults to content size). It is decorative;
     the pills are not. */
  min-width: 0;
  overflow: hidden;
  text-align: center;
  font-size: 10px;
  letter-spacing: .18em;
  color: var(--ink-faint);
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
}
.hud-pill-status { flex: 1; justify-content: flex-start; min-width: 0; overflow: hidden; }
.hud-status {
  font-size: 11.5px; font-weight: 600; color: #e8e4d8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hud-pill-daybar { flex: 1; max-width: 120px; }
.hud-daybar-label {
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #a8afac;
}
.hud-daybar {
  flex: 1;
  height: 7px;
  border-radius: 4px;
  background: #14100c;
  overflow: hidden;
}
.hud-daybar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--gold), var(--accent));
  transition: width .12s linear;
}

/* ----------------------------------------------------------------- PLAY --- */

.play {
  position: relative;
  overflow: hidden;
  background: var(--bg-room);
  z-index: 1;
}
.layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* MOBILE-SAFARI FIT (index.html shell): when the stage runs shorter than 844
   design px, the ROOM scales uniformly to the play region it actually has —
   canvas, tap zones, bubbles and markers together, so paint and DOM never
   disagree — while the UI layer (panels) keeps full-size type and scrolls.
   --play-scale is 1 everywhere the frame is tall enough, including the
   capture harness. */
.layer-back, .layer-props, .layer-actors {
  transform: scale(var(--play-scale, 1));
  transform-origin: top center;
}
/* COOKING-LOOP (2026-08-15): the UI layer itself is inert — a full-bleed
   pointer-events:auto layer was swallowing every tap meant for the stock
   zones and bubbles in the layers beneath it. The PANELS take their own
   events instead; over the bare room, taps fall through to the room's DOM. */
.layer-ui { pointer-events: none; }
/* :not() keeps this below the transparent diner panel's own rule — a
   two-class selector here silently beat .panel-transparent's none and the
   invisible panel went back to eating the room's taps. */
.layer-ui .panel:not(.panel-transparent) { pointer-events: auto; }

/* --- stub room (back layer) */
.stub-room { position: absolute; inset: 0; }
.stub-wall {
  position: absolute; inset: 0 0 22% 0;
  background: repeating-linear-gradient(180deg, #4a3526 0 26px, #45311f 26px 52px);
}
.stub-window {
  position: absolute; top: 8%; left: 55%; width: 34%; height: 32%;
  background: linear-gradient(#9db98f, #6d8a63);
  border: 6px solid #2f2015;
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px rgba(0,0,0,.2);
}
.stub-floor {
  position: absolute; inset: 78% 0 0 0;
  background:
    repeating-linear-gradient(90deg, #5a3f2a 0 40px, #543a26 40px 80px);
  border-top: 3px solid #2b1c12;
}

/* --- stub counter + plates (props layer) */
.stub-counter {
  position: absolute;
  left: 0; right: 0; top: 70%;
  height: 60px;
  background: linear-gradient(#6b4a2f, #4b3320);
  border-top: 4px solid #8a6440;
  box-shadow: 0 6px 0 rgba(0,0,0,.25);
}
/* --- COOKING-LOOP (2026-08-15): the room's two interactive things ---------
   Both containers cover the play area; their children carry the position
   (from art.anchors(), so DOM and paint agree). */
.plates, .actors {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The painted stock IS the button. The zone is an invisible thumb-sized
   target centred on the plate; the painted badge carries the count. */
.stock-tap {
  position: absolute;
  width: 64px;
  height: 52px;
  transform: translate(-50%, -55%);
  appearance: none;
  border: 0;
  background: none;
  pointer-events: auto;
  touch-action: manipulation;
}
.stock-tap.is-pressed { filter: brightness(1.2); }

/* The order bubble: a round white thought over the diner's head holding a
   PAINTED picture of the dish — no words (ref-loop.md step 3). The gentle
   bob is the room asking, not nagging. */
.order-bubble {
  position: absolute;
  width: 56px;
  height: 52px;
  transform: translate(-50%, -100%);
  pointer-events: none;
  animation: bubble-bob 2.4s ease-in-out infinite;
}
@keyframes bubble-bob {
  0%, 100% { margin-top: 0; }
  50% { margin-top: -4px; }
}
@media (prefers-reduced-motion: reduce) { .order-bubble { animation: none; } }
.order-pic {
  width: 100%;
  height: 100%;
  border-radius: 50% 50% 46% 46%;
  background: #f6efdd center / 78% no-repeat;
  border: 2px solid #6b5334;
  box-shadow: 0 3px 0 rgba(32, 20, 10, .3);
}
.order-pic { background-size: 82%; background-position: center 55%; }
.order-tail {
  position: absolute;
  left: 50%;
  bottom: -7px;
  width: 10px;
  height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: #f6efdd;
  border-right: 2px solid #6b5334;
  border-bottom: 2px solid #6b5334;
}

/* --- STORY-BEATS: speech in the room --------------------------------------
   Two bubbles, both anchored over the speaker's own head (same anchors the
   order bubble uses, so DOM and paint agree). BIBLE §5: max 2 lines, max 42
   characters per line — the width and font are sized so that's what fits. */
.say-bubble {
  position: absolute;
  max-width: 280px;
  transform: translate(-50%, -100%);
  pointer-events: none;
  appearance: none;
  border: 0;
  padding: 0;
  background: none;
  text-align: left;
}
.say-text {
  padding: 7px 10px 8px;
  border-radius: 12px;
  background: #f6efdd;
  border: 2px solid #6b5334;
  box-shadow: 0 3px 0 rgba(32, 20, 10, .3);
  color: #2b1c12;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}
.say-tail {
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 10px;
  height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: #f6efdd;
  border-right: 2px solid #6b5334;
  border-bottom: 2px solid #6b5334;
}
/* A beat bubble is an invitation: tappable, warmer, breathing gently.
   The bob is the room asking, not nagging — same rhythm as the order bubble. */
.beat-bubble {
  pointer-events: auto;
  touch-action: manipulation;
  animation: bubble-bob 2.4s ease-in-out infinite;
}
.beat-bubble .say-text {
  background: #fdf3d3;
  border-color: #8a5a2a;
}
.beat-bubble.is-pressed .say-text { filter: brightness(1.08); }
@media (prefers-reduced-motion: reduce) { .beat-bubble { animation: none; } }

/* El pilón line — a short transient message, low, out of the food's way. */
.toast {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(31, 20, 13, .92);
  border: 1px solid #6b5334;
  color: #e8d9b8;
  font-size: 12px;
  white-space: nowrap;
  pointer-events: none;
}
.toast[hidden] { display: none; }
.toast:not([hidden]) { animation: toast-in .16s ease-out; }
@keyframes toast-in {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to   { opacity: 1; transform: translateX(-50%); }
}

/* (The old #diner-status stub is gone — the status line lives in the HUD's
   second row now, which is where the critic said it belonged.) */

/* --------------------------------------------------------------- PANELS --- */

.panel {
  position: absolute;
  inset: 0;
  padding: 14px 14px 16px;
  background: linear-gradient(180deg, rgba(42,28,19,.96), rgba(31,20,13,.98));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.panel[hidden] { display: none; }
/* PHONE-FEEL: surfaces ARRIVE instead of popping. Everything here is under
   180ms — long enough to carry weight, short enough that the shoot harness's
   250ms settle always captures the finished state — and every animation dies
   under prefers-reduced-motion. */
.panel:not([hidden]):not(.panel-transparent) { animation: panel-in .14s ease-out; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.panel-transparent { background: none; pointer-events: none; padding: 0; }
.panel-transparent > * { pointer-events: auto; }

.panel-head { margin-bottom: 12px; }
.panel-title { font-size: 20px; font-weight: 800; letter-spacing: .01em; }
.panel-sub { font-size: 12px; color: var(--ink-faint); margin-top: 2px; }

/* --- dish grid (cook panel) */
.dish-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.dish-card {
  appearance: none;
  border: 2px solid var(--line);
  border-radius: 12px;
  background: var(--bg-raised);
  color: var(--ink);
  padding: 5px 5px 8px;
  font: inherit;
  text-align: center;
  transition: transform .06s ease, filter .06s ease;
}
.dish-card.is-pressed { transform: translateY(2px) scale(.97); filter: brightness(1.15); }
/**
 * FOOD-ART. The thumb well is a PALE CARD, not a dark one, and that is
 * measured rather than chosen: `ref-geometry.md` §4 found the reference's menu
 * icon floated on "a flat cream card, mean #cab6a6 l72%" with a dotted plate
 * ring and no cast shadow, and its median luma 19 points above the same dish
 * on the counter. A bright, saturated dish on a dark tile loses the contrast
 * the whole trick depends on. The dotted ring is baked INTO the bitmap by
 * food.js so the icon is self-contained wherever it is used.
 */
.dish-thumb {
  /**
   * ROUND-4. THE TILE WAS FLOODING THE CELL AND THE CELL SHAPE WAS WHY.
   *
   * Measured on the card thumb rect: our top colour `#e0d8c0` covered **70.1%**
   * of it against the reference icon cell's top colour at **34.7%**. Three
   * quarters of our menu thumbnail was one flat value, and no amount of work on
   * the dish itself can survive that — a judge reads the cell, not the sprite.
   *
   * The cause was aspect, not scale. A dish sprite bakes at roughly 1.36 : 1
   * (a disc at 20.3° plus whatever stands proud of it); the well was 110 × 74,
   * i.e. **1.49 : 1**, so `background-size: contain` fitted by HEIGHT and drew
   * every plate at 57% of the width available to it. At 88px the well is
   * 1.25 : 1, the width binds instead, and the dish fills the cell the way
   * theirs does.
   */
  /**
   * ROUND-9 OF FOOD-ART: 88 → 70. `art/index.js` now trims the card bitmap to
   * its own alpha bounding box (see `alphaBox`), so the thumbnail is the DISH
   * rather than the dish plus the airspace its sprite reserves for height. A
   * trimmed plate is about 1.9 : 1; at 88px tall in a ~100px cell the well was
   * 1.14 : 1, so `contain` fitted by width and left a third of the cell as
   * empty tile above and below the food. 70px puts the well at ~1.45 : 1, which
   * is close enough that the dish binds on both axes.
   */
  height: 70px;
  border-radius: 7px;
  /**
   * ROUND-3. The tile was `#c9b8a4`, **l 71%**, against the reference's own
   * menu tile at l 82% — and it carried a 1px `#2b1c12` border and an inset
   * shadow, so the brightest thing inside the cell was 11 points darker than
   * theirs before the dish was even drawn. On an 11-point-darker ground
   * nothing can read bright, and our l71% enamel plate had zero separation
   * from it. The measured consequence: card p50 luma 71% against their 84%.
   * Tile up 11 points, border to a warm mid-tone, inset shadow gone.
   */
  background: #e3d8c2 center/contain no-repeat;
  border: 1px solid #9c7d55;
  margin-bottom: 6px;
}
/* Uniform row heights. A blind judge marked us down because two cards in the
   same row were different heights: the caption wraps to two lines on some
   dishes and one on others, and the grid stretched to whichever was taller.
   The name box is now always two lines high, so every baseline aligns. */
.dish-card {
  display: flex; flex-direction: column;
  /* The cell was `--bg-raised` #402d20, l 19%, and it was the darkest dominant
     colour inside the thumb rect — 5% of it, against the reference's darkest
     dominant at l 25% and 2.3%. Lifted 12 points so the tile is not sitting in
     a hole. */
  background: #6a4c34;
  border-color: #8b6947;
}
.dish-name {
  font-size: 11px; font-weight: 700; line-height: 1.2;
  min-height: 26px;
  display: flex; align-items: center; justify-content: center;
}
.dish-price { font-size: 11px; color: var(--gold); margin-top: 2px; }
.dish-cost { font-size: 9.5px; color: var(--ink-faint); margin-top: 1px; }

/* --- el recetario (menu panel): the whole thirty, grouped by Cartel */
.cartel-head {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 12px 0 2px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.cartel-head:first-child { margin-top: 0; }
.recipe-row { grid-template-columns: 84px 1fr auto; align-items: flex-start; }
/* A dish sprite is ~2.3 : 1 — a disc seen at 20.3°. A square cell letterboxes it
   and draws the food at half the width it should have; the cell matches the art. */
.dish-icon {
  width: 74px; height: 50px;
  background-color: #e3d8c2;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}
.recipe-name { font-size: 13px; font-weight: 700; line-height: 1.25; }
.recipe-note {
  font-size: 10.5px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--ink-dim);
  margin-top: 3px;
}
.recipe-row .row-side { align-self: center; }

/* --- pots in progress */
.pot-row { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
.pot {
  border: 2px solid var(--line);
  border-radius: 10px;
  padding: 8px 10px;
  background: #221610;
}
.pot-name { font-size: 12px; margin-bottom: 6px; }
.pot-bar { height: 8px; border-radius: 4px; background: #14100c; overflow: hidden; }
.pot-bar-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--gold)); }
.pot-empty { font-size: 12px; color: var(--ink-faint); text-align: center; padding: 10px; }

/* --- la barra, pinned (punch-list 1)
   The cocina covers the room, so the counter comes INTO the cocina: the panel
   becomes a flex column and this band stays across its bottom while the dish
   grid scrolls behind it — ref-loop §2.9's sideboard strip, the copy-outright
   feature. Display only; serving stays a tap on the food in the room. */
.panel-cook-frame {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 14px 0 0;
}
.panel-cook-frame .panel-head { padding: 0 14px; }
.cook-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 14px 12px;
}
.sideboard {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px 10px;
  border-top: 2px solid var(--line);
  background: linear-gradient(180deg, #2c1d12, #241811);
}
.sideboard-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  flex: 0 0 auto;
}
.sideboard-items {
  display: flex;
  align-items: center;
  gap: 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.sideboard-item {
  position: relative;
  flex: 0 0 auto;
  width: 48px;
  height: 40px;
  border-radius: 8px;
  border: 2px solid var(--line);
  background-color: #e3d8c2; /* the same pale card the dish bakes expect */
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}
.sideboard-badge {
  position: absolute;
  right: -6px;
  bottom: -6px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: #2a1c13;
  border: 1.5px solid #e8dcc8;
  color: #f2e6d0;
  font-size: 10.5px;
  font-weight: 800;
  line-height: 14px;
  text-align: center;
  box-sizing: border-box;
}
.sideboard-empty { font-size: 11.5px; color: var(--ink-faint); font-style: italic; padding: 8px 0; }

/* --- generic list rows (menu / people / shop) */
.list { display: flex; flex-direction: column; gap: 8px; }
.row {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: #241811;
}
.row.is-locked { opacity: .45; }
.row.is-owned { border-color: var(--accent-2); }
.row-icon {
  width: 40px; height: 40px; border-radius: 8px;
  background: linear-gradient(#6b4a2f, #3d2a1a);
  border: 1px solid #2b1c12;
}
/**
 * FOOD-ART. The recetario's dish cell is a PALE tile, like the cook grid's and
 * like the reference's list cells. `.row-icon`'s dark gradient is a `background`
 * shorthand, so it was silently overriding `.dish-icon`'s `background-color`
 * and every one of the thirty recipes was sitting in a brown hole — the exact
 * failure the cook grid was just fixed for, one panel over.
 */
/**
 * …and the same cascade fault one line up: `.recipe-row` sets its three grid
 * columns at line 282, `.row` re-sets `40px 1fr auto` at line 317, equal
 * specificity, later wins. So the recipe rows have been laying out on a 40px
 * icon column this whole time and a wider icon just overflowed into the dish
 * name. Both overrides now sit on a two-class selector, which cannot be beaten
 * by a single-class rule wherever it lands in the file.
 */
.row.recipe-row { grid-template-columns: 84px 1fr auto; align-items: flex-start; }
.row.recipe-row .dish-icon {
  /**
   * ROUND-4 BUG, AND IT HALVED EVERY DISH IN THE RECETARIO.
   *
   * `.dish-icon` declares `width: 74px; height: 50px` at line 285. `.row-icon`
   * declares `width: 40px; height: 40px` at line 329. Both classes are on the
   * same element, equal specificity, so the LATER rule won and all thirty
   * recipe icons were rendering in a 40 × 40 square — not the 74 × 50 the
   * comment three lines above `.dish-icon` explains at length that they need,
   * and a square cell letterboxing a 1.36 : 1 sprite on top of that. Measured
   * result: 74.3% of the tile interior was one flat colour. The size belongs on
   * the winning rule.
   */
  /* Same trim, same arithmetic: 78 × 58 is 1.34 : 1 against art at ~1.9 : 1. */
  width: 84px; height: 50px;
  background: #e3d8c2 center/contain no-repeat;
  border: 1px solid #9c7d55;
  border-radius: 8px;
}
.row-main { font-size: 14px; font-weight: 700; }
.row-side { font-size: 12px; color: var(--ink-dim); }
.empty { font-size: 13px; color: var(--ink-faint); text-align: center; padding: 28px 10px; }

/* ------------------------------------------------------------------ NAV --- */

/* UI SWEEP (2026-08-15), rubric 9 + 10. The reference's nav is five painted
   objects standing in the room on small cool pedestal tabs — no bar of glyphs.
   Warm wood ground (their nav measures #6a5947 h31 s20% l35%), a painted
   vignette per tab that rises above the nav's top edge into the play area,
   and the label on a slate pedestal beneath it. */
.nav {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: stretch;
  background: linear-gradient(#6d5b47, #4e4034);
  border-top: 2px solid #43362a;
  z-index: 3;
}
.nav-btn {
  appearance: none;
  border: 0;
  background: none;
  color: #f2efe6;
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
  padding: 0 2px 9px;
  touch-action: manipulation;
  transition: transform .06s ease, filter .08s ease;
  /* the icon leans out of the bar into the room */
  overflow: visible;
}
.nav-icon {
  /* PUNCH-LIST 3: +4px, and the resting dim (saturate .92 brightness .94) is
     GONE — the nav is in every frame of the game, so a resting tax on its
     paint taxed every screenshot. The bitmap itself carries the lift now
     (navicons.js bake pass); rest state shows it straight. */
  width: 52px;
  height: 48px;
  margin-top: -18px;
  background: center / contain no-repeat;
  filter: drop-shadow(0 2px 1px rgba(20, 12, 6, .35));
  transition: filter .08s ease, transform .08s ease;
}
.nav-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .03em;
  padding: 2px 9px 3px;
  border-radius: 6px 6px 3px 3px;
  background: linear-gradient(#3d4747, #2e3737);
  border: 1px solid #262e2e;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
  box-shadow: 0 2px 0 rgba(0, 0, 0, .3);
}
.nav-btn.is-pressed { transform: translateY(2px); }
.nav-btn.is-active .nav-icon {
  filter: drop-shadow(0 2px 2px rgba(20, 12, 6, .45)) saturate(1.08) brightness(1.08);
  transform: translateY(-2px) scale(1.06);
}
.nav-btn.is-active .nav-label {
  color: var(--gold);
  background: linear-gradient(#454d4d, #343b3b);
}
/* "Compostura" is the one BIBLE §7 label that outruns its pedestal — it
   keeps the word and drops a point rather than getting a nickname. */
#nav-shop .nav-label { font-size: 9.5px; letter-spacing: 0; padding-inline: 6px; }

/* --- the speaker marker (punch-list 2)
   While a turn is active, this floats over whoever is saying it — the
   exchange strip keeps the words, the room shows the face. Same cream and
   ink as the exchange chrome so it reads as conversation furniture, with a
   slow bob that dies under prefers-reduced-motion. */
.speaker-marker {
  position: absolute;
  z-index: 4;
  pointer-events: none;
  width: 0;
  height: 0;
  transform: translateX(-50%);
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 13px solid #f2e7d0;
  filter: drop-shadow(0 0 1px #6b5334) drop-shadow(0 2px 0 rgba(20, 12, 6, .35));
  animation: marker-bob 1.15s ease-in-out infinite;
}
.speaker-marker[hidden] { display: none; }
@keyframes marker-bob {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -6px; }
}
@media (prefers-reduced-motion: reduce) {
  .speaker-marker { animation: none; }
}

/* --- the serve in flight (punch-list 8) */
.serve-flight {
  position: absolute;
  z-index: 3;
  width: 44px;
  height: 36px;
  margin: -18px 0 0 -22px;
  pointer-events: none;
  background: center / contain no-repeat;
  filter: drop-shadow(0 4px 2px rgba(20, 12, 6, .38));
}
.serve-flight[hidden] { display: none; }

/* -------------------------------------------------------------- OVERLAY --- */

.overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  align-items: end;
  background: rgba(10,6,4,.55);
  padding: 16px;
}
.overlay[hidden] { display: none; }

/* --- STORY-BEATS: the exchange -------------------------------------------
   The reference's dialogue mode discards its room for a grey panel eating
   55% of the screen (REFERENCE "How to beat it" §1). Ours: NO backdrop, no
   dim — the fonda stays lit and alive — and one low strip holding exactly
   one turn, replaced on tap, never re-printed. The strip clears the nav
   (78px) and stays inside the thumb's reach. */
.overlay[data-modal="dialogue"] {
  background: none;
  padding: 0 10px 88px;
}
.exchange {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 10px;
  align-items: center;
  padding: 10px 12px 8px;
  border-radius: 14px;
  border: 2px solid #6b5334;
  background: #f2e7d0;
  color: #2b1c12;
  box-shadow: 0 6px 0 rgba(20, 12, 6, .35);
}
.exchange-portrait {
  width: 64px;
  height: 64px;
  border-radius: 12px;
  border: 2px solid #6b5334;
  background: #e2cfa8 center 18% / 150% no-repeat;
  overflow: hidden;
}
.exchange-speaker {
  font-size: 12px;
  font-weight: 800;
  color: #7a4a22;
  margin-bottom: 2px;
}
.exchange-text {
  font-size: 14px;
  line-height: 1.35;
  min-height: 38px;
}
/* A line of business — something done rather than said. */
.exchange-is-action { grid-template-columns: 1fr; }
.exchange-action {
  font-size: 13px;
  font-style: italic;
  color: #5a4530;
  text-align: center;
  padding: 10px 6px;
  min-height: 38px;
  display: grid;
  align-items: center;
}
.exchange-foot {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 2px;
}
.exchange-count {
  font-size: 10px;
  color: #8a6a4a;
  letter-spacing: .06em;
}
.exchange-skip {
  appearance: none;
  border: 1.5px solid #8a6a4a;
  border-radius: 999px;
  background: none;
  color: #7a4a22;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  padding: 4px 14px;
  touch-action: manipulation;
}
.exchange-skip.is-pressed { background: rgba(122, 74, 34, .12); }

/* --- STORY-BEATS: la clientela -------------------------------------------- */
/* Doubled selector on purpose: the art system injects a `.row-icon` rule
   (the crates thumb) AFTER this sheet, and a regular whose bust has not been
   painted yet must show plain warm ground, not a soda crate for a face.
   Painted portraits arrive as inline styles and win over both. */
.row-icon.people-icon {
  background: #e2cfa8 center 18% / 150% no-repeat;
  border: 1.5px solid #6b5334;
}
.people-name { font-weight: 800; font-size: 14px; }
.people-line { font-size: 11px; opacity: .75; margin: 2px 0; }
.people-order { font-size: 11px; color: #d8a05c; }
.people-side { text-align: right; }
.people-visits { font-size: 11px; opacity: .7; }
.people-conf { font-size: 11px; color: #d8a05c; margin-top: 2px; }

.dayend {
  align-self: center;
  margin: auto;
  width: 100%;
  padding: 20px;
  border-radius: 16px;
  border: 2px solid var(--line);
  background: #241811;
  text-align: center;
  animation: card-in .16s ease-out;
}
@keyframes card-in {
  from { opacity: 0; transform: scale(.96) translateY(6px); }
  to   { opacity: 1; transform: none; }
}
/* Each dialogue turn lands with a breath, not a blink — 90ms, fade only. */
.exchange-text { animation: text-in .09s ease-out; }
@keyframes text-in { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .panel:not([hidden]):not(.panel-transparent),
  .toast:not([hidden]),
  .dayend,
  .exchange-text { animation: none; }
}
.dayend-title { font-size: 20px; margin-bottom: 12px; }
.dayend-row { font-size: 14px; color: var(--ink-dim); margin: 4px 0; }
/* The two forward-looking lines: what the tin is for, and the next rung.
   Warm, separated from tonight's arithmetic by a hairline. */
.dayend-goal {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid #3a2a1c;
  color: #d8a05c;
}
.dayend-cartel { font-size: 12px; color: #b0885c; }
/* Día de norte: the weather's one line on the card — cool against the warm
   goal lines, because the wind is the thing the till lost money to. */
.dayend-norte { font-style: italic; color: #8fa3a0; }

/* ---------------------------------------------------------- COMPOSTURA --- */

/* The head becomes a two-column grid so the tin sits on the right of the
   title/sub pair without disturbing the other panels' plain heads. */
#panel-shop .panel-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
}
#panel-shop .panel-title, #panel-shop .panel-sub { grid-column: 1; }
.shop-bote {
  grid-column: 2;
  grid-row: 1 / span 2;
  font-size: 12px;
  font-weight: 800;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.row.shop-row { grid-template-columns: 1fr auto; align-items: flex-start; }
.shop-name { font-weight: 800; font-size: 14px; }
.shop-line { font-size: 11px; font-weight: 400; opacity: .75; margin: 3px 0 2px; line-height: 1.35; }
.shop-effect { font-size: 11px; font-weight: 600; color: #d8a05c; }
.shop-side { text-align: right; }
.shop-owned { font-size: 12px; color: var(--accent-2); font-weight: 700; }
.shop-cost { font-size: 13px; font-weight: 800; color: var(--ink); }
.shop-progress { font-size: 11px; color: #d8a05c; margin-top: 2px; }
.btn.shop-buy {
  margin-top: 0;
  padding: 8px 12px;
  font-size: 12px;
  background: var(--accent);
  border-color: #8f4520;
  color: #241811;
  white-space: nowrap;
}

.btn {
  appearance: none;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--bg-raised);
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  padding: 12px 18px;
  margin-top: 16px;
  touch-action: manipulation;
}
.btn-primary { background: var(--accent); border-color: #8f4520; color: #241811; }
.btn.is-pressed { transform: translateY(2px); filter: brightness(1.1); }
