/* ============================================================
   LOVECRAFTIAN HORROR — The Gathering
   A 1920s seance in CSS: near-black greens & browns, candlelight
   amber, doom red, parchment text. No external resources.
   ============================================================ */

:root {
  /* palette */
  --abyss: #050706;
  --pit: #0a0d0a;
  --panel: #10130e;
  --panel-2: #171410;
  --leather: #1d1712;
  --edge: #34291a;
  --edge-lit: #5c4426;
  --parchment: #d9c9a3;
  --parchment-dim: #9a8d6f;
  --parchment-faint: #6f6650;
  --candle: #e0a244;
  --candle-hot: #ffd894;
  --blood: #b23327;
  --blood-deep: #6e1712;
  --doomglow: #ff5b41;
  --moss: #45604d;
  --sickly: #7da26b;
  --clue: #c9a53a;

  /* skills (Arkham convention) */
  --sk-willpower: #4a7aa8;
  --sk-intellect: #c08a2e;
  --sk-combat: #a83c2c;
  --sk-agility: #5d8a4a;
  --sk-wild: #8a6fb0;

  /* type */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", "URW Palladio L", Georgia, serif;

  /* texture */
  --grain-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

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

html, body { height: 100%; }

body {
  background: var(--abyss);
  color: var(--parchment);
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.45;
  overflow: hidden;
}

img { display: block; max-width: 100%; }
button { font-family: inherit; color: inherit; background: none; border: none; cursor: pointer; }
button:disabled { cursor: not-allowed; }

::selection { background: rgba(224, 162, 68, .35); }

/* scrollbars in theme */
* { scrollbar-width: thin; scrollbar-color: var(--edge) transparent; }
*::-webkit-scrollbar { width: 8px; }
*::-webkit-scrollbar-thumb { background: var(--edge); border-radius: 4px; }

/* ---------- atmosphere layers ---------- */

.grain {
  position: fixed; inset: -60px;
  background-image: var(--grain-img);
  opacity: .08;
  pointer-events: none;
  z-index: 400;
  mix-blend-mode: overlay;
  animation: grain-shift 1.4s steps(3) infinite;
}

@keyframes grain-shift {
  0% { transform: translate(0, 0); }
  33% { transform: translate(-14px, 9px); }
  66% { transform: translate(11px, -16px); }
  100% { transform: translate(0, 0); }
}

.vignette {
  position: fixed; inset: 0;
  background: radial-gradient(ellipse 90% 80% at 50% 42%, transparent 45%, rgba(0, 0, 0, .55) 82%, rgba(0, 0, 0, .88) 100%);
  pointer-events: none;
  z-index: 90;
}

/* ---------- shared bits ---------- */

.btn {
  font-family: var(--serif);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--parchment);
  background: linear-gradient(175deg, #241d13, #14100a);
  border: 1px solid var(--edge);
  border-radius: 3px;
  padding: 7px 14px;
  transition: border-color .18s, box-shadow .18s, transform .12s, color .18s;
  text-transform: uppercase;
}
.btn:hover:not(:disabled) {
  border-color: var(--edge-lit);
  color: var(--candle-hot);
  box-shadow: 0 0 14px rgba(224, 162, 68, .18), inset 0 0 8px rgba(224, 162, 68, .08);
}
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .38; }

.btn-gold {
  color: #1a1105;
  background: linear-gradient(175deg, var(--candle-hot), var(--candle) 55%, #a8722a);
  border-color: #8a5f22;
  font-weight: 700;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.btn-gold:hover:not(:disabled) {
  color: #000;
  box-shadow: 0 0 22px rgba(224, 162, 68, .45);
  border-color: var(--candle-hot);
}

.btn-ghost { background: transparent; border-color: #2a241a; color: var(--parchment-dim); }
.btn-ghost:hover:not(:disabled) { color: var(--parchment); }

.chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 10px;
  border: 1px solid var(--edge);
  background: rgba(8, 10, 8, .82);
  color: var(--parchment-dim);
  white-space: nowrap;
}
.chip-clue { color: var(--clue); border-color: #58471a; }
.chip-clue.empty { color: var(--parchment-faint); border-color: var(--edge); }
.chip-shroud { color: #9db3c9; border-color: #29394a; }
/* C7 ASK 1: doom sitting on the location itself (02205's flipped clue tokens) */
.chip-doom { color: var(--doomglow); border-color: #6b2418; }
/* C11 ASK 1: horror sitting on the location itself (Curtain Call's spreading
   flames/ooze/flood). Deliberately the HORROR palette (.chip-hor's violet), not
   doom's ember — it counts toward no clock and must not read as agenda pressure. */
.chip-horror { color: #b79ad1; border-color: #3d2c52; }
.chip-veiled { color: var(--parchment-faint); font-style: italic; }
.chip-res { color: var(--candle); border-color: #58471a; }
.chip-use { color: #b8c9a0; border-color: #35452a; }
.chip-dmg { color: var(--doomglow); border-color: var(--blood-deep); }
.chip-hor { color: #b79ad1; border-color: #3d2c52; }
.chip-acts { border: none; background: none; padding: 0 4px; }

.tag {
  display: inline-block;
  font-size: 9.5px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 2px;
}
.tag-engaged { color: #ffd9cf; background: var(--blood-deep); box-shadow: 0 0 10px rgba(178, 51, 39, .5); }
.tag-massive { color: #e8d5ff; background: #2c1b3d; box-shadow: 0 0 12px rgba(120, 60, 190, .55); }
.tag-other { color: var(--parchment-dim); background: #241d15; }
.tag-exhausted { color: #8f8f8f; background: #1b1b1b; }
.tag-ally { color: #d8ecc8; background: #2a3d24; }

.pip {
  display: inline-block; width: 9px; height: 9px;
  border-radius: 50%;
  border: 1px solid var(--edge-lit);
  background: #241d13;
  margin-right: 2px;
}
.pip.hp { border-color: #6e2a20; background: #7e3226; box-shadow: inset 0 0 3px rgba(0,0,0,.6); }
.pip.hp.spent { background: #17100d; border-color: #33201a; }
.pip.san { border-color: #3d3560; background: #4c4380; }
.pip.san.spent { background: #12101c; border-color: #262040; }
.pip.hit { background: var(--blood); border-color: var(--doomglow); box-shadow: 0 0 5px rgba(255, 91, 65, .6); }
.pip.candle { width: 8px; height: 12px; border-radius: 40% 40% 30% 30%; background: #1c160d; }
.pip.candle.lit {
  background: linear-gradient(var(--candle-hot), var(--candle));
  border-color: var(--candle);
  box-shadow: 0 0 8px rgba(224, 162, 68, .8);
  animation: candle-pip 2.2s ease-in-out infinite;
}
@keyframes candle-pip { 0%,100% { box-shadow: 0 0 6px rgba(224,162,68,.7);} 50% { box-shadow: 0 0 11px rgba(255,216,148,.9);} }

.zone-label {
  display: block;
  font-size: 10px; letter-spacing: .24em; text-transform: uppercase;
  color: var(--parchment-faint);
  margin-bottom: 4px;
}
.zone-label.danger { color: #a8564a; }

.empty-note { color: var(--parchment-faint); font-style: italic; font-size: 12.5px; list-style: none; }

kbd {
  font-family: var(--serif);
  font-size: 10px;
  color: var(--parchment-faint);
  border: 1px solid var(--edge);
  border-radius: 3px;
  padding: 0 4px;
}

/* ============================================================
   LANDING
   ============================================================ */

#landing {
  position: fixed; inset: 0; z-index: 500;
  display: grid; place-items: center;
  background:
    radial-gradient(ellipse 70% 55% at 50% 38%, rgba(224, 162, 68, .07), transparent 65%),
    radial-gradient(ellipse 120% 100% at 50% 110%, #0d0a06, transparent 60%),
    var(--abyss);
  overflow-y: auto;
  transition: opacity 1.1s ease, visibility 1.1s;
}
#landing.gone { opacity: 0; visibility: hidden; pointer-events: none; }

.landing-inner {
  text-align: center;
  padding: 40px 24px;
  max-width: 860px;
  animation: fade-up 1.4s ease both;
}

.landing-kicker, .end-kicker {
  font-size: 12px; letter-spacing: .5em; text-transform: uppercase;
  color: var(--parchment-faint);
  margin-bottom: 18px;
}

.landing-title {
  font-size: clamp(44px, 7vw, 76px);
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1.02;
  text-shadow: 0 0 40px rgba(224, 162, 68, .25), 0 4px 18px rgba(0, 0, 0, .9);
}
.landing-title span {
  display: block;
  color: var(--candle);
  letter-spacing: .34em;
  text-shadow: 0 0 34px rgba(224, 162, 68, .5);
}

.landing-sub {
  font-size: 21px; font-style: italic;
  color: var(--parchment-dim);
  margin-top: 14px;
}
.landing-sub::before, .landing-sub::after { content: " ✦ "; color: var(--edge-lit); font-style: normal; font-size: 13px; }

.landing-date { font-size: 12.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--parchment-faint); margin-top: 8px; }

.landing-body {
  display: flex; align-items: center; justify-content: center; gap: 48px;
  margin: 36px 0 26px;
  flex-wrap: wrap;
}

.landing-card {
  width: 190px;
  transform: rotate(-4deg);
  transition: transform .5s ease;
  filter: drop-shadow(0 14px 28px rgba(0, 0, 0, .85));
}
.landing-card:hover { transform: rotate(-1deg) scale(1.04); }
.landing-card img { border-radius: 9px; border: 1px solid var(--edge); }
.landing-card figcaption { font-size: 11.5px; font-style: italic; color: var(--parchment-dim); margin-top: 10px; }

.landing-form {
  text-align: left;
  background: linear-gradient(170deg, var(--leather), #120e0a);
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: 24px 28px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .8), inset 0 0 44px rgba(0, 0, 0, .5);
  min-width: 300px;
}

.difficulty { border: none; margin-bottom: 16px; }
.difficulty legend {
  font-size: 11px; letter-spacing: .24em; text-transform: uppercase;
  color: var(--parchment-faint);
  margin-bottom: 8px;
}
.diff-opt { display: inline-block; margin-right: 4px; }
/* display:inline-block would beat the hidden attr — the campaign picker hides
   the other campaign's scenario pills this way (same trap as .import-form). */
.diff-opt[hidden] { display: none; }
.diff-opt input { position: absolute; opacity: 0; }
.diff-opt span {
  display: inline-block;
  font-size: 12.5px; text-transform: capitalize;
  padding: 5px 12px;
  border: 1px solid var(--edge);
  border-radius: 3px;
  color: var(--parchment-dim);
  cursor: pointer;
  transition: all .18s;
}
.diff-opt input:checked + span {
  color: #150e04;
  background: linear-gradient(var(--candle-hot), var(--candle));
  border-color: var(--candle);
  box-shadow: 0 0 12px rgba(224, 162, 68, .4);
}
.diff-opt input:focus-visible + span { outline: 1px solid var(--candle-hot); }

/* The Interlude screen (C4 §4) — a campaign beat with no Game behind it:
   prose from the interlude's own resolve(), any choices it declares, Continue. */
.interlude-body {
  max-width: 560px;
  margin: 24px auto 0;
  text-align: left;
}
.interlude-line {
  font-family: var(--serif);
  font-size: 15px; line-height: 1.7;
  color: var(--parchment-dim);
  margin: 0 0 14px;
}
.interlude-choice { margin-top: 22px; }
.interlude-choice legend {
  text-transform: none; letter-spacing: .04em; font-size: 12.5px;
  color: var(--parchment-faint);
}
.interlude-choice .diff-opt span { text-transform: none; }
.interlude-body .btn-begin { margin-top: 26px; }

/* The Prologue's paraphrased setup, under the Dunwich lead picker (C4 §0.2). */
.prologue-note {
  margin: 10px 0 0;
  font-style: italic; font-size: 12.5px; line-height: 1.5;
  color: var(--parchment-dim);
}
.prologue-note[hidden] { display: none; }

.seed-row { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.seed-row span { font-size: 11px; letter-spacing: .24em; text-transform: uppercase; color: var(--parchment-faint); }
.seed-row input {
  flex: 1;
  font-family: var(--serif); font-size: 14px;
  color: var(--candle);
  background: #0a0805;
  border: 1px solid var(--edge);
  border-radius: 3px;
  padding: 6px 10px;
}
.seed-row input:focus { outline: none; border-color: var(--edge-lit); }

.btn-begin { width: 100%; padding: 12px; font-size: 15px; letter-spacing: .14em; }

.landing-flavor {
  max-width: 560px; margin: 0 auto;
  font-style: italic; font-size: 14px;
  color: var(--parchment-dim);
}

.landing-error { color: var(--doomglow); margin-top: 24px; }

@keyframes fade-up { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

/* ============================================================
   APP FRAME
   ============================================================ */

.app {
  display: grid;
  /* HUD and footer rows size to their content (min floors keep the frame from
     collapsing before JS renders); ONLY the middle viewport row absorbs the
     difference. A fixed 58px HUD used to clip its ~103px of content — agenda
     art, doom/clue badges, attached chips — against body overflow:hidden.
     The footer row is CLAMPED (--invpanel-max, drag the #panel-divider to
     change it): an asset-heavy board used to grow the footer unbounded and
     crush the stage to nothing; past the clamp the board zone scrolls. */
  grid-template-rows: minmax(84px, auto) minmax(0, 1fr) auto minmax(240px, min(var(--invpanel-max, 44vh), 78vh));
  height: 100vh;
}

/* ---------- stage/panel divider (drag to resize, dblclick to reset) ---------- */

#panel-divider {
  height: 8px;
  cursor: row-resize;
  touch-action: none;
  position: relative;
  z-index: 31; /* above #invpanel (30) so the grab strip always wins the hit test */
  background: linear-gradient(180deg, rgba(0, 0, 0, .35), rgba(0, 0, 0, 0));
}
#panel-divider::after {
  /* grip: a short candle-lit bar, centered */
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 56px; height: 3px;
  border-radius: 2px;
  background: var(--edge);
  transition: background .2s, box-shadow .2s;
}
#panel-divider:hover::after,
#panel-divider.dragging::after {
  background: var(--candle);
  box-shadow: 0 0 10px rgba(224, 162, 68, .45);
}

.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  min-height: 0;
}

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

#hud {
  display: flex; align-items: center; gap: 22px;
  /* vertical padding gives the .hud-stat badges (top:-7px overhang) legal room */
  padding: 10px 18px;
  background: linear-gradient(180deg, #121009, #0b0906);
  border-bottom: 1px solid var(--edge);
  z-index: 20;
}

.hud-left { display: flex; flex-direction: column; min-width: 150px; }
.hud-brand { font-size: 15px; letter-spacing: .22em; text-transform: uppercase; color: var(--candle); }
/* .hud-left is a COLUMN, so the note needs its own row box to sit beside the
   title — as a direct child it would stretch to the column's full width and
   render as a bar under the name rather than a chip next to it. */
.hud-title-row { display: flex; align-items: baseline; gap: 8px; }
/* Optional scenario-supplied note beside the title — C4's either-order pair
   uses it to say which half of the pair you are in (hover for what differs). */
.hud-note {
  padding: 1px 6px;
  font-size: 9px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--parchment-faint);
  border: 1px solid var(--edge);
  border-radius: 2px;
  cursor: help;
}
.hud-round { font-size: 11px; font-style: italic; color: var(--parchment-faint); }

.phases {
  display: flex; gap: 4px; list-style: none;
  margin-right: auto;
}
.phase {
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--parchment-faint);
  padding: 4px 12px;
  border: 1px solid transparent;
  border-radius: 2px;
  position: relative;
}
.phase:not(:last-child)::after { content: "·"; position: absolute; right: -6px; color: var(--edge-lit); }
.phase.on {
  color: var(--candle-hot);
  border-color: var(--edge-lit);
  background: rgba(224, 162, 68, .08);
  box-shadow: 0 0 12px rgba(224, 162, 68, .12);
}

.hud-right { display: flex; align-items: center; gap: 14px; }

/* An agenda/act card plus anything attached to it (C4 §2.2b — Light of
   Aforgomon). The chips used to be absolutely positioned because the HUD row
   was a fixed 58px track; now that the row is minmax(84px, auto) they sit in
   normal flow and simply grow the row. */
.hud-stack { position: relative; display: flex; flex-direction: column; align-items: center; }
.hud-attached {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  margin-top: 2px;
}
.hud-attach-chip {
  display: flex; align-items: center; gap: 4px;
  max-width: 78px;
  padding: 1px 4px;
  background: var(--blood-deep);
  border: 1px solid var(--blood);
  border-radius: 3px;
  cursor: pointer;
}
.hud-attach-chip img { width: 12px; height: 12px; object-fit: cover; border-radius: 2px; }
.hud-attach-chip span {
  font-size: 8px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--parchment-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hud-attach-chip:hover { background: var(--blood); }
.hud-attach-chip:hover span { color: var(--parchment); }

.hud-card {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding: 2px;
}
.hud-card img {
  /* landscape agenda/act art is ~7:5 — contain shows the WHOLE card (cover at
     74x42 sliced ~21% off) */
  width: 92px; height: 66px;
  object-fit: contain; object-position: center;
  border: 1px solid var(--edge);
  border-radius: 3px;
  background: #000;
  filter: brightness(.85);
  transition: filter .2s;
}
.hud-card:hover img { filter: brightness(1.05); }
.hud-card label { font-size: 8.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--parchment-faint); margin-top: 3px; cursor: pointer; }
.hud-card.ghost { width: 92px; height: 83px; justify-content: center; border: 1px dashed var(--edge); border-radius: 3px; }

.hud-stat {
  position: absolute; top: -7px; right: -9px;
  font-size: 12px; font-weight: 700;
  padding: 1px 7px;
  border-radius: 9px;
  border: 1px solid;
}
.hud-stat i { font-style: normal; font-size: 9.5px; opacity: .75; }
.hud-stat.doom { color: #ffd0c6; background: var(--blood-deep); border-color: var(--blood); }
.hud-stat.doom.pulse { animation: doom-pulse 1.6s ease-in-out infinite; }
.hud-stat.clue { color: #1c1503; background: var(--clue); border-color: #8a6f1e; }
@keyframes doom-pulse {
  0%, 100% { box-shadow: 0 0 4px rgba(178, 51, 39, .5); }
  50% { box-shadow: 0 0 16px rgba(255, 91, 65, .9); }
}

.hud-pile { text-align: center; }
.hud-pile b { display: block; font-size: 17px; color: var(--parchment); }
.hud-pile.bag b { color: var(--sickly); }
.hud-pile label { font-size: 8.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--parchment-faint); }

.hud-map { padding: 2px 6px; border: 1px solid transparent; border-radius: 4px; transition: border-color .2s; }
.hud-map label { cursor: pointer; }
.hud-map:hover b, .hud-map.on b { color: var(--candle); }
.hud-map.on { border-color: var(--edge-lit); background: rgba(224, 162, 68, .07); }

/* ============================================================
   FIRST-PERSON VIEWPORT
   ============================================================ */

#viewport {
  position: relative;
  overflow: hidden;
  background: var(--abyss);
}

.void-room {
  height: 100%;
  display: grid; place-items: center;
  font-style: italic;
  color: var(--parchment-faint);
}

/* full-bleed blurred card art = the room */
.backdrop { position: absolute; inset: 0; }
.backdrop img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: blur(22px) brightness(.42) saturate(.72);
  transform: scale(1.18);
}
.backdrop::after {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 80% 70% at 50% 45%, transparent 30%, rgba(3, 4, 3, .82) 100%),
    linear-gradient(180deg, rgba(3, 4, 3, .55), transparent 30%, transparent 62%, rgba(3, 4, 3, .88));
}

/* approved full-screen location art (assets/art/locations/<code>.png, slotted
   from art-direction/) — shown SHARP instead of the blurred card art, only on
   revealed locations. The inherited ::after gradient plus a slightly heavier
   dim keep the banner, chips, flavor ribbon and the card window readable. */
.backdrop.location-art img {
  filter: brightness(.58) saturate(.88);
  transform: none;
}
.backdrop.location-art::after {
  background:
    radial-gradient(ellipse 85% 75% at 50% 45%, transparent 35%, rgba(3, 4, 3, .78) 100%),
    linear-gradient(180deg, rgba(3, 4, 3, .62), rgba(3, 4, 3, .18) 30%, rgba(3, 4, 3, .18) 60%, rgba(3, 4, 3, .9));
}

/* candlelight breathing over the whole room */
.candlelight {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 55% 50% at 48% 72%, rgba(224, 162, 68, .16), transparent 70%);
  mix-blend-mode: soft-light;
  animation: flicker 4.7s ease-in-out infinite;
  pointer-events: none;
}
.candlelight.two {
  background: radial-gradient(ellipse 35% 40% at 62% 30%, rgba(255, 216, 148, .10), transparent 70%);
  animation: flicker 3.1s ease-in-out infinite reverse;
}
@keyframes flicker {
  0%, 100% { opacity: .75; }
  8% { opacity: .95; }
  22% { opacity: .7; }
  36% { opacity: 1; }
  54% { opacity: .8; }
  71% { opacity: .98; }
  86% { opacity: .68; }
}

/* the sharp "vision" — an arched window onto the location card art */
.vision {
  position: absolute;
  left: 50%; top: 51%;
  transform: translate(-50%, -50%);
  width: clamp(280px, 26vw, 420px);
  height: 74%;
  border-radius: 200px 200px 10px 10px;
  overflow: hidden;
  border: 1px solid var(--edge-lit);
  outline: 6px solid rgba(10, 8, 5, .85);
  outline-offset: 4px;
  box-shadow:
    0 0 0 5px rgba(52, 41, 26, .55),
    0 30px 80px rgba(0, 0, 0, .85),
    inset 0 0 90px rgba(0, 0, 0, .8);
  cursor: zoom-in;
  transition: box-shadow .35s;
  padding: 0;
}
.vision:hover {
  box-shadow:
    0 0 0 5px rgba(92, 68, 38, .8),
    0 0 60px rgba(224, 162, 68, .18),
    0 30px 80px rgba(0, 0, 0, .85),
    inset 0 0 70px rgba(0, 0, 0, .72);
}
.vision img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
}
.vision::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: radial-gradient(ellipse 90% 90% at 50% 40%, transparent 55%, rgba(0, 0, 0, .55) 100%);
  pointer-events: none;
}

/* location name & chips */
.loc-banner {
  position: absolute; top: 22px; left: 26px;
  z-index: 5;
  max-width: 34%;
}
.loc-banner h1 {
  font-size: clamp(24px, 2.6vw, 38px);
  font-weight: 400;
  letter-spacing: .1em;
  color: var(--parchment);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .95), 0 0 34px rgba(0, 0, 0, .8);
  border-bottom: 1px solid rgba(92, 68, 38, .6);
  padding-bottom: 6px;
  margin-bottom: 8px;
}
.loc-chips { display: flex; gap: 6px; flex-wrap: wrap; }

/* flavor text ribbon */
.flavor-ribbon {
  position: absolute; left: 26px; bottom: 148px;
  z-index: 5;
  max-width: 30%;
  font-style: italic;
  font-size: 14.5px;
  color: var(--parchment-dim);
  background: linear-gradient(90deg, rgba(8, 7, 4, .88), rgba(8, 7, 4, .55));
  border-left: 2px solid var(--edge-lit);
  padding: 12px 16px;
  border-radius: 0 4px 4px 0;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .9);
}
.flavor-ribbon i { color: var(--parchment-dim); }

/* figures standing in the room (enemies + story allies) */
.figures {
  position: absolute;
  right: 22px; top: 162px; bottom: 140px; /* clears the corner mini-map */
  z-index: 6;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 14px;
  max-width: 34%;
  flex-wrap: wrap-reverse;
}

.figure {
  position: relative;
  width: 150px;
  background: linear-gradient(180deg, rgba(14, 12, 8, .94), rgba(8, 7, 5, .96));
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: 5px 5px 8px;
  cursor: pointer;
  transition: transform .25s, border-color .25s, box-shadow .25s;
  animation: figure-in .6s ease both;
}
@keyframes figure-in { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: none; } }
.figure:hover { transform: translateY(-4px); border-color: var(--edge-lit); }

.figure-art {
  height: 108px;
  overflow: hidden;
  border-radius: 4px 4px 0 0;
  background: #0c0a07;
}
.figure-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 16%; }

.figure figcaption { padding: 6px 4px 0; display: flex; flex-direction: column; gap: 4px; }
.figure-name { font-size: 13.5px; letter-spacing: .04em; color: var(--parchment); }

.figure.foe.engaged {
  border-color: var(--blood);
  box-shadow: 0 0 18px rgba(178, 51, 39, .4), inset 0 0 12px rgba(178, 51, 39, .12);
}
.figure.foe.engaged .figure-art img { filter: saturate(1.1) contrast(1.05); }
.figure.foe.exhausted { transform: rotate(6deg); opacity: .62; filter: grayscale(.5); }
.figure.foe.exhausted:hover { transform: rotate(6deg) translateY(-3px); }
.figure.foe.selected { border-color: var(--candle); box-shadow: 0 0 20px rgba(224, 162, 68, .3); }
.figure.ally { border-color: #2f4527; }
.figure.ally:hover { box-shadow: 0 0 16px rgba(125, 162, 107, .25); }

.foe-stats { display: flex; gap: 5px; }
.st {
  font-size: 11px; font-weight: 700;
  padding: 1px 6px;
  border-radius: 2px;
  background: #14110c;
  border: 1px solid var(--edge);
}
.st-f { color: #d98d7c; }
.st-f::before { content: "FGT "; font-weight: 400; font-size: 8.5px; color: var(--parchment-faint); }
.st-h { color: #e6c88f; }
.st-h::before { content: "HP "; font-weight: 400; font-size: 8.5px; color: var(--parchment-faint); }
.st-e { color: #9dbb8b; }
.st-e::before { content: "EVA "; font-weight: 400; font-size: 8.5px; color: var(--parchment-faint); }

.foe-dmg { line-height: 1; }

.foe-menu {
  display: flex; gap: 5px; flex-wrap: wrap;
  padding: 7px 4px 2px;
  border-top: 1px solid var(--edge);
  margin-top: 6px;
  animation: fade-up .2s ease both;
}
.foe-act { font-size: 11px; padding: 5px 10px; flex: 1; }
.foe-act.act-fight:hover:not(:disabled) { border-color: var(--blood); color: #ffb3a6; box-shadow: 0 0 12px rgba(178, 51, 39, .35); }
.foe-act.act-evade:hover:not(:disabled) { border-color: var(--sickly); color: #cde7bd; }
.foe-wait { font-size: 11px; font-style: italic; color: var(--parchment-faint); }

/* exits — doorways along the bottom of the viewport */
.exits {
  position: absolute;
  left: 0; right: 0; bottom: 18px;
  z-index: 7;
  /* The doorway strip can overlap an expanded enemy card at short viewport
     heights.  Only real doors should win that hit test; the transparent nav
     between them must let Fight/Evade controls underneath receive the tap. */
  pointer-events: none;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 22px;
  padding: 0 20px;
}

.door {
  position: relative;
  pointer-events: auto;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  width: 118px;
  padding: 10px 8px 9px;
  background: linear-gradient(180deg, rgba(26, 20, 12, .92), rgba(10, 8, 5, .95));
  border: 1px solid var(--edge);
  border-radius: 60px 60px 5px 5px;
  color: var(--parchment);
  transition: transform .2s, border-color .2s, box-shadow .2s;
}
.door .door-arch {
  width: 34px; height: 44px;
  border-radius: 17px 17px 0 0;
  background:
    radial-gradient(ellipse 60% 45% at 50% 100%, rgba(224, 162, 68, .5), transparent 72%),
    linear-gradient(180deg, #050604, #0e0b07);
  border: 1px solid var(--edge);
  border-bottom-width: 2px;
  transition: box-shadow .2s, border-color .2s;
}
.door:hover:not(:disabled) {
  transform: translateY(-5px);
  border-color: var(--candle);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .7), 0 0 26px rgba(224, 162, 68, .22);
}
.door:hover:not(:disabled) .door-arch {
  border-color: var(--candle);
  box-shadow: inset 0 -12px 22px rgba(224, 162, 68, .4);
}
.door-name { font-size: 13px; letter-spacing: .08em; }
.door kbd { position: absolute; top: 7px; right: 9px; }
.door.locked { opacity: .55; filter: saturate(.4); }
.door-lock { position: absolute; top: 6px; right: 9px; color: var(--blood); font-size: 12px; }
.door-reason {
  font-size: 10px; font-style: italic;
  color: #b06a5c;
  max-width: 100%;
  line-height: 1.25;
}
.no-exit { font-style: italic; color: var(--parchment-faint); }

/* ---------- mini-map of the known house ---------- */

.minimap {
  position: absolute;
  top: 16px; right: 18px;
  background: rgba(6, 7, 5, .9);
  border: 1px solid var(--edge);
  border-radius: 6px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .65), inset 0 0 30px rgba(0, 0, 0, .5);
}
.minimap.mini {
  width: 176px; height: 132px;
  z-index: 9;
  opacity: .85;
  transition: opacity .2s, box-shadow .2s;
}
.minimap.mini:hover { opacity: 1; box-shadow: 0 10px 30px rgba(0, 0, 0, .65), 0 0 18px rgba(224, 162, 68, .12); }
.minimap.expanded {
  width: min(420px, 40vw);
  height: 330px;
  z-index: 40;
  border-color: var(--edge-lit);
  animation: sheet-in .25s ease both;
}
.map-title {
  position: absolute; top: 9px; left: 14px;
  font-size: 11px; font-weight: 400;
  letter-spacing: .3em; text-transform: uppercase;
  color: var(--parchment-dim);
  z-index: 2;
}
.map-canvas { position: absolute; inset: 6px; }
.minimap.expanded .map-canvas { inset: 34px 10px 10px; }
.map-canvas svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.map-canvas svg line {
  stroke: var(--edge-lit);
  stroke-width: 1.5px;
  stroke-dasharray: 4 3;
  opacity: .75;
}
.map-node {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 4px 9px;
  border-radius: 4px;
  background: linear-gradient(180deg, #1b160e, #0e0b07);
  border: 1px solid var(--edge);
  cursor: zoom-in;
  transition: border-color .15s, box-shadow .15s;
  max-width: 46%;
}
.map-node:hover { border-color: var(--candle); box-shadow: 0 0 12px rgba(224, 162, 68, .25); }
.map-node.veiled {
  background: #0b0b0e;
  border-style: dashed;
  color: var(--parchment-faint);
}
.map-node.here { border-color: var(--candle); box-shadow: 0 0 14px rgba(224, 162, 68, .4); }
.map-name {
  font-size: 11px; letter-spacing: .05em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 92px;
}
.minimap.mini .map-node { padding: 2px 6px; }
.minimap.mini .map-name { font-size: 8.5px; max-width: 56px; }
.map-dots { display: flex; gap: 2px; }
.dot { width: 5px; height: 5px; border-radius: 50%; display: inline-block; }
.dot-clue { background: var(--clue); box-shadow: 0 0 3px rgba(201, 165, 58, .8); }
.dot-foe { background: var(--blood); box-shadow: 0 0 4px rgba(178, 51, 39, .9); }
.map-you {
  font-size: 7.5px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase;
  color: #150e04;
  background: var(--candle);
  border-radius: 2px;
  padding: 0 4px;
}

/* ============================================================
   RIGHT RAIL — the chronicle (narrative log)
   ============================================================ */

#rail {
  display: flex; flex-direction: column;
  min-height: 0;
  background: linear-gradient(180deg, #0e0c08, #090806);
  border-left: 1px solid var(--edge);
  z-index: 15;
}

.rail-title {
  width: 100%;
  font-size: 12px; font-weight: 400;
  letter-spacing: .4em; text-transform: uppercase;
  color: var(--parchment-faint);
  text-align: center;
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--edge);
}
.rail-title::before, .rail-title::after { content: " — "; color: var(--edge-lit); }
.rail-toggle { display: none; }

#log {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px 18px;
  scroll-behavior: smooth;
}

.log-line {
  font-size: 13px;
  color: var(--parchment-dim);
  margin-bottom: 7px;
  animation: log-in .4s ease both;
}
@keyframes log-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }

.log-line.k-info { color: var(--parchment-dim); }
.log-line.k-warn { color: #c9a35c; }
.log-line.k-danger { color: #d4695a; }
.log-line.k-success { color: #93b479; }
.log-line.k-token { color: #b3a2cf; font-style: italic; }
.log-line.k-encounter { color: #b78bd1; }
.log-line.k-scenario {
  color: var(--parchment);
  font-style: italic;
  font-size: 14.5px;
  border-left: 2px solid var(--edge-lit);
  padding-left: 10px;
  margin: 12px 0;
}
.log-line.k-round {
  text-align: center;
  color: var(--candle);
  letter-spacing: .3em;
  text-transform: uppercase;
  font-size: 11px;
  border-top: 1px solid var(--edge);
  padding-top: 12px;
  margin-top: 14px;
}
.log-line.k-phase {
  color: var(--parchment-faint);
  letter-spacing: .2em;
  text-transform: uppercase;
  font-size: 10.5px;
  margin-top: 10px;
}
.log-line.k-turn { color: var(--candle-hot); font-style: italic; }

/* card references inside chronicle lines — hover previews, right-click inspects */
.cardref {
  border-bottom: 1px dotted rgba(224, 162, 68, .55);
  cursor: help;
  transition: color .15s, border-color .15s;
}
.cardref:hover {
  color: var(--candle-hot);
  border-bottom-color: var(--candle-hot);
}

/* ============================================================
   INVESTIGATOR PANEL (bottom)
   ============================================================ */

#invpanel {
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, #14110b, #0b0906 70%);
  border-top: 1px solid var(--edge);
  z-index: 30;
  /* hand cards zoom upward past the panel edge */
  overflow: visible;
}

.action-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 16px;
  border-bottom: 1px solid rgba(52, 41, 26, .5);
  min-height: 42px;
  flex-wrap: wrap;
}

.turn-status { font-size: 13px; font-style: italic; color: var(--parchment-faint); margin-right: 8px; }
.turn-status.live { color: var(--candle-hot); text-shadow: 0 0 12px rgba(224, 162, 68, .3); }

.act-btn { font-size: 12px; padding: 5px 12px; }
.act-btn.abil { border-color: #2e3a2a; color: #b8c9a0; text-transform: none; letter-spacing: .03em; }
.act-btn.abil:hover:not(:disabled) { border-color: var(--sickly); color: #d9ecc8; box-shadow: 0 0 12px rgba(125, 162, 107, .2); }

.btn-advance {
  animation: doom-pulse 2.4s ease-in-out infinite;
  letter-spacing: .1em;
}
.btn-end { margin-left: auto; }

.panel-body {
  flex: 1;
  display: grid;
  /* col 1 = portrait 150 + gap 12 + ~158 for the plaque's 9-pip health row */
  grid-template-columns: 320px minmax(0, 1fr) minmax(230px, 26%);
  /* the single row must be allowed to shrink below its content, or the
     board zone can never hit its overflow-y and the clamp above just clips */
  grid-template-rows: minmax(0, 1fr);
  gap: 18px;
  padding: 10px 16px 12px;
  min-height: 0;
}

/* --- plaque --- */

.plaque { display: flex; gap: 12px; align-items: center; }

.portrait {
  /* investigator cards are LANDSCAPE ~7:5; the old 86x120 portrait-orientation
     crop with cover showed only the middle ~half of the art */
  width: 150px; height: 107px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--edge-lit);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .7);
  flex: none;
  padding: 0;
  cursor: zoom-in;
  transition: box-shadow .2s;
}
.portrait:hover { box-shadow: 0 0 18px rgba(224, 162, 68, .3); }
.portrait img { width: 100%; height: 100%; object-fit: contain; object-position: center; background: #000; }

.plaque-info h3 {
  font-size: 17px; font-weight: 400;
  letter-spacing: .08em;
  color: var(--parchment);
  margin-bottom: 6px;
}
.vitals { display: flex; flex-direction: column; gap: 3px; margin-bottom: 7px; }
.vital { display: flex; align-items: center; gap: 8px; }
.vital label { font-size: 9px; letter-spacing: .18em; text-transform: uppercase; color: var(--parchment-faint); width: 44px; }
.purse { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* --- hand fan --- */

.hand-zone { min-width: 0; position: relative; }
.hand {
  display: flex;
  align-items: flex-end;
  list-style: none;
  padding: 4px 30px 0 6px;
  height: 138px;
}
/* Jitter-proof hover: .hand-hit is the pointer target and is NEVER transformed,
   so its hit box stays put; the enlarged card is .hand-visual, which has
   pointer-events:none and therefore can't steal the hover from a neighbor. */
.hand-card {
  position: relative;
  margin-left: -24px;
  z-index: calc(var(--i) + 1);
}
.hand-card:first-child { margin-left: 0; }
.hand-card:hover { z-index: 130; }
.hand-hit {
  display: block;
  padding: 0;
  width: 96px;
  aspect-ratio: 5 / 7;
}
.hand-visual {
  display: block;
  pointer-events: none;
  transform: rotate(calc((var(--i) - 3) * 1.4deg));
  transform-origin: bottom center;
  transition: transform .2s ease;
}
.hand-visual img {
  width: 96px;
  border-radius: 5px;
  border: 1px solid #2c2418;
  box-shadow: -6px 4px 14px rgba(0, 0, 0, .65);
  transition: box-shadow .2s, border-color .2s;
}
.hand-card:hover .hand-visual {
  /* big enough to read the card's rules text */
  transform: translateY(-148px) scale(2.9) rotate(0deg);
}
.hand-card:hover .hand-visual img { box-shadow: 0 18px 50px rgba(0, 0, 0, .9); border-color: var(--edge-lit); }
.hand-card.playable .hand-visual img { border-color: #57652f; }
.hand-card.playable:hover .hand-visual img { border-color: var(--candle); box-shadow: 0 0 26px rgba(224, 162, 68, .4), 0 18px 50px rgba(0, 0, 0, .9); }
/* F1-3: fast-playable cards (no action cost) get a cool teal edge */
.hand-card.fast .hand-visual img { border-color: #2e6b5e; }
.hand-card.fast:hover .hand-visual img { border-color: #5fd7bc; box-shadow: 0 0 26px rgba(95, 215, 188, .35), 0 18px 50px rgba(0, 0, 0, .9); }
/* F3: near-dead imports — dimmed card + wax-seal badge (icons commit, no Play) */
.hand-card.near-dead .hand-visual img { filter: grayscale(.55) brightness(.75); border-color: #4a3040; }
.near-dead-seal {
  position: absolute; top: 4px; right: 4px;
  width: 18px; height: 18px; line-height: 18px;
  border-radius: 50%; text-align: center;
  font-size: 11px; color: #d8b4c8;
  background: rgba(58, 26, 46, .92);
  border: 1px solid #7a4a66;
  box-shadow: 0 0 8px rgba(0, 0, 0, .7);
  pointer-events: none;
}
.hand-visual { position: relative; }

.zone-hint {
  font-style: italic;
  text-transform: none;
  letter-spacing: .04em;
  font-size: 10px;
  color: var(--parchment-faint);
  opacity: .85;
  margin-left: 6px;
}

/* --- board (assets / threats) --- */

.board-zone { display: flex; flex-direction: column; gap: 8px; min-width: 0; min-height: 0; overflow-y: auto; padding-right: 4px; }

.board-row { min-width: 0; }
.board-cards { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-start; }

.mini-card { width: 66px; position: relative; transition: transform .2s; }
.mini-card.exhausted { transform: rotate(8deg); opacity: .58; }
.mini-art { padding: 0; display: block; cursor: zoom-in; }
.mini-art img {
  width: 100%;
  border-radius: 4px;
  border: 1px solid var(--edge);
  transition: border-color .2s, box-shadow .2s;
}
.mini-art:hover img { border-color: var(--edge-lit); box-shadow: 0 0 12px rgba(224, 162, 68, .2); }
.mini-card.threat .mini-art img { border-color: var(--blood-deep); }
.mini-card.threat .mini-art:hover img { border-color: var(--blood); box-shadow: 0 0 12px rgba(178, 51, 39, .35); }

.mini-chips { display: flex; flex-direction: column; gap: 2px; margin-top: 3px; align-items: flex-start; }
.mini-chips .chip { font-size: 9px; padding: 1px 5px; }
.mini-abil { margin-top: 3px; display: flex; flex-direction: column; gap: 2px; }
.mini-btn { font-size: 9.5px; padding: 3px 5px; text-transform: none; letter-spacing: .02em; width: 100%; }

/* ============================================================
   OVERLAYS
   ============================================================ */

/* stacking (no wrapper stacking contexts — each fixed layer sets its own z):
   modals 200 < result stamps 300 < encounter reveal 320 < toasts 330
   < card inspect 360 < hover preview 370 < grain 400 */

.overlay {
  position: fixed; inset: 0;
  z-index: 200;
  display: grid; place-items: center;
  background: rgba(3, 4, 3, .78);
  backdrop-filter: blur(3px);
  animation: overlay-in .3s ease both;
  padding: 30px;
  overflow-y: auto;
}
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

.sheet, .test-sheet, .token-scene, .end-scroll {
  background: linear-gradient(168deg, var(--leather), #100c08 70%);
  border: 1px solid var(--edge-lit);
  border-radius: 8px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .9),
    0 0 0 6px rgba(20, 16, 10, .85),
    0 0 0 7px var(--edge),
    0 40px 90px rgba(0, 0, 0, .9),
    inset 0 0 60px rgba(0, 0, 0, .55);
  padding: 28px 34px;
  animation: sheet-in .35s cubic-bezier(.2, .9, .3, 1.15) both;
}
@keyframes sheet-in { from { opacity: 0; transform: translateY(24px) scale(.96); } to { opacity: 1; transform: none; } }

.sheet-title {
  font-size: 21px; font-weight: 400;
  letter-spacing: .06em;
  color: var(--parchment);
  margin-bottom: 6px;
  text-align: center;
}
.sheet-hint { font-size: 12.5px; font-style: italic; color: var(--parchment-faint); text-align: center; margin-bottom: 16px; }

/* --- choice modal --- */

.choice-sheet { max-width: 760px; max-height: 84vh; overflow-y: auto; }

.choice-grid { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 14px; }

.choice-opt {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 10px 16px;
  min-width: 130px; max-width: 190px;
  border: 1px solid var(--edge);
  border-radius: 5px;
  background: rgba(10, 8, 6, .7);
  color: var(--parchment);
  transition: border-color .18s, box-shadow .18s, transform .15s;
}
.choice-opt:hover:not(:disabled) {
  border-color: var(--candle);
  box-shadow: 0 0 18px rgba(224, 162, 68, .22);
  transform: translateY(-2px);
}
.choice-opt:disabled { opacity: .4; }
.choice-opt.selected {
  border-color: var(--candle);
  background: rgba(224, 162, 68, .1);
  box-shadow: 0 0 20px rgba(224, 162, 68, .35), inset 0 0 14px rgba(224, 162, 68, .1);
}
.opt-art { width: 108px; border-radius: 5px; border: 1px solid var(--edge); }
.opt-label { font-size: 13px; line-height: 1.3; }
.opt-detail { font-size: 11px; font-style: italic; color: var(--parchment-dim); }

.choice-footer { display: flex; gap: 12px; justify-content: center; margin-top: 20px; }

/* --- skill test commit window: docked seance table ---
   Deliberately light: no full-screen dim, pointer-events pass through the
   empty area so the room, enemies and mini-map stay visible & inspectable. */

.overlay-test {
  place-items: end center;
  padding: 0;
  background: linear-gradient(180deg, transparent 34%, rgba(3, 4, 3, .6) 82%);
  backdrop-filter: none;
  pointer-events: none;
}
.overlay-test .test-sheet { pointer-events: auto; }

.test-sheet {
  width: min(1040px, 96vw);
  max-height: 76vh;
  overflow-y: auto;
  border-radius: 10px 10px 0 0;
  border-bottom: none;
  padding: 18px 30px 18px;
  animation: sheet-in .4s cubic-bezier(.2, .9, .3, 1.1) both;
}

.test-head { display: flex; align-items: center; gap: 16px; margin-bottom: 10px; }
.test-peek {
  margin-left: auto;
  max-width: 190px;
  text-align: right;
  font-size: 10.5px; font-style: italic;
  color: var(--parchment-faint);
}

/* body: source card headline | commit area | chaos-bag reference */
.test-body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) 260px;
  gap: 20px;
  align-items: start;
  margin-bottom: 10px;
}
.test-main { min-width: 0; }

.test-source {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  width: 172px;
}
.test-source-card { padding: 0; border-radius: 8px; transition: transform .2s; }
.test-source-card img {
  width: 172px;
  border-radius: 8px;
  border: 1px solid var(--blood-deep);
  box-shadow: 0 0 28px rgba(178, 51, 39, .28), 0 14px 30px rgba(0, 0, 0, .7);
}
.test-source-card:hover { transform: scale(1.05); }
.test-source-note { font-size: 10px; font-style: italic; letter-spacing: .06em; color: #b06a5c; }

.bag-ref {
  background: rgba(8, 7, 5, .6);
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: 10px 12px;
  max-height: 250px;
  overflow-y: auto;
}
.bag-title {
  font-size: 10px; font-weight: 400;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--parchment-faint);
  margin-bottom: 8px;
}
.bag-row { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 7px; }

/* odds cheat mode — gated panel under the bag reference */
.odds-cheat { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--edge); }
.odds-ask { width: 100%; font-size: 11px; }
.odds-ask i, .odds-title i { font-style: italic; color: var(--parchment-faint); }
.odds-confirm p { font-size: 11px; line-height: 1.5; color: var(--parchment-dim); margin-bottom: 8px; }
.odds-confirm-row { display: flex; gap: 6px; }
.odds-confirm-row .btn { flex: 1; font-size: 10px; padding: 5px 4px; }
.odds-title {
  font-size: 10px; font-weight: 400;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--parchment-faint);
  margin-bottom: 6px;
}
.odds-nums { display: flex; gap: 12px; margin-bottom: 7px; }
.odds-num { display: grid; justify-items: center; }
.odds-num b { font-size: 17px; color: var(--gold, #c9a227); }
.odds-num label { font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--parchment-faint); }
.odds-chips { display: flex; flex-wrap: wrap; gap: 3px; margin-bottom: 7px; }
.odds-chip {
  width: 20px; height: 20px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11px;
  background: #12100b;
  border: 1px solid var(--edge-lit);
}
.odds-chip.ok { color: #7fbf7f; border-color: #3d5a3d; }
.odds-chip.no { color: #b06a5c; opacity: .55; }
.odds-hide { width: 100%; font-size: 10px; }
.bag-glyph {
  flex: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 13px;
  background: #12100b;
  border: 1px solid var(--edge-lit);
  color: var(--parchment);
}
.bag-glyph.t-fail { color: var(--doomglow); border-color: var(--blood); }
.bag-glyph.t-elder { color: var(--candle-hot); border-color: var(--candle); }
.bag-glyph.t-sym { color: #c5b2e0; }
.bag-text { font-size: 11.5px; color: var(--parchment-dim); line-height: 1.35; }
.bag-none { font-size: 11.5px; font-style: italic; color: var(--parchment-faint); }

/* compact everything-in-play strip */
.inplay-strip {
  border-top: 1px solid var(--edge);
  padding-top: 8px;
  margin-bottom: 10px;
}
.ip-thumbs { display: flex; gap: 12px; flex-wrap: wrap; }
.ip-thumb { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 0; }
.ip-thumb img {
  width: 52px;
  border-radius: 3px;
  border: 1px solid var(--edge);
  transition: border-color .15s, transform .15s;
}
.ip-thumb:hover img { border-color: var(--candle); transform: scale(1.1); }
.ip-thumb label {
  font-size: 8.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--parchment-faint);
  cursor: pointer;
}

.skill-seal {
  flex: none;
  width: 64px; height: 64px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  border: 2px solid;
  background: radial-gradient(circle at 38% 32%, rgba(255, 255, 255, .1), transparent 55%), #0c0a07;
  box-shadow: 0 0 20px rgba(0, 0, 0, .6);
}
.sk-willpower { color: #a8c8e8; border-color: var(--sk-willpower); box-shadow: 0 0 18px rgba(74, 122, 168, .35); }
.sk-intellect { color: #ecd29a; border-color: var(--sk-intellect); box-shadow: 0 0 18px rgba(192, 138, 46, .35); }
.sk-combat { color: #eba99c; border-color: var(--sk-combat); box-shadow: 0 0 18px rgba(168, 60, 44, .35); }
.sk-agility { color: #bcdcab; border-color: var(--sk-agility); box-shadow: 0 0 18px rgba(93, 138, 74, .35); }

.test-title h2 { font-size: 19px; font-weight: 400; letter-spacing: .04em; color: var(--parchment); }
.test-math { font-size: 14px; color: var(--parchment-dim); margin-top: 3px; display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.test-math b { font-size: 19px; color: var(--candle-hot); }
.test-math i { font-style: italic; color: var(--parchment-faint); }
.math-detail { font-size: 11px; color: var(--parchment-faint); }
.verdict { font-size: 11px; font-style: italic; letter-spacing: .06em; }
.verdict.v-holding { color: #93b479; }
.verdict.v-short { color: #d4695a; }

.commit-hand {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
  padding: 10px 4px;
  min-height: 104px;
  align-items: center;
}

/* same stable-hit pattern as the hand: the button never transforms,
   only the (pointer-events:none) image inside it grows */
.commit-card {
  position: relative;
  padding: 0;
  border-radius: 6px;
}
.commit-card:hover:not(.inert) { z-index: 5; }
.commit-card img {
  width: 84px;
  border-radius: 6px;
  border: 1px solid var(--edge);
  pointer-events: none;
  transform-origin: bottom center;
  transition: border-color .18s, filter .18s, transform .18s, box-shadow .18s;
}
.commit-card:hover:not(.inert) img { transform: translateY(-24px) scale(2.3); box-shadow: 0 16px 44px rgba(0, 0, 0, .85); }
.commit-card.inert img { filter: grayscale(.75) brightness(.5); }
.commit-card.selected img {
  border-color: var(--candle);
  box-shadow: 0 0 22px rgba(224, 162, 68, .5);
  transform: translateY(-10px);
}
.commit-card.selected:hover img { transform: translateY(-24px) scale(2.3); }
.commit-card .commit-badge { pointer-events: none; }

.commit-badge {
  position: absolute; top: -8px; right: -8px;
  font-size: 11px; font-weight: 700;
  padding: 2px 7px;
  border-radius: 9px;
  border: 1px solid;
  background: #0c0a07;
}

.pump-row { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-bottom: 8px; }
.btn-pump { text-transform: none; letter-spacing: .02em; }
.btn-pump b { color: var(--candle); }

.test-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  border-top: 1px solid var(--edge);
  padding-top: 14px;
}
.commit-count { font-size: 12.5px; font-style: italic; color: var(--parchment-faint); }
.btn-reveal { font-size: 15px; padding: 11px 26px; letter-spacing: .12em; }

/* --- chaos token reveal --- */

.overlay-token { background: rgba(2, 3, 2, .88); }

.token-scene {
  text-align: center;
  padding: 40px 60px;
  border-radius: 12px;
}

.token-coin {
  width: 132px; height: 132px;
  margin: 0 auto 20px;
  position: relative;
  transform-style: preserve-3d;
  animation: token-flip 1.05s cubic-bezier(.3, .7, .3, 1) both;
}
@keyframes token-flip {
  0% { transform: rotateY(990deg) scale(.3) translateY(-70px); }
  70% { transform: rotateY(180deg) scale(1.06); }
  100% { transform: rotateY(0deg) scale(1); }
}
.token-face {
  position: absolute; inset: 0;
  border-radius: 50%;
  backface-visibility: hidden;
  display: grid; place-items: center;
}
.token-back {
  transform: rotateY(180deg);
  background: radial-gradient(circle at 40% 32%, #2b241a, #0d0b08 70%);
  border: 3px double var(--edge-lit);
}
.token-front {
  background: radial-gradient(circle at 40% 30%, #332a1c, #12100b 75%);
  border: 3px double var(--candle);
  box-shadow: 0 0 44px rgba(224, 162, 68, .3), inset 0 0 24px rgba(0, 0, 0, .8);
}
.token-glyph {
  font-size: 52px;
  color: var(--parchment);
  text-shadow: 0 0 22px rgba(224, 162, 68, .6);
}
.token-coin.t-fail .token-front { border-color: var(--blood); box-shadow: 0 0 50px rgba(178, 51, 39, .55), inset 0 0 24px rgba(0, 0, 0, .8); }
.token-coin.t-fail .token-glyph { color: var(--doomglow); text-shadow: 0 0 26px rgba(255, 91, 65, .8); }
.token-coin.t-elder .token-front { border-color: var(--candle-hot); box-shadow: 0 0 60px rgba(255, 216, 148, .6), inset 0 0 24px rgba(0, 0, 0, .8); }
.token-coin.t-elder .token-glyph { color: var(--candle-hot); }
.token-coin.t-sym .token-glyph { color: #c5b2e0; text-shadow: 0 0 24px rgba(138, 111, 176, .7); }
.token-coin.good .token-glyph { color: #a9d18f; }

.token-name {
  font-size: 15px; font-weight: 400;
  letter-spacing: .4em; text-transform: uppercase;
  color: var(--parchment-dim);
  margin-bottom: 10px;
  animation: fade-up .5s .55s ease both;
}
.token-effect {
  font-size: 14px; font-style: italic;
  color: var(--parchment);
  max-width: 380px; margin: 0 auto 8px;
  animation: fade-up .5s .65s ease both;
}
.token-effect b { color: var(--candle-hot); font-style: normal; }
.token-math {
  font-size: 12.5px; color: var(--parchment-faint);
  margin-bottom: 20px;
  animation: fade-up .5s .75s ease both;
}
.token-math b { color: var(--parchment); }
.token-scene .btn-gold { animation: fade-up .5s .9s ease both; }

/* --- card inspect (click / universal right-click) --- */

.overlay-zoom {
  background: rgba(2, 3, 2, .9);
  cursor: zoom-out;
  place-content: center;
  z-index: 360; /* above skill-test/choice modals AND the encounter reveal */
}
.zoom-card {
  max-height: 82vh; max-width: 86vw;
  border-radius: 14px;
  box-shadow: 0 0 90px rgba(0, 0, 0, 1), 0 0 40px rgba(224, 162, 68, .12);
  animation: sheet-in .25s ease both;
}
.zoom-bar { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 14px; }
.zoom-flip { cursor: pointer; }
.zoom-hint { text-align: center; font-size: 11.5px; font-style: italic; color: var(--parchment-faint); }

/* --- AV1: the agenda/act presentation ritual --- */

.overlay-present {
  background: rgba(2, 3, 2, .93);
  cursor: pointer;
  place-content: center;
  /* above the skill-test/choice modals a flip's effects may have opened (the
     story beat reads first), but below the zoom overlay and the card preview */
  z-index: 350;
}
.present-inner {
  display: flex; align-items: center; gap: 38px;
  max-width: 1000px;
  animation: sheet-in .3s ease both;
}
.present-card {
  width: 320px; max-width: 38vw; max-height: 78vh;
  flex: none;
  border-radius: 14px;
  box-shadow: 0 0 90px rgba(0, 0, 0, 1), 0 0 44px rgba(224, 162, 68, .14);
}
.present-copy { min-width: 0; }
.present-kicker {
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--parchment-faint);
}
.present-kicker i { font-style: normal; color: var(--edge-lit); }
.present-name {
  font-family: var(--serif);
  font-size: 30px; line-height: 1.15; margin: 6px 0 14px;
  color: var(--candle-hot);
}
.present-flavor {
  font-family: var(--serif); font-style: italic;
  font-size: 15.5px; line-height: 1.62;
  color: var(--parchment);
  max-height: 42vh; overflow-y: auto;
}
.present-flavor p + p { margin-top: .7em; }
.present-caption {
  margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--edge);
  font-size: 13px; color: var(--clue);
}
.present-bar { display: flex; gap: 12px; margin: 18px 0 8px; }
.present-bar .btn { cursor: pointer; }
.overlay-present .zoom-hint { text-align: left; }

@media (max-width: 900px) {
  .present-inner { flex-direction: column; gap: 18px; }
  .present-card { width: 210px; max-width: 60vw; }
  .present-flavor { max-height: 26vh; }
}

/* floating preview for chronicle card references */
.card-preview {
  position: fixed;
  z-index: 370;
  width: 232px;
  display: none;
  pointer-events: none;
  animation: overlay-in .15s ease both;
}
.card-preview img {
  width: 100%;
  border-radius: 10px;
  border: 1px solid var(--edge-lit);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .95), 0 0 30px rgba(224, 162, 68, .12);
}

/* --- resolution screen --- */

.overlay-end { background: rgba(2, 3, 2, .94); }

.end-scroll {
  max-width: 660px;
  text-align: center;
  padding: 48px 56px;
}
.end-title {
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--parchment);
  margin-bottom: 14px;
  text-shadow: 0 0 34px rgba(224, 162, 68, .25);
}
.end-resolution { font-size: 15px; letter-spacing: .1em; color: var(--candle); margin-bottom: 22px; text-transform: uppercase; }
.end-summary {
  border-top: 1px solid var(--edge); border-bottom: 1px solid var(--edge);
  padding: 20px 8px;
  margin-bottom: 20px;
  max-height: 38vh;
  overflow-y: auto;
}
.end-summary p {
  font-size: 15px; font-style: italic;
  color: var(--parchment-dim);
  margin-bottom: 10px;
  animation: fade-up .8s ease both;
}
.end-summary p:nth-child(1) { animation-delay: .3s; }
.end-summary p:nth-child(2) { animation-delay: .8s; }
.end-summary p:nth-child(3) { animation-delay: 1.3s; }
.end-summary p:nth-child(4) { animation-delay: 1.8s; }
.end-summary p:nth-child(5) { animation-delay: 2.3s; }
.end-summary p:nth-child(n+6) { animation-delay: 2.7s; }
.end-xp { font-size: 17px; color: var(--clue); letter-spacing: .08em; margin-bottom: 26px; }

/* ============================================================
   TRANSIENT FX
   ============================================================ */

.stamp {
  position: fixed;
  left: 50%; top: 42%;
  z-index: 300;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 12px 40px 16px 52px;
  border: 4px double currentColor;
  border-radius: 6px;
  pointer-events: none;
  animation: stamp-in 2.6s cubic-bezier(.15, .9, .3, 1) both;
  text-shadow: 0 0 40px currentColor;
  background: rgba(4, 5, 4, .7);
  max-width: min(640px, 84vw);
}
.stamp-word {
  font-size: clamp(42px, 6vw, 76px);
  letter-spacing: .3em;
  text-transform: uppercase;
  line-height: 1;
}
.stamp-detail {
  font-size: 14.5px;
  font-style: italic;
  letter-spacing: .04em;
  color: var(--parchment);
  text-shadow: 0 1px 4px rgba(0, 0, 0, .9);
  text-align: center;
}
.stamp-success { color: #9fca80; }
.stamp-fail { color: var(--doomglow); }
@keyframes stamp-in {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-8deg) scale(2.4); }
  11% { opacity: 1; transform: translate(-50%, -50%) rotate(-8deg) scale(1); }
  78% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(-8deg) scale(.96); }
}

/* encounter reveal — modal until the player clicks Continue */
.encounter-flash {
  position: fixed; inset: 0;
  z-index: 320;
  display: grid; place-items: center;
  background: rgba(2, 3, 2, .92);
  cursor: pointer;
  animation: encounter-bg .25s ease both;
  padding: 20px;
  overflow-y: auto;
}
@keyframes encounter-bg { from { opacity: 0; } to { opacity: 1; } }
.encounter-inner { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.encounter-inner img {
  max-height: 74vh;
  max-width: 86vw;
  border-radius: 14px;
  box-shadow: 0 0 120px rgba(178, 51, 39, .35), 0 0 60px rgba(0, 0, 0, 1);
  animation: encounter-lurch .5s cubic-bezier(.2, 1.2, .3, 1) both;
}
@keyframes encounter-lurch {
  0% { opacity: 0; transform: scale(.55) rotate(3deg); filter: brightness(3); }
  55% { opacity: 1; transform: scale(1.04) rotate(-1deg); filter: brightness(1.25); }
  100% { transform: scale(1) rotate(0); filter: brightness(1); }
}
.encounter-cap {
  font-size: 14px; letter-spacing: .34em; text-transform: uppercase;
  color: var(--parchment-dim);
  animation: fade-up .4s .25s ease both;
  text-align: center;
}
.encounter-continue {
  font-size: 15px;
  padding: 11px 34px;
  letter-spacing: .12em;
  animation: fade-up .4s .5s ease both;
}

.toast {
  position: fixed;
  bottom: 262px; left: 50%; /* floats ~22px above the (now 240px-min) footer */
  z-index: 330;
  transform: translateX(-50%);
  font-size: 13.5px; font-style: italic;
  color: var(--parchment);
  background: rgba(20, 12, 9, .95);
  border: 1px solid var(--blood-deep);
  border-radius: 4px;
  padding: 9px 20px;
  pointer-events: none;
  animation: toast-in 2.6s ease both;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .8);
}
@keyframes toast-in {
  0% { opacity: 0; transform: translate(-50%, 10px); }
  8%, 80% { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -6px); }
}

/* ============================================================
   RESPONSIVE (primary ≥1200px; degrade gracefully below)
   ============================================================ */

@media (max-width: 1400px) {
  .stage { grid-template-columns: minmax(0, 1fr) 280px; }
  .panel-body { grid-template-columns: 300px minmax(0, 1fr) minmax(200px, 24%); }
  /* 133 + 12 gap + ~155 pip row = 300 */
  .portrait { width: 133px; height: 95px; }
}

@media (max-width: 1200px) {
  .stage { grid-template-columns: minmax(0, 1fr) 240px; }
  .figures { max-width: 30%; }
  .figure { width: 128px; }
  .flavor-ribbon { max-width: 26%; font-size: 13px; }
  .hand-hit { width: 84px; }
  .hand-visual img { width: 84px; }
  .hand-card:hover .hand-visual { transform: translateY(-118px) scale(2.6) rotate(0); }
  .panel-body { grid-template-columns: 280px minmax(0, 1fr) 200px; gap: 12px; }
  /* 115 + 12 gap + ~153 pip row = 280 */
  .portrait { width: 115px; height: 82px; }
  /* Degrade the phase strip to just the CURRENT phase instead of hiding the
     indicator entirely — plenty of "normal" windows are under 1200px wide. */
  .phases .phase { display: none; }
  .phases .phase.on { display: block; font-size: 9.5px; padding: 3px 8px; }
  .phases .phase.on::after { content: none; }
  .test-body { grid-template-columns: auto minmax(0, 1fr); }
  .bag-ref { grid-column: 1 / -1; max-height: 140px; }
  .test-source-card img, .test-source { width: 132px; }
  .minimap.mini { width: 148px; height: 112px; }
}

@media (max-width: 950px) {
  body { overflow: auto; }
  /* body scrolls here, so the footer clamp/divider are moot — hide the grip */
  .app { height: auto; grid-template-rows: auto minmax(420px, 60vh) auto auto; }
  #panel-divider { display: none; }
  .stage { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) 160px; }
  #rail { border-left: none; border-top: 1px solid var(--edge); }
  .panel-body { grid-template-columns: 1fr; }
  .flavor-ribbon { display: none; }
  .figures { position: static; flex-direction: row; justify-content: flex-end; padding: 150px 16px 0; }
  .test-body { grid-template-columns: 1fr; }
  .test-source { flex-direction: row; width: auto; }
  .minimap.expanded { width: min(420px, 92vw); }
}

/* ============================================================
   TWO-INVESTIGATOR HOT-SEAT CO-OP (2026-07-14)
   Party picker on the landing page, whose-decision banners,
   investigator tabs, HUD vitals strips, per-seat map markers.
   Seat colors follow faction: seat-1 Roland (guardian blue),
   seat-2 Daisy (seeker gold).
   ============================================================ */

:root {
  --seat-1: #4a7aa8;
  --seat-2: #c08a2e;
}

/* ---------- landing: party picker ---------- */

.party-select { border: none; }
.party-select legend, .difficulty legend {
  font-size: 11px; letter-spacing: .25em; text-transform: uppercase;
  color: var(--parchment-faint); margin-bottom: 8px;
}
/* F3b retired the fixed party grid (.party-row/.party-opt/.party-card/
   .party-art and the .duo overlap): the landing builds seats now. .party-select
   survives — the seat fieldset still wears it for the legend rule above. */

/* ---------- landing: F3b seat list (import-first party assembly) ---------- */

.seat-hint {
  font-size: 11.5px; color: var(--parchment-dim); font-style: italic;
  margin: 0 0 10px; text-align: center;
}
.seat-hint b { color: var(--candle, #e0a244); font-style: normal; }
.seat-list { display: flex; flex-direction: column; gap: 10px; }
.seat-row {
  padding: 10px;
  border: 1px solid var(--edge); border-radius: 8px;
  background: var(--panel);
  text-align: left;
}
.seat-row.seat-bad { border-color: #a8543f; }
.seat-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.seat-no {
  font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--parchment-faint);
}
.seat-mode { cursor: pointer; font-size: 12px; display: flex; align-items: center; gap: 5px; }
.seat-mode input { accent-color: var(--candle, #e0a244); }
.seat-drop { margin-left: auto; font-size: 11px; padding: 2px 8px; }
.seat-add { margin-top: 10px; font-size: 12px; }
.seat-body { display: flex; align-items: flex-start; gap: 10px; margin-top: 8px; }
.seat-art { flex: none; width: 56px; }
.seat-art img { width: 56px; border-radius: 5px; border: 1px solid var(--edge); }
.seat-pick { flex: 1; min-width: 0; }
.seat-preset {
  width: 100%; padding: 5px 7px;
  border: 1px solid var(--edge); border-radius: 5px;
  background: var(--ink, #14100c); color: var(--parchment);
  font: inherit; font-size: 12.5px;
}
.seat-import { display: flex; flex-direction: column; gap: 6px; }
.seat-import[hidden] { display: none; }   /* display:flex would beat the hidden attr */
.seat-import input, .seat-import textarea {
  width: 100%; padding: 5px 7px;
  border: 1px solid var(--edge); border-radius: 5px;
  background: var(--ink, #14100c); color: var(--parchment);
  font: inherit; font-size: 12px;
}
.seat-import textarea { resize: vertical; min-height: 36px; }
.seat-import .btn { align-self: flex-start; }
.seat-report { margin-top: 8px; }
.seat-report p { margin: 2px 0; font-size: 11.5px; }
.seat-pick .import-err { margin: 6px 0 0; font-size: 11.5px; }
.seat-neardead { margin: 10px 0 0; font-size: 11.5px; text-align: left; }
.seat-gate {
  margin: 6px 0 0; font-size: 11.5px; font-style: italic;
  color: var(--parchment-faint);
}
.btn-begin[disabled] { opacity: .45; cursor: not-allowed; filter: saturate(.4); }

/* ---------- whose-decision banner (choice + commit overlays) ---------- */

.decider {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
  padding: 4px 8px;
  border: 1px solid var(--edge);
  border-left: 3px solid var(--candle);
  border-radius: 5px;
  background: rgba(224, 162, 68, .08);
  width: fit-content;
}
.decider-face {
  width: 26px; height: 26px; object-fit: cover; object-position: top;
  border-radius: 50%; border: 1px solid var(--edge-lit);
}
.decider-name { font-size: 12.5px; letter-spacing: .04em; }
.decider-name i { color: var(--parchment-dim); font-style: italic; }
.test-title .decider { margin-bottom: 4px; }

/* ---------- HUD: per-investigator vitals strips (co-op) ---------- */

.hud-invs { display: flex; gap: 8px; align-items: center; }
.hud-inv {
  display: flex; align-items: center; gap: 5px;
  padding: 2px 6px 2px 2px;
  border: 1px solid var(--edge); border-radius: 5px;
  background: var(--panel);
  opacity: .82;
}
.hud-inv.on { border-color: var(--candle); opacity: 1; box-shadow: 0 0 6px rgba(224, 162, 68, .25); }
.hud-inv.out { opacity: .38; filter: grayscale(.8); }
.hud-inv.seat-1 { border-left: 3px solid var(--seat-1); }
.hud-inv.seat-2 { border-left: 3px solid var(--seat-2); }
/* landscape-shaped thumb (~7:5) so the crop keeps the face instead of a
   square slice of card middle */
.hud-inv img { width: 34px; height: 24px; object-fit: cover; object-position: center; border-radius: 3px; }
.hud-inv-stats { display: flex; gap: 5px; font-size: 10.5px; }
.hud-inv-stats b { font-weight: 600; }
.hud-inv-stats .st-hp { color: var(--doomglow); }
.hud-inv-stats .st-san { color: var(--sk-willpower); }
.hud-inv-stats .st-clue { color: var(--clue); }
.hud-inv-stats .st-res { color: var(--parchment-dim); }

/* ---------- investigator panel: viewer tabs (co-op) ---------- */

.inv-tabs {
  display: flex; gap: 6px;
  padding: 5px 10px 0;
}
.inv-tab {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 4px;
  border: 1px solid var(--edge); border-bottom: none;
  border-radius: 7px 7px 0 0;
  background: var(--pit);
  font-size: 12px; color: var(--parchment-dim);
}
.inv-tab img { width: 34px; height: 24px; object-fit: cover; object-position: center; border-radius: 3px; }
.inv-tab.seat-1 { border-top: 2px solid var(--seat-1); }
.inv-tab.seat-2 { border-top: 2px solid var(--seat-2); }
.inv-tab.viewing { background: var(--panel); color: var(--parchment); border-color: var(--edge-lit); }
.inv-tab.active-turn .inv-tab-name { color: var(--candle-hot); }
.inv-tab-turn { font-size: 9.5px; color: var(--candle); letter-spacing: .1em; text-transform: uppercase; }
.inv-tab-lead {
  font-size: 8.5px; letter-spacing: .18em; text-transform: uppercase;
  color: #150e04; background: var(--parchment-dim);
  border-radius: 2px; padding: 0 4px;
}
.inv-tab.out { opacity: .45; filter: grayscale(.7); }
.inv-tab-out { font-size: 9.5px; color: var(--doomglow); font-style: italic; }

/* ---------- mini-map: per-seat investigator markers (co-op) ---------- */

.map-marks { display: flex; gap: 3px; justify-content: center; }
.map-you.seat-1 { background: var(--seat-1); color: #05131f; letter-spacing: 0; }
.map-you.seat-2 { background: var(--seat-2); color: #1d1305; letter-spacing: 0; }
.map-you.seat-1.on, .map-you.seat-2.on { outline: 1px solid var(--candle-hot); }

/* ---------- turn handoff banner (hot-seat cue) ---------- */

.turn-banner {
  position: fixed; left: 50%; top: 26%;
  transform: translateX(-50%);
  padding: 12px 34px;
  border: 1px solid var(--edge-lit);
  border-radius: 6px;
  background: rgba(5, 7, 6, .92);
  color: var(--candle-hot);
  font-size: 22px; letter-spacing: .12em;
  text-shadow: 0 0 18px rgba(224, 162, 68, .5);
  animation: turn-banner-in 2.2s ease forwards;
  pointer-events: none;
  z-index: 60;
}
@keyframes turn-banner-in {
  0% { opacity: 0; transform: translateX(-50%) translateY(10px); }
  12% { opacity: 1; transform: translateX(-50%) translateY(0); }
  80% { opacity: 1; }
  100% { opacity: 0; }
}

/* ---------- audio (narration) control ---------- */
#audio-ctl {
  position: fixed; right: 14px; bottom: 14px;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--edge-lit);
  border-radius: 20px;
  background: rgba(5, 7, 6, .88);
  /* Above every overlay (present=350) but below the zoom (360). It used to sit
     at 70, under .overlay's 200 — which meant the presentation ritual, being
     full-screen from the first moment of every scenario, physically covered the
     mute button AND the button that turns the ritual off, and a click aimed at
     either one landed on the overlay and advanced the ritual instead. Narration
     controls must be reachable while narration is happening. */
  z-index: 355;
  opacity: .55;
  transition: opacity .25s ease;
}
#audio-ctl:hover { opacity: 1; }
#audio-ctl button {
  background: none; border: none; cursor: pointer;
  font-size: 17px; line-height: 1; padding: 0;
  filter: none;
}
#audio-ctl button.muted { filter: grayscale(1) brightness(.7); }
#audio-ctl input[type="range"] {
  width: 74px; accent-color: var(--candle-hot, #e0a244);
  cursor: pointer;
}

/* ---------- F2: campaign panels ---------- */
.landing-continue {
  margin: 14px auto 0; max-width: 720px;
  border: 1px solid var(--edge-lit); border-radius: 6px;
  background: rgba(5, 7, 6, .8);
  padding: 10px 14px;
  text-align: left; font-size: 13px;
}
.landing-continue .continue-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0;
}
.landing-continue .continue-row + .continue-row { border-top: 1px solid rgba(92, 68, 38, .4); }
.landing-continue .continue-row span { flex: 1; }
.landing-continue i { opacity: .7; }
/* F3: per-seat deck import rows */
.landing-continue .deck-hint { padding-top: 8px; }
.landing-continue .deck-row span b { color: var(--candle, #e0a244); font-weight: 600; }
.landing-continue .import-form { flex-wrap: wrap; }
.landing-continue .import-form[hidden] { display: none; }   /* display:flex would beat the hidden attr */
.landing-continue .import-form input,
.landing-continue .import-form textarea {
  flex: 1 1 100%;
  background: rgba(0, 0, 0, .55); color: inherit;
  border: 1px solid rgba(92, 68, 38, .7); border-radius: 4px;
  font: inherit; font-size: 12px; padding: 5px 8px;
}
.landing-continue .import-form textarea { resize: vertical; min-height: 40px; }
.landing-continue .import-report { display: block; }
.landing-continue .import-report p { margin: 2px 0; font-size: 12px; }
.import-err { color: #ff9d8a; }
.campaign-won { color: #e9d78f; text-shadow: 0 0 14px rgba(233, 215, 143, .35); }
.campaign-lost { color: #ff9d8a; text-shadow: 0 0 14px rgba(178, 51, 39, .45); }
.import-warn { color: #e0c98a; }
.import-ok { color: #9dd6a8; }

.end-campaign {
  margin: 18px auto; max-width: 560px;
  border-top: 1px solid var(--edge-lit);
  padding-top: 14px;
}
.end-campaign h2 {
  font-size: 15px; letter-spacing: .08em;
  color: var(--candle-hot); margin-bottom: 8px;
}
.end-campaign p { margin: 4px 0; font-size: 13px; }
.end-campaign .end-campaign-hint { opacity: .75; font-style: italic; margin-top: 10px; }
.end-campaign button { margin-top: 12px; }

/* ---------- doom on enemies (C-next) ---------- */
.tag-doom { color: #ffb59e; background: #2c1410; box-shadow: 0 0 10px rgba(255, 91, 65, .35); }
.dot-doom { background: var(--doomglow); box-shadow: 0 0 4px rgba(255, 91, 65, .9); }
/* C11 ASK 1: location horror on the minimap — its own dot, never folded into
   the doom dots (the fire spreading is not the clock ticking). */
.dot-horror { background: #b79ad1; box-shadow: 0 0 4px rgba(183, 154, 209, .9); }

/* ============================================================
   CARD FACSIMILE — HTML stand-in for faces with no printed scan
   (src/ui/card-facsimile.js; ported from lh-chapter2). Pool codes
   with no arkhamdb scan (custom player cards especially) resolve
   to null and render sites show this frame instead of a hidden
   <img>. Container-query sizing: the frame is sized by its host
   context, the type scales with it.
   ============================================================ */

.card-fax {
  --fax-trim: #8a8578; /* neutral default; faction classes override */
  position: relative;
  width: 100%;
  aspect-ratio: 5 / 7;
  container-type: size;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  text-align: left;
  border-radius: 5px;
  border: 1px solid var(--fax-trim);
  background:
    var(--grain-img),
    linear-gradient(168deg, #201b13 0%, #14110c 55%, #0e0c08 100%);
  background-size: 240px 240px, cover;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .6), inset 0 0 22cqw rgba(0, 0, 0, .45);
  color: var(--parchment);
  font-family: var(--serif);
  line-height: 1.25;
}
.fax-guardian { --fax-trim: #4e7cb8; }
.fax-seeker   { --fax-trim: #c08a2e; }
.fax-rogue    { --fax-trim: #3e8a63; }
.fax-mystic   { --fax-trim: #7d5ba6; }
.fax-survivor { --fax-trim: #b0413e; }
.fax-neutral  { --fax-trim: #8a8578; }
.fax-mythos   { --fax-trim: #5a5346; }
.card-fax.fax-back { border-style: dashed; }

.fax-head {
  display: flex; align-items: center; gap: 3cqw;
  padding: 3cqw 4cqw 1cqw;
  background: linear-gradient(180deg, rgba(0, 0, 0, .5), rgba(0, 0, 0, .12));
  border-bottom: 1px solid color-mix(in srgb, var(--fax-trim) 55%, transparent);
}
.fax-cost {
  flex: none;
  min-width: 12cqw; height: 12cqw; line-height: 12cqw;
  border-radius: 50%; text-align: center;
  font-size: 8cqw; font-weight: 700;
  color: var(--candle-hot);
  background: rgba(0, 0, 0, .55);
  border: 1px solid var(--fax-trim);
}
.fax-name {
  font-size: 7cqw; font-weight: 700; color: var(--candle-hot);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.fax-unique { font-style: normal; color: var(--candle); }
.fax-xp { margin-left: 2cqw; color: var(--candle); font-size: 6cqw; letter-spacing: .1em; }
.fax-subname { padding: 0 4cqw; font-size: 5.2cqw; font-style: italic; color: var(--parchment-dim); }

.fax-pips { display: flex; gap: 1.5cqw; padding: 1.5cqw 4cqw 0; }
.fax-pip {
  min-width: 8.5cqw; height: 8.5cqw; line-height: 8.5cqw;
  text-align: center; border-radius: 2cqw;
  font-size: 5.5cqw; color: #fff;
  background: var(--parchment-faint);
}
.fax-pip-willpower { background: var(--sk-willpower); }
.fax-pip-intellect { background: var(--sk-intellect); }
.fax-pip-combat    { background: var(--sk-combat); }
.fax-pip-agility   { background: var(--sk-agility); }
.fax-pip-wild      { background: var(--sk-wild); }

.fax-art {
  flex: none;
  height: 30cqh;
  margin: 2cqw 4cqw 0;
  border-radius: 3px;
  border: 1px solid color-mix(in srgb, var(--fax-trim) 45%, #000);
  background: radial-gradient(circle at 50% 40%, rgba(196, 166, 96, .14), rgba(0, 0, 0, .55) 70%);
  display: grid; place-content: center;
  overflow: hidden;
}
.fax-art img { width: 100%; height: 100%; object-fit: cover; }
.fax-ornament { font-size: 16cqw; color: color-mix(in srgb, var(--fax-trim) 70%, #fff 8%); opacity: .55; }

.fax-type {
  padding: 1.5cqw 4cqw 0;
  font-size: 4.6cqw; letter-spacing: .14em; text-transform: uppercase;
  color: var(--parchment-faint);
}
.fax-traits { padding: 0 4cqw; font-size: 5cqw; font-weight: 700; font-style: italic; color: var(--parchment-dim); }

.fax-body { flex: 1; min-height: 0; overflow: hidden; padding: 1.5cqw 4cqw 2cqw; }
.fax-text { font-size: 5.4cqw; }
.fax-flavor { margin-top: 1.5cqw; font-size: 5cqw; font-style: italic; color: var(--parchment-dim); }
.fax-victory { margin-top: 1.5cqw; font-size: 5cqw; font-weight: 700; color: var(--clue); }
.fax-sym {
  display: inline-block;
  padding: 0 .8cqw;
  font-style: normal;
  color: var(--candle);
}
.fax-sym-word { font-size: .85em; letter-spacing: .08em; text-transform: uppercase; }

/* Skill iconography (head / book / fist / foot) — inline SVG inherits the
   pip's white or the body text's candle color via currentColor. */
.fax-icon {
  width: 1em; height: 1em;
  vertical-align: -.12em;
  fill: currentColor;
}
.fax-pip .fax-icon { vertical-align: middle; }

/* Dense cards: shrink the illustration window and type so long rules text
   (e.g. Scroll of the Pharaohs) fits inside the frame instead of clipping. */
.card-fax.fax-long .fax-art { height: 20cqh; }
.card-fax.fax-long .fax-text { font-size: 4.7cqw; }
.card-fax.fax-long .fax-flavor { font-size: 4.3cqw; }
.card-fax.fax-xlong .fax-art { height: 13cqh; }
.card-fax.fax-xlong .fax-text { font-size: 4.2cqw; }
.card-fax.fax-xlong .fax-flavor { font-size: 4cqw; }
.card-fax.fax-xlong .fax-traits { font-size: 4.4cqw; }

.fax-stats {
  flex: none;
  display: flex; gap: 2cqw; justify-content: center;
  padding: 1.5cqw 4cqw 2.5cqw;
  background: linear-gradient(0deg, rgba(0, 0, 0, .5), transparent);
}
.fax-stat {
  min-width: 11cqw; padding: 0 1.5cqw; height: 9cqw; line-height: 9cqw;
  text-align: center; border-radius: 2cqw;
  font-size: 5.5cqw; font-weight: 700;
  background: rgba(0, 0, 0, .55);
  border: 1px solid var(--edge-lit);
}
.fax-stat-fight, .fax-stat-combat { color: #e08a7a; }
.fax-stat-health { color: #e05545; }
.fax-stat-evade, .fax-stat-agility { color: #9fd08a; }
.fax-stat-sanity { color: #8ab6e0; }
.fax-stat-willpower { color: #8ab6e0; }
.fax-stat-intellect { color: var(--clue); }
.fax-stat-shroud { color: var(--parchment); }
.fax-stat-clue { color: var(--clue); }
.fax-stat-dmg { color: #e05545; }
.fax-stat-hor { color: #8ab6e0; }

/* --- per-site sizing (each matches the <img> it stands in for) --- */

.hand-visual .card-fax {
  width: 96px;
  box-shadow: -6px 4px 14px rgba(0, 0, 0, .65), inset 0 0 0 1px rgba(0, 0, 0, .6);
}
.hand-card.playable .hand-visual .card-fax { border-color: #57652f; }
.hand-card.playable:hover .hand-visual .card-fax { border-color: var(--candle); }

.mini-art .card-fax { width: 100%; cursor: zoom-in; }

/* commit chooser: same stable-hit hover growth as the scan <img> */
.commit-card .card-fax {
  width: 84px;
  pointer-events: none;
  transform-origin: bottom center;
  transition: border-color .18s, filter .18s, transform .18s, box-shadow .18s;
}
.commit-card:hover:not(.inert) .card-fax { transform: translateY(-24px) scale(2.3); box-shadow: 0 16px 44px rgba(0, 0, 0, .85); }
.commit-card.inert .card-fax { filter: grayscale(.75) brightness(.5); }
.commit-card.selected .card-fax { border-color: var(--candle); box-shadow: 0 0 22px rgba(224, 162, 68, .5); transform: translateY(-10px); }
.commit-card.selected:hover .card-fax { transform: translateY(-24px) scale(2.3); }

.ip-thumb .card-fax { width: 52px; transition: border-color .15s, transform .15s; }
.ip-thumb:hover .card-fax { border-color: var(--candle); transform: scale(1.1); }

.choice-opt .card-fax.opt-art { width: 108px; }

.card-preview .card-fax {
  width: 100%;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .95), 0 0 30px rgba(224, 162, 68, .12);
}

/* full-size inspect (zoom overlay) */
.overlay-zoom .card-fax-zoom {
  width: min(430px, 86vw, calc(82vh * 5 / 7));
  border-radius: 14px;
  box-shadow: 0 0 90px rgba(0, 0, 0, 1), 0 0 40px rgba(224, 162, 68, .12);
  animation: sheet-in .25s ease both;
  cursor: default;
}

/* presentation overlay: the fax fills the .present-card slot */
.present-card-fax { box-shadow: none; }
.present-card-fax .card-fax {
  width: 100%;
  border-radius: 14px;
  box-shadow: 0 0 90px rgba(0, 0, 0, 1), 0 0 44px rgba(224, 162, 68, .14);
}

/* Long deck-building backs: the zoomed facsimile body scrolls instead of
   clipping (wheel-scroll only — clicks still close the overlay). */
.overlay-zoom .card-fax-zoom .fax-body { overflow-y: auto; }

/* ============================================================
   PHONE LAYOUT (390px / 375px)
   The desktop board keeps its three-column investigator panel and right rail.
   Phones get a deliberately vertical reading order, with the few dense zones
   (hand, board, chronicle, and sheets) scrolling inside their own bounds.
   ============================================================ */

@media (max-width: 600px) {
  html, body { min-width: 0; }
  body { overflow-x: hidden; overflow-y: auto; }

  /* --- landing --- */
  #landing {
    display: block;
    overflow-x: hidden;
    overflow-y: auto;
  }
  .landing-inner {
    width: 100%;
    max-width: none;
    padding: 30px 16px 40px;
  }
  .landing-kicker {
    font-size: 10px;
    line-height: 1.5;
    letter-spacing: .2em;
    overflow-wrap: anywhere;
  }
  .landing-title {
    /* 8.6vw keeps "LOVECRAFTIAN" on one line at 375px (was breaking mid-word) */
    font-size: clamp(28px, 8.6vw, 46px);
    letter-spacing: .06em;
    overflow-wrap: normal;
  }
  .landing-title span { letter-spacing: .16em; }
  .landing-sub {
    font-size: 18px;
    line-height: 1.35;
    overflow-wrap: anywhere;
  }
  .landing-date {
    font-size: 11px;
    line-height: 1.4;
    letter-spacing: .1em;
  }
  .landing-body {
    display: block;
    width: 100%;
    margin: 24px 0 20px;
  }
  .landing-form {
    width: 100%;
    min-width: 0;
    padding: 18px 16px;
  }
  .landing-form fieldset { min-width: 0; }
  .difficulty { margin-bottom: 14px; }
  .diff-opt {
    display: inline-flex;
    max-width: 100%;
    margin: 0 3px 6px 0;
    vertical-align: top;
  }
  .diff-opt span {
    max-width: 100%;
    padding: 6px 9px;
    text-align: center;
    overflow-wrap: anywhere;
  }
  .seat-hint { font-size: 11px; line-height: 1.45; }
  .seat-head { gap: 6px 9px; }
  .seat-mode { font-size: 11.5px; }
  .seat-body { gap: 8px; }
  .seat-preset { font-size: 12px; }
  .seat-neardead, .seat-gate { line-height: 1.45; }
  .seed-row {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 8px;
  }
  .seed-row select { flex: 1 1 160px; min-width: 0; }
  .landing-flavor { font-size: 13px; line-height: 1.55; }
  .landing-continue .continue-row {
    align-items: flex-start;
    flex-wrap: wrap;
  }
  .landing-continue .continue-row span { flex: 1 1 100%; }

  /* --- app frame and vertical board order --- */
  .app {
    height: auto;
    min-height: 100vh;
    /* #panel-divider is display:none here, so #invpanel is the THIRD grid
       item — a 0 row would collapse the whole investigator footer to 1px and
       let the plaque overlap the action bar (director, 2026-09-03). */
    grid-template-rows: auto auto auto;
  }
  #panel-divider { display: none; }
  .stage {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    min-width: 0;
  }
  #viewport {
    min-width: 0;
    min-height: clamp(430px, 60vh, 540px);
  }

  /* The chronicle is a compact disclosure below the room instead of a fixed
     160px competing column. Its log retains its own scroll when opened. */
  #rail {
    height: 42px;
    min-height: 42px;
    border-left: none;
    border-top: 1px solid var(--edge);
    overflow: hidden;
  }
  #rail.open {
    height: min(52vh, 420px);
    min-height: 42px;
  }
  #rail .rail-title {
    display: flex;
    align-items: center;
    flex: none;
    height: 42px;
    justify-content: space-between;
    padding: 0 14px;
    text-align: left;
    cursor: pointer;
  }
  #rail .rail-title::before, #rail .rail-title::after { content: none; }
  .rail-toggle {
    display: inline-block;
    color: var(--candle);
    font-size: 18px;
    line-height: 1;
    transition: transform .2s ease;
  }
  #rail.open .rail-toggle { transform: rotate(90deg); }
  #rail #log {
    display: none;
    min-height: 0;
    padding: 10px 14px 16px;
  }
  #rail.open #log { display: block; }

  /* Keep all HUD groups inside the narrow viewport; piles may wrap but never
     establish a horizontal page overflow. */
  #hud {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 7px 9px;
    padding: 8px 12px;
    min-width: 0;
  }
  .hud-left { grid-column: 1; grid-row: 1; min-width: 0; }
  .hud-title-row { min-width: 0; flex-wrap: wrap; }
  .hud-brand {
    min-width: 0;
    max-width: 100%;
    font-size: 12px;
    letter-spacing: .1em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .hud-invs {
    grid-column: 1 / -1;
    grid-row: 2;
    min-width: 0;
    flex-wrap: wrap;
    gap: 5px;
  }
  .hud-inv { min-width: 0; }
  .hud-inv-stats { gap: 4px; font-size: 10px; }
  .phases {
    grid-column: 2;
    grid-row: 1;
    margin-right: 0;
    justify-self: end;
  }
  .hud-right {
    grid-column: 1 / -1;
    grid-row: 3;
    min-width: 0;
    width: 100%;
    justify-content: space-between;
    gap: 5px 7px;
    flex-wrap: wrap;
  }
  .hud-card img { width: 64px; height: 46px; }
  .hud-card.ghost { width: 64px; height: 60px; }
  .hud-pile label { font-size: 7.5px; letter-spacing: .1em; }

  /* The location card remains the room's focal point. Names and chips use the
     space not occupied by the compact map; figures get a scrollable strip. */
  .loc-banner {
    top: 16px;
    left: 16px;
    right: 16px;
    max-width: none;
  }
  .loc-banner h1 {
    max-width: calc(100% - 150px);
    font-size: clamp(20px, 7vw, 30px);
    line-height: 1.08;
    overflow-wrap: anywhere;
  }
  .loc-chips {
    max-width: calc(100% - 150px);
    gap: 4px;
  }
  .loc-chips .chip { font-size: 10px; padding: 2px 6px; }
  .minimap.mini {
    top: 12px;
    right: 12px;
    width: 136px;
    height: 104px;
  }
  .minimap.expanded {
    top: 14px;
    right: 12px;
    width: min(420px, calc(100% - 24px));
    height: min(330px, calc(100% - 28px));
  }
  .figures {
    position: absolute;
    left: 12px;
    right: 12px;
    top: 156px;
    bottom: 92px;
    max-width: none;
    padding: 0;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-content: flex-start;
    align-items: flex-start;
    overflow-x: hidden;
    overflow-y: auto;
    gap: 8px;
  }
  .figure {
    width: min(138px, calc(50% - 6px));
    flex: 0 0 auto;
  }
  .figure-art { height: 88px; }
  .exits {
    bottom: 12px;
    justify-content: flex-start;
    gap: 8px;
    padding: 0 10px;
    overflow-x: auto;
  }
  .door { width: 108px; flex: 0 0 108px; padding: 8px 6px; }
  .door-name { font-size: 12px; }

  /* The investigator footer reads hand → in-play cards → investigator plaque.
     The hand has horizontal scrolling; the board's own vertical scroll keeps
     a large asset collection from making the whole footer unusable. */
  #invpanel { min-width: 0; }
  .inv-tabs {
    min-width: 0;
    overflow-x: auto;
    padding: 5px 10px 0;
  }
  .inv-tab { flex: 0 0 auto; }
  .action-bar {
    align-items: flex-start;
    gap: 6px;
    padding: 8px 12px;
  }
  .turn-status {
    flex: 1 0 100%;
    margin-right: 0;
    font-size: 12px;
  }
  .btn-end { margin-left: 0; }
  .panel-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 10px 12px 18px;
  }
  .hand-zone { order: 1; flex: 0 0 auto; }
  .board-zone {
    order: 2;
    flex: 0 0 auto;
    max-height: min(220px, 28vh);
    overflow-y: auto;
  }
  .plaque {
    order: 3;
    flex: 0 0 auto;
    align-items: flex-start;
    gap: 8px;
  }
  .portrait { width: 112px; height: 80px; }
  .plaque-info { min-width: 0; }
  .plaque-info h3 { font-size: 15px; margin-bottom: 4px; }
  .vital { align-items: flex-start; gap: 6px; }
  .vital label { width: 40px; }
  .pips { display: flex; flex-wrap: wrap; max-width: 170px; }
  .hand {
    width: 100%;
    height: 116px;
    min-height: 116px;
    align-items: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 4px 16px 0 8px;
  }
  .hand-card { flex: 0 0 76px; margin-left: -18px; }
  .hand-card:first-child { margin-left: 0; }
  .hand-hit { width: 76px; }
  .hand-visual img { width: 76px; }
  .hand-visual .card-fax { width: 76px; }
  .hand-card:hover .hand-visual { transform: rotate(calc((var(--i) - 3) * 1.4deg)); }
  .board-cards { gap: 7px; }
  .mini-card { width: 62px; }

  /* --- touch-sized full-width sheets --- */
  .overlay {
    padding: 0;
    place-items: stretch;
    overflow: hidden;
  }
  .sheet, .test-sheet, .token-scene, .end-scroll {
    width: 100%;
    min-width: 0;
    max-width: none;
    max-height: none;
    min-height: 100%;
    border-radius: 0;
    border-left: none;
    border-right: none;
    padding: 20px 16px;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .choice-sheet { height: 100%; }
  .choice-grid { gap: 8px; }
  .choice-grid.with-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .choice-opt {
    width: 100%;
    min-width: 0;
    max-width: none;
    padding: 8px 6px;
    overflow-wrap: anywhere;
  }
  .choice-opt .opt-art,
  .choice-opt .card-fax.opt-art {
    width: min(136px, 100%);
    max-width: 100%;
  }
  .opt-label, .opt-detail { max-width: 100%; overflow-wrap: anywhere; }
  .choice-footer { flex-wrap: wrap; gap: 8px; }
  .choice-footer .btn { max-width: 100%; }

  .overlay-test {
    place-items: stretch;
    overflow: hidden;
  }
  .test-sheet {
    height: 100%;
    padding: 16px;
  }
  .test-head { align-items: flex-start; flex-wrap: wrap; gap: 10px; }
  .test-peek { display: none; }
  .test-title { min-width: 0; flex: 1 1 180px; }
  .test-body { display: flex; flex-direction: column; gap: 12px; }
  .test-source { width: 100%; flex-direction: row; align-items: flex-start; }
  .test-source-card img { width: 110px; }
  .test-source-note { align-self: center; }
  .test-main { width: 100%; }
  .commit-hand {
    justify-content: flex-start;
    flex-wrap: nowrap;
    overflow-x: auto;
    min-height: 116px;
  }
  .commit-card { flex: 0 0 auto; }
  .bag-ref { width: 100%; max-height: 180px; }
  .test-footer { flex-direction: column; align-items: stretch; gap: 8px; }
  .btn-reveal { width: 100%; }

  .token-scene {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
  }
  .token-coin { width: 104px; height: 104px; flex: none; }
  .token-glyph { font-size: 42px; }
  .token-effect, .token-math { max-width: 100%; overflow-wrap: anywhere; }

  .overlay-present {
    padding: 16px;
    place-items: start center;
    overflow-y: auto;
  }
  .present-inner {
    width: min(100%, 358px);
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
    margin: auto 0;
  }
  .present-card {
    width: min(180px, 54vw);
    max-width: 100%;
    max-height: 32vh;
    align-self: center;
    object-fit: contain;
  }
  .present-name {
    font-size: clamp(22px, 7vw, 30px);
    overflow-wrap: anywhere;
  }
  .present-flavor {
    max-height: 24vh;
    overflow-y: auto;
  }
  .present-rules { max-height: 21vh; }
  .present-bar { flex-wrap: wrap; gap: 8px; }

  .encounter-flash {
    padding: 16px;
    place-items: stretch;
    overflow-y: auto;
  }
  .encounter-inner {
    width: 100%;
    min-height: 100%;
    justify-content: center;
    gap: 12px;
  }
  .encounter-inner img {
    width: 100%;
    max-width: 100%;
    max-height: 62vh;
    object-fit: contain;
  }
  .encounter-cap { font-size: 12px; line-height: 1.35; letter-spacing: .2em; }
  .encounter-continue { width: 100%; }

  .overlay-zoom { padding: 16px; overflow-y: auto; }
  .zoom-card { max-width: 100%; max-height: 78vh; }
  .overlay-zoom .card-fax-zoom { width: min(430px, 100%, calc(78vh * 5 / 7)); }
  .zoom-bar { flex-wrap: wrap; gap: 8px; }
  .zoom-hint { max-width: 100%; overflow-wrap: anywhere; }

  .end-scroll { padding: 32px 16px; }
  .end-title { font-size: clamp(28px, 8vw, 40px); overflow-wrap: anywhere; }
}
