/* DUNGEON RUN component styles: wet stone, torchlight, iron, dirt. The bar for this look is art_target.html.
   Every color, shadow, surface, type size, spacing step and timing value comes from tokens.css (DESIGN.md
   section 8). The only literals left here are structure: keyframe stops, grid tracks, 0 / 50% / 100%
   placement, and media/container query breakpoints, which CSS does not allow to be custom properties. */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  color: var(--color-text);
  font-family: var(--font-text);
  font-size: var(--type-md);
  line-height: var(--leading-text);
  font-variant-numeric: tabular-nums lining-nums;
  background: var(--surface-room);
  background-color: var(--color-void);
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  touch-action: manipulation;
}

/* The room: noise over the stone, and a vignette that drops every edge into the dark (DESIGN.md sections 1, 3). */
body::before, body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
}
body::before {
  background: var(--texture-noise);
  background-size: var(--texture-noise-size);
  mix-blend-mode: var(--blend-noise);
  opacity: var(--opacity-noise-room);
}
body::after { box-shadow: var(--shadow-vignette); }

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  touch-action: manipulation;
}

b { font-weight: var(--weight-heavy); }

.sprite-sheet { position: absolute; width: 0; height: 0; overflow: hidden; }
.icon { width: var(--icon-sm); height: var(--icon-sm); flex: none; }

/* Grain: every built surface gets a layer of noise beneath its content (DESIGN.md section 3). */
.hud, .field, .log, .pile, .card, .big-button, .intent, .outcome .panel, .boot pre,
.board, .slab, .sheet, .map, .plain-button, .choice, .companion, .call-toggle, .key, .relic, .ladder li {
  position: relative;
  isolation: isolate;
}
.hud::before, .field::before, .log::before, .pile::before, .card::before,
.big-button::before, .intent::before, .outcome .panel::before, .boot pre::before,
.board::before, .slab::before, .sheet::before, .map::before, .plain-button::before, .choice::before,
.companion::before, .call-toggle::before, .key::before, .relic::before, .ladder li::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--surface-grain, var(--texture-noise));
  background-size: var(--surface-grain-size, var(--texture-noise-size));
  mix-blend-mode: var(--blend-noise);
  opacity: var(--surface-grain-opacity, var(--opacity-noise));
  pointer-events: none;
}

.app {
  position: fixed;
  inset: 0;
  z-index: var(--z-app);
  padding:
    max(var(--space-2), env(safe-area-inset-top))
    max(var(--space-2), env(safe-area-inset-right))
    max(var(--space-2), env(safe-area-inset-bottom))
    max(var(--space-2), env(safe-area-inset-left));
}

/* ---------- Boot / error ---------- */

.boot {
  height: 100%;
  display: grid;
  place-items: center;
  padding: var(--space-7);
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--type-xl);
  color: var(--color-text-dim);
}
.boot h1 {
  margin: 0 0 var(--space-6);
  font-size: var(--type-3xl);
  font-weight: var(--weight-display);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.boot pre {
  margin: 0 auto;
  max-width: var(--measure);
  padding: var(--space-6) var(--space-7);
  text-align: left;
  white-space: pre-wrap;
  font: var(--weight-text) var(--type-md) / var(--leading-text) var(--font-text);
  color: var(--color-text);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  -webkit-user-select: text;
  user-select: text;
}

/* ---------- Combat layout ----------
   Landscape (primary): HUD over the board with the log beside it, then controls and the hand.
   Portrait: the board keeps a steady height; the log takes what is left, so a tall hand squeezes the log, not the fight. */

.combat {
  height: 100%;
  display: grid;
  gap: var(--gap-region);
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto var(--field-h-portrait) minmax(var(--log-min-h), 1fr) auto auto;
  grid-template-areas: "hud" "field" "log" "controls" "hand";
}
.combat.log-collapsed { grid-template-rows: auto minmax(0, 1fr) auto auto auto; }
.hud { grid-area: hud; }
.field { grid-area: field; }
.log { grid-area: log; }
.controls { grid-area: controls; }
.hand { grid-area: hand; }

@media (orientation: landscape) {
  .combat {
    grid-template-columns: minmax(0, 1fr) var(--log-w);
    grid-template-rows: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "hud hud" "field log" "controls controls" "hand hand";
  }
  .combat.log-collapsed {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr) auto auto;
  }
}

/* ---------- HUD: a stone ledge, lit from the left ---------- */

.hud {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  min-height: var(--tap);
  padding: var(--space-1) var(--space-5);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
}
/* The ledge's light flickers in steps, like the torch above it. */
.hud::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--surface-hud-light);
  pointer-events: none;
  animation: torch-flicker var(--dur-torch-flicker) steps(1, end) var(--ambient-delay) infinite;
}
.hud .title {
  margin: 0 auto 0 0;
  font-family: var(--font-display);
  font-size: var(--type-3xl);
  font-weight: var(--weight-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.hud .turn {
  font-family: var(--font-display);
  font-size: var(--type-lg);
  letter-spacing: var(--tracking-label);
  color: var(--color-text-faint);
}
.hud .turn b { color: var(--color-text-dim); font-family: var(--font-text); }

.stat {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap);
  padding-left: var(--space-5);
  border-left: var(--hairline) solid var(--color-mortar);
  box-shadow: var(--shadow-carved-divider);
}
.stat .icon { width: var(--icon-md); height: var(--icon-md); }
.stat b {
  font-size: var(--type-2xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
  text-shadow: var(--shadow-number-glow), var(--shadow-text-ink);
}
.stat .of { font-size: var(--type-sm); color: var(--color-text-faint); }
.stat .cap {
  font-family: var(--font-display);
  font-size: var(--type-xs);
  letter-spacing: var(--tracking-label);
  color: var(--color-text-faint);
}
.stat.hp .icon { color: var(--color-blood); filter: var(--filter-glow-blood); }
.stat.hp b { color: var(--color-hp-text); }
.stat.block .icon, .stat.block b { color: var(--color-steel); }
.stat.gold .icon { color: var(--color-flame); }
.stat.gold b { color: var(--color-elemental); }
.stat.breaths .icon, .stat.breaths b { color: var(--color-necromancy); }
.stat.deck-button .icon { color: var(--color-text-dim); }
.stat.relics .icon { color: var(--color-gilt); }

/* Companions: a seal per companion in its school's color. */
.stat.allies { gap: var(--space-2); }
.medallion {
  width: var(--medallion-size);
  height: var(--medallion-size);
  flex: none;
  padding: var(--space-1);
  border-radius: var(--radius-wax);
  background: var(--color-page-low);
  color: var(--companion-color);
  box-shadow: var(--shadow-medallion);
}
.medallion svg { display: block; width: 100%; height: 100%; }
button.stat { background: none; border-top: 0; border-right: 0; border-bottom: 0; }
button.stat:active { transform: translateY(var(--press-depth)); }
button.stat:disabled { filter: var(--filter-unlit); }

/* Energy is lit while you have it, and goes dark when it's spent. */
.orb {
  width: var(--orb-size);
  height: var(--orb-size);
  display: grid;
  place-items: center;
  border-radius: var(--radius-wax);
  background: var(--surface-wax);
  box-shadow: var(--shadow-seal), var(--glow-torch);
}
.orb b { font-size: var(--type-2xl); color: var(--color-text-on-fire); text-shadow: none; }
.stat.energy.spent .orb { background: var(--color-stone-deep); box-shadow: var(--shadow-niche); }
.stat.energy.spent .orb b { color: var(--color-text-faint); }

/* ---------- The board: recessed stone, lit by two wall torches ---------- */

.field {
  /* How wide one creature may be: the board split by how many share it. */
  --slot-w: calc(100cqw / (var(--units, 1) + var(--bosses, 0) * var(--span-boss-extra)) - var(--slot-gutter));
  --slot-w-boss: calc(var(--slot-w) * var(--span-boss));
  /* ...and how tall: the board's height, less the intent tag, name and health bar around a creature. */
  --slot-h: calc(100cqh - var(--unit-chrome));
  container-type: size;
  min-height: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-5) var(--field-pad-x) var(--space-6);
  overflow: hidden;
  clip-path: var(--chipped-corners);
  background: var(--surface-field);
  background-size: var(--surface-field-size);
  box-shadow: var(--shadow-board);
}

/* The boss's open room: the shard in the crab's shell throws its own violet light across the floor. */
.field[data-room="boss"] {
  background: var(--surface-field-boss);
  background-size: var(--surface-field-boss-size);
}

/* Wall torches. The pool of light each one throws is its own layer so it can flicker. */
.torch {
  position: absolute;
  top: var(--torch-top);
  width: var(--torch-w);
  height: var(--torch-h);
  color: var(--color-iron-dark);
  pointer-events: none;
}
.torch::before {
  content: "";
  position: absolute;
  left: 50%;
  top: var(--torch-glow-center);
  z-index: -1;
  width: var(--torch-glow-size);
  height: var(--torch-glow-size);
  translate: -50% -50%;
  border-radius: var(--radius-round);
  background: radial-gradient(closest-side, var(--falloff-flame));
  animation:
    flicker var(--dur-flicker) var(--ease-ambient) var(--ambient-delay) infinite,
    sway var(--dur-sway) var(--ease-ambient) var(--ambient-delay) infinite;
}
.torch .sconce, .torch .flame { position: absolute; inset: 0; width: 100%; height: 100%; }
.torch .flame {
  transform-origin: 50% var(--torch-flame-base);
  animation:
    flame-dance var(--dur-flame) var(--ease-ambient) var(--ambient-delay) infinite,
    flicker var(--dur-flame-fade) var(--ease-ambient) var(--ambient-delay) infinite;
}
/* The right-hand torch burns out of step with the left. */
.torch.right::before, .torch.right .flame { animation-delay: calc(var(--ambient-delay) - var(--torch-stagger)); }
.torch.left { left: var(--torch-inset); }
.torch.right { right: var(--torch-inset); }
.side { display: flex; align-items: flex-end; gap: var(--space-6); }
.foes { justify-content: flex-end; }

.unit {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  min-width: min(var(--unit-min-w), var(--slot-w));
  max-width: var(--slot-w);
  padding: var(--space-4) var(--space-4) var(--space-5);
  border: var(--rule) solid transparent;
  border-radius: var(--radius-worn-3);
  background: transparent;
  transition: box-shadow var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
/* A valid target is lit, not boxed: a pool of torchlight under it and a warm rim. */
.unit.targetable {
  border-color: var(--color-torch);
  background: var(--surface-target-pool);
  box-shadow: var(--glow-target);
}
.unit.targetable .sprite { filter: var(--filter-lit) var(--filter-sprite); }

/* A boss is given a wider slot than anything else on the board. */
.unit[data-tier="boss"] { --slot-w: var(--slot-w-boss); }

/* Summons stand on your side, facing the enemy. A summon picked up for new orders is lit green. */
.unit.summon { min-width: min(var(--summon-min-w), var(--slot-w)); }

/* A crowded board (six or more creatures) tightens every creature's tag, name and bar.
   The intent's target always stays: the player plans around it. */
.field:is([data-units="6"], [data-units="7"], [data-units="8"], [data-units="9"], [data-units="10"], [data-units="11"], [data-units="12"]) {
  --unit-chrome: var(--unit-chrome-crowded);
}
.field:is([data-units="6"], [data-units="7"], [data-units="8"], [data-units="9"], [data-units="10"], [data-units="11"], [data-units="12"]) .unit {
  padding: var(--space-2) var(--space-1);
}
.field:is([data-units="6"], [data-units="7"], [data-units="8"], [data-units="9"], [data-units="10"], [data-units="11"], [data-units="12"]) .intent {
  padding: var(--space-1) var(--space-2);
  font-size: var(--type-lg);
}
.field:is([data-units="6"], [data-units="7"], [data-units="8"], [data-units="9"], [data-units="10"], [data-units="11"], [data-units="12"]) :is(.intent .who, .intent .what, .hpbar .label) {
  font-size: var(--type-xs);
}
.field:is([data-units="6"], [data-units="7"], [data-units="8"], [data-units="9"], [data-units="10"], [data-units="11"], [data-units="12"]) .name {
  font-size: var(--type-sm);
}
.unit.summon .sprite { color: var(--color-risen); filter: var(--filter-risen) var(--filter-sprite); }
.unit.summon .sprite use { transform: var(--mirror); transform-box: view-box; transform-origin: 50% 50%; }
.unit.selected {
  border-color: var(--color-necromancy);
  background: var(--surface-risen-pool);
  box-shadow: var(--glow-summon-selected);
}

/* The creature's body. Damage numbers rise from it, below the intent tag, so the two numbers never mix. */
.figure { position: relative; display: block; }
.sprite {
  --breathe: breathe var(--breathe-dur, var(--dur-breathe)) var(--ease-ambient) var(--ambient-delay) infinite alternate;
  width: min(calc(var(--sprite-h, var(--sprite-h-default)) * var(--sprite-aspect, var(--aspect-default))), var(--slot-w));
  max-height: calc(var(--slot-h) - var(--extra-chips, 0) * var(--chip-row-h) - var(--extra-tags, 0) * var(--tag-row-h));
  height: auto;
  aspect-ratio: var(--sprite-aspect, var(--aspect-default));
  color: var(--color-iron);
  filter: var(--filter-sprite);
  transform-origin: 50% 100%;
  animation: var(--breathe);
}
.sprite[data-sprite="player"] { --sprite-h: var(--sprite-h-player); --sprite-aspect: var(--aspect-player); --breathe-dur: var(--dur-breathe-player); color: var(--color-robe); }
.sprite[data-sprite="dungeon_rat"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-rat); color: var(--color-vermin); }
.sprite[data-sprite="cave_bat"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-bat); color: var(--color-bat); }
.sprite[data-sprite="blood_mote"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-mote); color: var(--color-blood); }
.sprite[data-sprite="barnacle"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-barnacle); color: var(--color-ash); }
.sprite[data-sprite="powder_wretch"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-wretch); color: var(--color-hide); }
.sprite[data-sprite="blood_blob"] { --sprite-h: var(--sprite-h-small); --sprite-aspect: var(--aspect-blob); color: var(--color-blood); }
.sprite[data-sprite="goblin_shaman"] { --sprite-h: var(--sprite-h-small); --sprite-aspect: var(--aspect-shaman); color: var(--color-goblin); }
.sprite[data-sprite="bone_skeleton"], .sprite[data-sprite="skeleton"] { --sprite-h: var(--sprite-h-medium); --sprite-aspect: var(--aspect-skeleton); color: var(--color-bones); }
.sprite[data-sprite="bone_wall"] { --sprite-h: var(--sprite-h-medium); --sprite-aspect: var(--aspect-bone-wall); color: var(--color-bones); }
.sprite[data-sprite="torch_wraith"] { --sprite-h: var(--sprite-h-medium); --sprite-aspect: var(--aspect-wraith); color: var(--color-wraith); }
.sprite[data-sprite="goblin_shieldbearer"] { --sprite-h: var(--sprite-h-medium); --sprite-aspect: var(--aspect-shieldbearer); color: var(--color-goblin); }
.sprite[data-sprite="goblin_brute"] { --sprite-h: var(--sprite-h-large); --sprite-aspect: var(--aspect-brute); color: var(--color-goblin); }
.sprite[data-sprite="the_leech"] { --sprite-h: var(--sprite-h-large); --sprite-aspect: var(--aspect-leech); color: var(--color-flesh); }
.sprite[data-sprite="iron_torturer"] { --sprite-h: var(--sprite-h-elite); --sprite-aspect: var(--aspect-torturer); color: var(--color-hide); }
.sprite[data-sprite="the_questioner"] { --sprite-h: var(--sprite-h-elite); --sprite-aspect: var(--aspect-questioner); color: var(--color-inquisitor); }
.sprite[data-sprite="corrupted_crab"] { --sprite-h: var(--sprite-h-boss); --sprite-aspect: var(--aspect-crab); color: var(--color-shell); }
.sprite[data-sprite="cellar_spider"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-spider); color: var(--color-spider); }
.sprite[data-sprite="dungeon_hound"] { --sprite-h: var(--sprite-h-vermin); --sprite-aspect: var(--aspect-hound); color: var(--color-hound); }
.sprite[data-sprite="ghoul"] { --sprite-h: var(--sprite-h-medium); --sprite-aspect: var(--aspect-ghoul); color: var(--color-ghoul); }
.sprite[data-sprite="hooded_acolyte"] { --sprite-h: var(--sprite-h-large); --sprite-aspect: var(--aspect-acolyte); color: var(--color-acolyte); }
.sprite[data-sprite="kennel_master"] { --sprite-h: var(--sprite-h-elite); --sprite-aspect: var(--aspect-kennel); color: var(--color-hide); }
/* A summon the crab's beam stole: it stands with the enemy now, in the shard's violet. */
.unit.stolen .sprite { color: var(--color-stolen); filter: var(--filter-stolen) var(--filter-sprite); }

.name {
  font-family: var(--font-display);
  font-size: var(--type-lg);
  font-weight: var(--weight-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-label);
  color: var(--color-bones);
  text-shadow: var(--shadow-text-ink);
}
.vitals { display: flex; align-items: center; gap: var(--space-2); width: 100%; }
.hpbar {
  position: relative;
  flex: 1;
  min-width: min(var(--hpbar-min-w), var(--slot-w));
  height: var(--hpbar-h);
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radius-chip);
  background: var(--color-blood-deep);
  box-shadow: var(--shadow-hpbar);
}
.hpbar .fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--hp-frac) * 100%);
  background: var(--surface-blood);
}
/* The HP just lost, shown in pale ember behind the bar until the bar has drained past it. */
.hpbar .loss {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--hp-frac) * 100%);
  background: var(--color-hp-loss);
}
.unit.fx-hit .hpbar .fill, .unit.fx-heal .hpbar .fill { animation: drain var(--dur-drain) var(--ease-out); }
.unit.fx-hit .hpbar .loss { animation: drain var(--dur-loss) var(--ease-in) var(--dur-loss-hold) backwards; }
.unit.fx-heal .hpbar .loss { visibility: hidden; }

/* Damage number: what the hit did, after it resolved. Punches out, rises, falls away. */
.damage-number {
  position: absolute;
  left: 50%;
  top: var(--number-top);
  z-index: var(--z-number);
  translate: -50% 0;
  font-size: var(--type-3xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
  color: var(--color-blood-bright);
  text-shadow: var(--shadow-number);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  animation: number-pop var(--dur-number) var(--ease-out) calc(var(--order) * var(--dur-number-stagger)) both;
}
.damage-number.blocked { font-size: var(--type-2xl); color: var(--color-iron); text-shadow: var(--shadow-number-blocked); }
.hpbar .label {
  position: relative;
  font-size: var(--type-sm);
  font-weight: var(--weight-heavy);
  text-shadow: var(--shadow-text-carved);
}
.block-badge {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: var(--badge-size);
  height: var(--badge-size);
}
.block-badge .icon {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--color-iron);
  filter: var(--filter-raised);
}
.block-badge b { position: relative; font-size: var(--type-sm); color: var(--color-pitch); }

/* Intent: a bronze tag hung above the creature, lit by the torches. Icon, number, target: the player plans
   around it. A long target name wraps onto a second line once the tag reaches its cap, so it never pushes
   off the board. */
.intent {
  max-width: min(var(--intent-max-w), var(--slot-w));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 var(--space-2);
  text-align: center;
  padding: var(--space-1) var(--space-4);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-tag);
  background: var(--surface-intent);
  box-shadow: var(--shadow-tag), var(--shadow-ledge);
  font-family: var(--font-display);
  font-size: var(--type-lg);
  letter-spacing: var(--tracking-label);
  line-height: var(--leading-snug);
  color: var(--color-vellum-bright);
}
.intent .icon { width: var(--icon-md); height: var(--icon-md); color: var(--intent-number); }
.intent b {
  font-family: var(--font-text);
  font-size: var(--type-2xl);
  font-weight: var(--weight-heavy);
  letter-spacing: 0;
  color: var(--intent-number);
  text-shadow: var(--shadow-text-blood);
}
.intent .arrow { font-family: var(--font-text); color: var(--color-text-faint); }
.intent .who { font-size: var(--type-md); color: var(--color-bones); }
.intent .who.you { color: var(--color-hp-text); }
.intent .who.summon { color: var(--color-necromancy); }
.intent .what { font-size: var(--type-sm); text-transform: capitalize; color: var(--color-text-dim); }
.intent .times { font-family: var(--font-text); font-size: var(--type-md); color: var(--color-text-dim); }
.intent.guard { --intent-number: var(--color-steel); border-color: var(--color-iron-dark); }
.intent.guard b { text-shadow: var(--shadow-text-carved); }
.intent.scheme { --intent-number: var(--color-scheme-number); border-color: var(--color-darkhold); box-shadow: var(--glow-scheme), var(--shadow-ledge); }
.intent.scheme b { text-shadow: var(--shadow-text-scheme); }

/* A timed ability on the turn it fires (the crab's beam): hung above the intent, lit by the shard. */
.intent.beam { --intent-number: var(--color-scheme-number); border-color: var(--color-darkhold); box-shadow: var(--glow-beam), var(--shadow-ledge); }
.intent.beam .icon { color: var(--color-darkhold); }
.intent.beam b, .intent.beam .who { text-shadow: var(--shadow-text-beam); }
.intent.beam .what { text-transform: none; color: var(--color-text); }

/* Status chips: small bronze-rimmed plates under the health bar. */
.statuses { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); }
.chip {
  padding: var(--space-1) var(--space-3);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-chip);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-ledge);
  font-family: var(--font-display);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking-label);
  text-transform: capitalize;
  color: var(--color-text);
}
.chip.trait { font-family: var(--font-text); font-style: italic; letter-spacing: 0; text-transform: none; border-color: var(--color-darkhold); color: var(--color-text-dim); }
/* Counters the player plans around: the armor's hits left, the turns until the beam. */
.chip.armor { text-transform: none; border-color: var(--color-steel-edge); background: var(--color-steel-plate); color: var(--color-steel); }
.chip.armor.broken { color: var(--color-text-faint); border-color: var(--color-iron-dark); background: var(--surface-plaque); text-decoration: line-through; }
.chip.countdown { text-transform: none; border-color: var(--color-darkhold); box-shadow: var(--shadow-ledge), var(--glow-scheme); color: var(--color-countdown); }

/* Encrusted Armor: each barnacle that comes off drops and spins away from the shell. */
.armor-piece { transform-box: fill-box; transform-origin: 50% 100%; }
.armor-piece.shed { animation: shed var(--dur-shed) var(--ease-in) forwards; }

/* Feedback. Every duration is a token, and every token is 400ms or less. */
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(calc(var(--shake-distance) * -1)); }
  40% { transform: translateX(var(--shake-distance)); }
  60% { transform: translateX(calc(var(--shake-settle) * -1)); }
  80% { transform: translateX(var(--shake-settle)); }
}
@keyframes flash-hurt { from { filter: var(--filter-hurt); } to { filter: none; } }
@keyframes flash-heal { from { filter: var(--filter-healed); } to { filter: none; } }
@keyframes pop { 45% { transform: scale(var(--pop-scale)); } }
@keyframes die { to { opacity: 0; transform: translateY(var(--die-drop)) scale(var(--die-scale)); } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes drain { from { width: calc(var(--hp-from) * 100%); } }
@keyframes shed { to { opacity: 0; transform: translateY(var(--shed-drop)) rotate(var(--shed-spin)); } }
@keyframes flash-beam { from { filter: var(--filter-beam); } to { filter: none; } }
@keyframes flash-armor-break { from { filter: var(--filter-armor-break); } to { filter: none; } }
@keyframes taken {
  from { opacity: 1; filter: var(--filter-taken); }
  to { opacity: 0; filter: var(--filter-taken); transform: translateY(var(--taken-rise)) scale(var(--die-scale)); }
}
@keyframes number-pop {
  0% { opacity: 0; transform: translateY(0) scale(var(--number-scale-start)); }
  18% { opacity: 1; transform: translateY(calc(var(--number-punch-rise) * -1)) scale(var(--number-scale-punch)); }
  55% { opacity: 1; transform: translateY(calc(var(--number-rise) * -1)) scale(1); }
  100% { opacity: 0; transform: translateY(calc(var(--number-fall) - var(--number-rise))) scale(var(--number-scale-end)); }
}

/* Feedback runs alongside breathing: shake moves `transform`, breathing moves `scale`, so they combine. */
.unit.fx-hit .sprite { animation: shake var(--dur-hit) var(--ease-out), flash-hurt var(--dur-hit) var(--ease-out), var(--breathe); }
.unit.fx-guard .sprite { animation: shake var(--dur-fast) var(--ease-out), var(--breathe); }
.unit.fx-heal .sprite { animation: flash-heal var(--dur-hit) var(--ease-out), var(--breathe); }
.unit.fx-block .block-badge { animation: pop var(--dur-med) var(--ease-punch); }
.unit.fx-die { animation: die var(--dur-die) var(--ease-in) forwards; pointer-events: none; }
/* The beam fired: the crab's whole body flares violet. A summon it took is drawn up and away, not killed. */
.unit.fx-beam .figure { animation: flash-beam var(--dur-hit) var(--ease-out); }
.unit.fx-armor-break .figure { animation: flash-armor-break var(--dur-hit) var(--ease-out); }
.unit.fx-taken { animation: taken var(--dur-die) var(--ease-in) forwards; pointer-events: none; }

/* ---------- Ambient keyframes: irregular steps, low amplitude. Felt, not watched. ---------- */

@keyframes flicker {
  0%, 19%, 63%, 100% { opacity: 1; }
  11%, 46%, 86% { opacity: var(--flicker-mid); }
  34%, 71% { opacity: var(--flicker-low); }
}
@keyframes sway {
  0%, 100% { scale: 1; }
  38% { scale: var(--sway-high); }
  67% { scale: var(--sway-low); }
}
@keyframes flame-dance {
  0%, 64%, 100% { scale: 1; }
  17%, 52% { scale: var(--flame-tall); }
  29%, 81% { scale: var(--flame-short); }
}
@keyframes accent-flicker {
  0%, 58%, 100% { filter: none; }
  23%, 77% { filter: var(--accent-dim); }
  41% { filter: var(--accent-bright); }
}
@keyframes breathe { to { scale: var(--breathe-in); translate: var(--breathe-rise); } }
/* A torch's light jumps between levels; it doesn't fade. */
@keyframes torch-flicker {
  0%, 100% { opacity: var(--flicker-step-1); }
  12% { opacity: var(--flicker-step-2); }
  19% { opacity: 1; }
  33% { opacity: var(--flicker-step-3); }
  47% { opacity: var(--flicker-step-1); }
  61% { opacity: var(--flicker-step-4); }
  78% { opacity: 1; }
}

/* Torch-colored accents catch the same unsteady light. Spent or disabled ones go dark and still. */
.hud .title, .orb, .big-button:not(:disabled) {
  animation: accent-flicker var(--dur-accent-flicker) var(--ease-ambient) var(--ambient-delay) infinite;
}
.stat.energy.spent .orb { animation: none; }

/* ---------- Outcome: a slab above everything, with real shadow ---------- */

.outcome {
  position: absolute;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--space-6);
  background: var(--surface-outcome-veil);
  animation: fade-in var(--dur-med) var(--ease-out);
}
.outcome .panel {
  padding: var(--space-6) var(--space-8) var(--space-7);
  text-align: center;
  border-radius: var(--radius-plaque);
  border: var(--hairline) solid var(--color-bronze-edge);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-modal), var(--shadow-plaque);
}
.outcome h2 {
  margin: 0 0 var(--space-4);
  font-family: var(--font-display);
  font-size: var(--type-4xl);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-title);
  line-height: var(--leading-tight);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.outcome.lost .panel { border-color: var(--color-blood-deep); }
.outcome.lost h2 { color: var(--color-blood); text-shadow: var(--shadow-text-blood); }
.outcome p { margin: var(--space-1) 0; font-size: var(--type-lg); color: var(--color-text-dim); }
.outcome .actions { margin-top: var(--space-6); }
.outcome .small { margin: 0; font-size: var(--type-sm); color: var(--color-text-faint); }

/* ---------- Combat log: a dim niche. Present, legible, never competing with the board. ---------- */

.log {
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: var(--hairline) solid var(--color-mortar);
  border-left: var(--rule) solid var(--color-torch);
  border-radius: 0 var(--radius-log) var(--radius-log) 0;
  background: var(--surface-log);
  box-shadow: var(--shadow-niche);
}
.log-toggle {
  flex: none;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: 0 var(--space-5);
  border: 0;
  background: none;
  font-family: var(--font-display);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking-title);
  color: var(--color-text-faint);
}
.log-toggle .toggle-word { color: var(--color-torch-dim); }
.log-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 var(--space-5) var(--space-5);
  font-size: var(--type-md);
  line-height: var(--leading-text);
  -webkit-user-select: text;
  user-select: text;
}
.log-entry {
  padding: var(--space-3) 0;
  border-top: var(--hairline) solid var(--color-mortar);
  box-shadow: var(--shadow-scratch);
}
.log-title { font-weight: var(--weight-bold); color: var(--color-text); }
/* The arithmetic, step by step: the steps sit back, what landed stands out, the damage burns red. */
.log-line { padding-left: var(--space-5); font-size: var(--type-sm); color: var(--color-text-dim); white-space: pre-wrap; }
.log-line b { font-weight: var(--weight-heavy); color: var(--color-text); }
.log-line.line-step { color: var(--color-text-faint); }
.log-line.line-step b { color: var(--color-text-dim); }
.log-line .dmg { color: var(--color-blood-bright); text-shadow: var(--shadow-text-blood); }
.log-entry.log-turn {
  margin-top: var(--space-3);
  border-top: 0;
  box-shadow: none;
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--type-lg);
  letter-spacing: var(--tracking-title);
  color: var(--color-torch-dim);
}
.log-entry.log-turn .log-title { color: inherit; font-weight: var(--weight-display); }
.log-entry.log-phase { text-align: center; font-style: italic; }
.log-entry.log-phase .log-title, .log-entry.log-info .log-title { font-weight: var(--weight-text); color: var(--color-text-faint); }
.log-entry.log-by-player .log-title { color: var(--color-log-player); }
.log-entry.log-by-enemy .log-title { color: var(--color-log-enemy); }
.log-entry.log-by-summon .log-title, .log-entry.log-raise .log-title { color: var(--color-log-summon); }
.log-entry.log-by-companion .log-title { color: var(--color-gilt); }
.log-entry.log-death .log-title { color: var(--color-blood); }
.log-entry.log-timed .log-title, .log-entry.log-taken .log-title { color: var(--color-darkhold); text-shadow: var(--shadow-text-beam); }
.log-entry.log-armor .log-title { font-weight: var(--weight-text); color: var(--color-bones); }
.log-entry.log-outcome { text-align: center; font-family: var(--font-display); font-size: var(--type-xl); letter-spacing: var(--tracking-title); }
.log-entry.log-outcome .log-title { font-weight: var(--weight-display); color: var(--color-blood); }
.log-entry.log-won .log-title { color: var(--color-torch); }

/* ---------- Controls: piles, prompt, end turn ---------- */

.controls { display: flex; align-items: center; gap: var(--space-3); }
.pile {
  flex: none;
  width: var(--pile-w);
  min-height: var(--tap);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-1) 0;
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-pile);
}
.pile b { font-size: var(--type-xl); font-weight: var(--weight-heavy); line-height: var(--leading-tight); text-shadow: var(--shadow-text-carved); }
.pile span {
  font-family: var(--font-display);
  font-size: var(--type-xs);
  letter-spacing: var(--tracking-label);
  color: var(--color-text-faint);
}
.prompt {
  flex: 1;
  min-width: 0;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: var(--type-lg);
  font-style: italic;
  color: var(--color-text-faint);
}
.prompt { flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.prompt.focus { color: var(--color-text); }

/* Call Your Shot: a toggle beside the piles, and while it is on, a keypad row above them. */
.controls { flex-wrap: wrap; }
.call-toggle {
  flex: none;
  width: var(--pile-w);
  min-height: var(--tap);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-1);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  color: var(--color-text-faint);
  font-family: var(--font-display);
  font-size: var(--type-xs);
  letter-spacing: var(--tracking-label);
  line-height: var(--leading-tight);
  transition: transform var(--dur-press) var(--ease-out);
}
.call-toggle .icon { width: var(--icon-md); height: var(--icon-md); }
.call-toggle.on { border-color: var(--color-bronze-edge); background: var(--surface-bronze); color: var(--color-torch-hot); box-shadow: var(--shadow-bronze); text-shadow: var(--shadow-text-lit); }
.call-toggle:active { transform: translateY(var(--press-depth)); }
.keypad {
  order: -1;
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-2);
}
.call-readout {
  min-width: var(--readout-w);
  min-height: var(--tap);
  display: grid;
  place-items: center;
  padding: 0 var(--space-4);
  border-radius: var(--radius-well);
  background: var(--surface-well);
  box-shadow: var(--shadow-well);
  font-size: var(--type-2xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
  color: var(--color-text-faint);
}
.call-readout.empty { font-family: var(--font-display); font-size: var(--type-sm); font-weight: var(--weight-display); letter-spacing: var(--tracking-title); }
.call-readout.live { color: var(--color-torch); text-shadow: var(--shadow-text-lit); box-shadow: var(--shadow-niche), var(--shadow-key-lit); }
.key {
  width: var(--tap);
  height: var(--tap);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  font-size: var(--type-xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
  color: var(--color-text);
  transition: transform var(--dur-press) var(--ease-out);
}
.key:active { transform: translateY(var(--press-depth)); box-shadow: var(--shadow-bronze-pressed); }
.key:disabled { filter: var(--filter-unlit); }

/* "Pay X health" stepper. Shows X only, never what X will become. */
.payment {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-weight: var(--weight-bold);
  color: var(--color-text);
}
.step {
  width: var(--tap);
  height: var(--tap);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-plaque);
  background: var(--surface-bronze);
  box-shadow: var(--shadow-bronze);
  font-size: var(--type-2xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
  color: var(--color-text);
  transition: transform var(--dur-press) var(--ease-out);
}
.step:active { transform: translateY(var(--press-depth)); box-shadow: var(--shadow-bronze-pressed); }
.step:disabled { filter: var(--filter-unlit); }
.payment .amount {
  min-width: var(--amount-w);
  text-align: center;
  font-size: var(--type-3xl);
  line-height: var(--leading-tight);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.prompt.warn { color: var(--color-torch); font-weight: var(--weight-bold); text-shadow: var(--shadow-text-lit); }

/* The main action: a bronze plaque, warm with torchlight, its lettering stamped. */
.big-button {
  min-width: var(--button-min-w);
  min-height: var(--button-h);
  padding: 0 var(--space-7);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-button);
  background: var(--surface-bronze);
  color: var(--color-torch-hot);
  font-family: var(--font-display);
  font-size: var(--type-2xl);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-title);
  line-height: var(--leading-tight);
  text-shadow: var(--shadow-text-lit);
  box-shadow: var(--shadow-bronze);
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press) var(--ease-out);
}
.big-button:active { transform: translateY(var(--press-depth)); box-shadow: var(--shadow-bronze-pressed); }
.big-button:disabled { filter: var(--filter-unlit); box-shadow: var(--shadow-plaque); }

/* ---------- Hand: pages torn from the book, held up into the light ---------- */

.hand {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: var(--space-3);
  padding: var(--hand-headroom) var(--space-5) var(--hand-footroom);
  overflow-x: auto;
  overflow-y: hidden;
}
.card {
  flex: 0 1 var(--card-w);
  min-width: var(--card-min-w);
  min-height: var(--card-min-h);
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-5) var(--space-5);
  text-align: left;
  color: var(--card-ink);
  border: var(--hairline) solid var(--card-edge);
  border-radius: var(--radius-page);
  background: var(--surface-card);
  box-shadow: var(--shadow-card-frame), var(--shadow-rarity), var(--shadow-card);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), filter var(--dur-fast) var(--ease-out);
}
.card:nth-child(2n) { border-radius: var(--radius-page-alt); }
/* In the hand, pages widen to share the row, so long rules text wraps less and the hand stays short. */
.hand .card { flex: 1 1 var(--card-w); max-width: var(--card-max-w); }
.card:active { transform: translateY(calc(var(--press-depth) * -1)); }
.card.selected {
  transform: translateY(var(--card-lift));
  filter: var(--filter-lit);
  box-shadow: var(--shadow-card-frame), var(--shadow-rarity), var(--shadow-card-lifted);
}
/* Unplayable: dimmed and desaturated, not just inert (DESIGN.md section 4). */
.card.unplayable { filter: var(--filter-unlit); }
.card.unplayable:active { transform: none; }

/* The school's edge: a strip of colored light down the page's left side, so the school reads at a glance. */
.card .edge {
  position: absolute;
  left: 0;
  top: var(--space-6);
  bottom: var(--space-6);
  width: var(--edge-w);
  border-radius: var(--radius-chip);
  background: var(--surface-edge);
  box-shadow: var(--glow-edge);
  pointer-events: none;
}

/* Head: the cost seal (the number the player checks most) is stamped over the page's corner, so the name
   keeps the page's full width. */
.card-head { display: block; min-height: var(--seal-tuck); }
.cost {
  position: absolute;
  top: var(--seal-offset);
  left: var(--seal-offset);
  width: var(--seal-size);
  height: var(--seal-size);
  display: grid;
  place-items: center;
  border-radius: var(--radius-wax);
  background: var(--surface-wax);
  box-shadow: var(--shadow-seal), var(--glow-cost);
  color: var(--color-text-on-fire);
  font-size: var(--type-2xl);
  font-weight: var(--weight-heavy);
  line-height: var(--leading-tight);
}
.card-name {
  display: block;
  text-indent: var(--seal-clearance);
  overflow-wrap: break-word; /* a long name breaks rather than spilling off a narrow card, */
  hyphens: auto; /* and with a hyphen where the language allows one */
  font-family: var(--font-display);
  font-size: var(--type-lg);
  font-weight: var(--weight-display);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-card-name);
  color: var(--card-name-ink);
  text-shadow: var(--shadow-text-ink);
}

/* The art well: recessed into the page and lit from within in the school's color. Its glyph says what the
   card mainly does; the school's sigil is stamped in the corner. */
.art {
  position: relative;
  height: var(--art-well-h);
  display: grid;
  place-items: center;
  border-radius: var(--radius-well);
  background: var(--surface-well);
  box-shadow: var(--shadow-well);
  overflow: hidden;
}
.art-glyph { height: var(--art-glyph-size); aspect-ratio: 1; color: var(--school); filter: var(--filter-glyph); }
.art .sigil {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-2);
  width: var(--sigil-size);
  height: var(--sigil-size);
  color: var(--school);
  opacity: var(--opacity-sigil);
}

.card-text { flex: 1; font-size: var(--type-md); line-height: var(--leading-text); }
.card-text b { font-weight: var(--weight-heavy); color: var(--card-number); }
.card-reason { font-size: var(--type-xs); font-weight: var(--weight-heavy); color: var(--color-hp-text); }

/* Rare and ancient: gilt brackets in the page's corners. */
.card:is([data-rarity="rare"], [data-rarity="ancient"])::after {
  content: "";
  position: absolute;
  inset: var(--ornament-inset);
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(var(--card-ornament) 0 0) left top / var(--ornament-len) var(--ornament-thick),
    linear-gradient(var(--card-ornament) 0 0) left top / var(--ornament-thick) var(--ornament-len),
    linear-gradient(var(--card-ornament) 0 0) right top / var(--ornament-len) var(--ornament-thick),
    linear-gradient(var(--card-ornament) 0 0) right top / var(--ornament-thick) var(--ornament-len),
    linear-gradient(var(--card-ornament) 0 0) left bottom / var(--ornament-len) var(--ornament-thick),
    linear-gradient(var(--card-ornament) 0 0) left bottom / var(--ornament-thick) var(--ornament-len),
    linear-gradient(var(--card-ornament) 0 0) right bottom / var(--ornament-len) var(--ornament-thick),
    linear-gradient(var(--card-ornament) 0 0) right bottom / var(--ornament-thick) var(--ornament-len);
  background-repeat: no-repeat;
  opacity: var(--opacity-ornament);
}

/* What is acting on this card right now (a companion, Strength, Weak), beside its text, never folded in. */
.card-mods { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.card-mod {
  padding: 0 var(--space-2);
  border: var(--hairline) solid var(--card-mod-edge);
  border-radius: var(--radius-chip);
  background: var(--color-mod-chip);
  color: var(--color-vellum-bright);
  font-size: var(--type-xs);
  font-weight: var(--weight-bold);
  line-height: var(--leading-text);
}
/* The called shot, pinned to the lifted card like a wager slip. */
.call-tag {
  position: absolute;
  top: var(--call-tag-offset);
  right: var(--call-tag-offset);
  padding: var(--space-1) var(--space-3);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-tag);
  background: var(--surface-bronze);
  box-shadow: var(--shadow-tag);
  color: var(--color-torch-hot);
  font-family: var(--font-display);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking-label);
  white-space: nowrap;
}

/* Short landscape screens: the hand gives the board room, with a slimmer art well and smaller rules text. */
@media (orientation: landscape) and (max-height: 800px) {
  .hand .art { height: var(--art-well-h-short); }
  .hand .card-text { font-size: var(--type-sm); line-height: var(--leading-snug); }
}

/* Narrow cards (small iPads in portrait): tighter type so long names and rules text still fit. */
@container (max-width: 150px) {
  .card-name { font-size: var(--type-md); letter-spacing: 0; }
  .card-text { font-size: var(--type-sm); }
}

/* ---------- Run screens: map, rewards, shop, rest, title, end ---------- */

.screen {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--gap-region);
}
.screen > .torch { top: var(--torch-top); }

/* A board: the recessed stone a screen's business happens on. */
.board {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-7) var(--space-6);
  clip-path: var(--chipped-corners);
  background: var(--surface-board);
  box-shadow: var(--shadow-board);
}
.board-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--type-3xl);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-tight);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.board-prompt { margin: 0; text-align: center; font-size: var(--type-lg); color: var(--color-text-dim); }
.board-message { margin: 0; text-align: center; font-size: var(--type-lg); font-weight: var(--weight-bold); color: var(--color-torch); text-shadow: var(--shadow-text-lit); }
.gain { margin: 0; display: inline-flex; align-items: center; gap: var(--space-3); font-size: var(--type-2xl); color: var(--color-text); }
.gain .icon { width: var(--icon-md); height: var(--icon-md); color: var(--color-flame); }

/* Fills the board's width: cards contain their own size, so they can't stretch a row to fit them. */
.card-row {
  align-self: stretch;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: var(--space-6) var(--space-5);
  padding: var(--hand-headroom) var(--space-4) var(--hand-footroom);
}
.card-row .card { flex: 0 1 var(--card-row-w); }

.actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--space-4); }
.actions.column { flex-direction: column; align-items: stretch; }

/* The quieter button: dark stone with a bronze rim, not lit. */
.plain-button {
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0 var(--space-6);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-button);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  font-family: var(--font-display);
  font-size: var(--type-lg);
  letter-spacing: var(--tracking-label);
  color: var(--color-text);
  transition: transform var(--dur-press) var(--ease-out);
}
.plain-button .icon { color: var(--color-flame); }
/* Numbers are always set in the text face's bold figures, even inside display lettering. */
:is(.plain-button, .big-button, .board-title, .game-title) b, .num { font-family: var(--font-text); font-weight: var(--weight-heavy); letter-spacing: 0; }
.hud .turn .of { font-family: var(--font-text); }
.plain-button:active { transform: translateY(var(--press-depth)); box-shadow: var(--shadow-bronze-pressed); }
.plain-button:disabled { filter: var(--filter-unlit); }

/* Shop */
.for-sale { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); flex: 0 1 var(--card-row-w); }
.for-sale .card { width: 100%; flex: 1; }
.price {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-4);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-tag);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  font-size: var(--type-xl);
  font-weight: var(--weight-heavy);
  color: var(--color-elemental);
}
.price .icon { width: var(--icon-md); height: var(--icon-md); color: var(--color-flame); }
.price.short { color: var(--color-blood-bright); }
.for-sale.sold .price { color: var(--color-text-faint); }
/* The relic shelf: a plaque each, with its own price and buy button. */
.relic-shelf { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-5); }
.relic-for-sale { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.relic-for-sale .plain-button b { color: var(--color-elemental); }
.relic-for-sale.sold .relic { filter: var(--filter-unlit); }

/* Rest */
.choices { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-6); }
.choice {
  width: var(--choice-w);
  min-height: var(--choice-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-6);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-plaque);
  background: var(--surface-choice);
  box-shadow: var(--shadow-plaque), var(--glow-torch);
  color: var(--color-text);
  transition: transform var(--dur-press) var(--ease-out);
}
.choice b { font-family: var(--font-display); font-size: var(--type-2xl); font-weight: var(--weight-display); letter-spacing: var(--tracking-display); color: var(--color-torch-hot); text-shadow: var(--shadow-text-lit); }
.choice span { font-size: var(--type-md); color: var(--color-text-dim); }
.choice .choice-reason { font-weight: var(--weight-bold); color: var(--color-hp-text); }
.choice-icon { width: var(--icon-xl); height: var(--icon-xl); color: var(--color-flame); }
.choice:active { transform: translateY(var(--press-depth)); }
.choice:disabled { filter: var(--filter-unlit); box-shadow: var(--shadow-plaque); }

/* Card picker */
.overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--space-5);
  background: var(--color-scrim);
  animation: fade-in var(--dur-med) var(--ease-out);
}
.sheet {
  width: min(100%, var(--sheet-max-w));
  max-height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-modal), var(--shadow-plaque);
}
.sheet-head, .sheet-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-4); }
.preview { flex: 1; font-size: var(--type-md); color: var(--color-text-dim); }
.preview b { color: var(--color-text); }
.card-grid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--card-row-w), 1fr));
  gap: var(--space-7) var(--space-5);
  padding: var(--hand-headroom) var(--space-4) var(--hand-footroom);
}

/* Companions: a plaque each, on the reward board and in the Allies sheet. */
.offer { align-self: stretch; display: flex; flex-direction: column; align-items: center; gap: var(--space-4); }
.offer .companion { flex: none; width: min(100%, var(--companion-max-w)); } /* in a column, flex-basis would set its height */
.offer.chosen .companion { border-color: var(--color-torch); box-shadow: var(--shadow-ledge), var(--glow-target); }
.offer-toggle.on { border-color: var(--color-torch); color: var(--color-torch); box-shadow: var(--shadow-ledge), var(--glow-torch); }
.found { margin: 0; font-size: var(--type-md); font-weight: var(--weight-bold); color: var(--color-text-dim); }
.offer-title { margin: 0; text-align: center; font-family: var(--font-display); font-size: var(--type-2xl); font-weight: var(--weight-display-heavy); color: var(--color-torch); text-shadow: var(--shadow-text-lit); }
.companion-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-5);
}
.companion {
  flex: 1 1 var(--companion-w);
  max-width: var(--companion-max-w);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  border: var(--hairline) solid var(--companion-color);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque), var(--glow-companion);
  text-align: left;
}
.companion-head { display: flex; align-items: center; gap: var(--space-4); }
.companion h3 { margin: 0; font-family: var(--font-display); font-size: var(--type-2xl); font-weight: var(--weight-display); letter-spacing: var(--tracking-display); line-height: var(--leading-tight); color: var(--companion-color); }
.companion p { margin: 0; font-size: var(--type-md); line-height: var(--leading-text); color: var(--color-text-dim); }
.companion .flavor { font-style: italic; color: var(--color-text-faint); }
.companion .passive b { color: var(--color-text); }
.companion .sacrifice-text b { color: var(--color-blood-bright); }
.companion .actions { justify-content: flex-start; padding-top: var(--space-2); }
.companion .small, .offer .small { font-size: var(--type-sm); color: var(--color-text-faint); }
/* Sacrifice is a real button, always there, and it looks like what it costs. */
.sacrifice-button {
  min-width: 0;
  border-color: var(--color-blood-deep);
  background: var(--surface-blood);
  color: var(--color-text);
  font-size: var(--type-xl);
  box-shadow: var(--shadow-button), var(--glow-intent);
}

/* ---------- Events ---------- */

.flavor-text { margin: 0; max-width: var(--measure); text-align: center; font-size: var(--type-lg); font-style: italic; color: var(--color-text-dim); }
.event-choices { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-6); }
.event-choice { width: var(--event-choice-w); min-height: var(--choice-h); }
.event-choice span { font-size: var(--type-md); line-height: var(--leading-text); }
.event-choice.selected { border-color: var(--color-torch); box-shadow: var(--shadow-ledge), var(--glow-target); }
.event-choice.walk-away { border-color: var(--color-bronze); background: var(--surface-plaque); box-shadow: var(--shadow-plaque); }
.event-choice.walk-away b { color: var(--color-text-dim); text-shadow: var(--shadow-text-carved); }
.event-choice.walk-away.selected { border-color: var(--color-torch); box-shadow: var(--shadow-ledge), var(--glow-target); }
/* A step that would kill you is drawn in blood, and asks twice. */
.big-button.deadly { border-color: var(--color-blood-deep); background: var(--surface-blood); color: var(--color-text); box-shadow: var(--shadow-button), var(--glow-intent); }
.results { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; font-size: var(--type-lg); }
.results li { color: var(--color-text-dim); }
.results li.headline { order: -1; font-family: var(--font-display); font-size: var(--type-2xl); color: var(--color-text); }
.event .board-prompt { max-width: var(--measure); }
.tally { margin: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2) var(--space-7); font-size: var(--type-lg); color: var(--color-text-dim); }
.tally b { font-size: var(--type-2xl); color: var(--color-torch); text-shadow: var(--shadow-text-lit); }

/* The Dealer's Table: cards face down on the table, turned one at a time. */
.memory-grid {
  display: grid;
  grid-template-columns: repeat(var(--memory-cols), var(--memory-card-w));
  gap: var(--space-5);
  justify-content: center;
}
@media (orientation: portrait) { .memory-grid { grid-template-columns: repeat(var(--memory-cols-narrow), var(--memory-card-w)); } }
.memory-card {
  aspect-ratio: var(--aspect-player);
  min-height: var(--tap);
  display: grid;
  place-items: center;
  padding: 0;
  border: var(--rule) solid var(--color-iron-dark);
  border-radius: var(--radius-worn-2);
  background: var(--surface-card-back);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-press) var(--ease-out);
}
.memory-card:active { transform: translateY(var(--press-depth)); }
.memory-card.shown { border-color: var(--face); background: var(--surface-well); color: var(--face); box-shadow: var(--shadow-well), var(--glow-face); }
.memory-card.shown svg { width: var(--memory-glyph); height: var(--memory-glyph); filter: var(--filter-glyph); }
.memory-card.matched { opacity: var(--opacity-ahead); box-shadow: var(--shadow-card); }
.memory-card:disabled { cursor: default; }
.memory-card.just svg { animation: flip-in var(--dur-fast) var(--ease-out); }
@keyframes flip-in { from { scale: var(--flip-from); } }

/* The Blood Wager: the ladder of rounds, cost and odds and prize, the next rung lit. */
.ladder { margin: 0; padding: 0; list-style: none; width: min(100%, var(--ladder-w)); display: flex; flex-direction: column-reverse; gap: var(--space-2); }
.ladder li {
  display: grid;
  grid-template-columns: 1fr 1fr 2fr;
  align-items: center;
  gap: var(--space-4);
  min-height: var(--tap);
  padding: var(--space-2) var(--space-5);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque);
  color: var(--color-text-faint);
  font-size: var(--type-md);
}
.ladder li b { color: var(--color-text-dim); }
.ladder .icon { color: var(--color-blood); }
.ladder .rung-prize { text-align: right; font-weight: var(--weight-bold); }
.ladder li.next { border-color: var(--color-blood); color: var(--color-text); box-shadow: var(--glow-intent), var(--shadow-ledge); }
.ladder li.next b { color: var(--color-text); }
.ladder li.cleared { color: var(--color-text-dim); border-color: var(--color-iron); }
.ladder li.cleared .rung-prize { color: var(--color-torch); }
.draw { margin: 0; font-family: var(--font-display); font-size: var(--type-4xl); font-weight: var(--weight-display-heavy); line-height: var(--leading-tight); animation: pop var(--dur-med) var(--ease-punch); }
.draw.clean { color: var(--color-bone); text-shadow: var(--shadow-text-lit); }
.draw.rot { color: var(--color-necromancy); text-shadow: var(--shadow-text-blood); }

/* Relics */
.relic-list { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-5); }
.relic {
  width: var(--relic-w);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  border: var(--hairline) solid var(--relic-edge);
  border-radius: var(--radius-plaque);
  background: var(--surface-plaque);
  box-shadow: var(--shadow-plaque), var(--glow-relic);
  text-align: left;
}
.relic-head { display: flex; align-items: center; gap: var(--space-3); }
.relic-head .icon { width: var(--icon-md); height: var(--icon-md); color: var(--relic-edge); }
.relic h3 { margin: 0; font-family: var(--font-display); font-size: var(--type-xl); font-weight: var(--weight-display); letter-spacing: var(--tracking-display); line-height: var(--leading-tight); color: var(--color-text); }
.relic p { margin: 0; font-size: var(--type-md); line-height: var(--leading-text); color: var(--color-text-dim); }
.relic .relic-count { color: var(--color-text); }
.relic .relic-count b { color: var(--color-torch-hot); }
.lasting { margin: 0; padding: 0 var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); font-size: var(--type-md); color: var(--color-text-dim); }
.lasting b { color: var(--color-text); }

/* Title and end: a slab above everything. */
.title-screen, .end-screen { align-items: center; justify-content: center; }
.slab {
  width: min(100%, var(--slab-w));
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-8);
  text-align: center;
  border: var(--hairline) solid var(--color-bronze-edge);
  border-radius: var(--radius-plaque);
  background: var(--surface-slab);
  box-shadow: var(--shadow-modal), var(--shadow-plaque);
}
.game-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--type-5xl);
  font-weight: var(--weight-display-heavy);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  color: var(--color-torch);
  text-shadow: var(--shadow-text-lit);
}
.slab.lost .game-title { color: var(--color-blood); text-shadow: var(--shadow-text-blood); }
.tagline { margin: 0; font-size: var(--type-lg); color: var(--color-text-dim); }
.best { margin: 0; font-size: var(--type-sm); color: var(--color-text-faint); }
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(var(--choice-w), 1fr)); gap: var(--space-2) var(--space-6); margin: 0; text-align: left; }
.summary div { display: flex; justify-content: space-between; gap: var(--space-4); padding: var(--space-2) 0; border-bottom: var(--hairline) solid var(--color-mortar); box-shadow: var(--shadow-scratch); }
.summary dt { color: var(--color-text-dim); }
.summary dd { margin: 0; font-weight: var(--weight-heavy); }

/* Map: a page of the book, held up to a torch. Paths inked in faded vellum, rooms pressed in as bronze seals.
   The way forward is lit; the way you came is burnt in. */
.map {
  flex: 1;
  min-height: 0;
  --surface-grain: var(--texture-noise-fine);
  --surface-grain-size: var(--texture-noise-fine-size);
  --surface-grain-opacity: var(--opacity-noise-page);
  border: var(--hairline) solid var(--color-bronze);
  border-radius: var(--radius-page);
  background: var(--surface-map);
  box-shadow: var(--shadow-card-frame-map), var(--shadow-card);
  color: var(--color-text);
}
.map-inner { position: absolute; inset: var(--map-pad); }
.map-paths { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.map-paths line { stroke: var(--color-vellum-faint); stroke-width: var(--map-line); stroke-dasharray: var(--map-dash); stroke-linecap: round; }
.map-paths line.walked { stroke: var(--color-torch-dim); stroke-width: var(--map-line-strong); stroke-dasharray: none; }
.map-paths line.open { stroke: var(--color-torch-hot); stroke-width: var(--map-line-strong); stroke-dasharray: none; filter: var(--filter-path-lit); }

/* Node types are prefixed (type-combat, type-boss) so they can never collide with screen classes like .combat. */
.node {
  position: absolute;
  left: calc(var(--across) * 100%);
  top: calc(var(--along) * 100%);
  translate: -50% -50%;
  min-width: var(--tap);
  min-height: var(--tap);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text);
}
.stamp {
  width: var(--stamp-size);
  height: var(--stamp-size);
  display: grid;
  place-items: center;
  border-radius: var(--radius-wax);
  background: var(--surface-stamp);
  box-shadow: var(--shadow-stamp);
  transition: box-shadow var(--dur-fast) var(--ease-out);
}
.node-icon { width: var(--icon-md); height: var(--icon-md); color: var(--color-vellum-dim); }
.node-label {
  font-family: var(--font-display);
  font-size: var(--type-md);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-label);
  line-height: var(--leading-tight);
  color: var(--color-text-dim);
  text-shadow: var(--shadow-text-ink);
}
.node.type-elite .node-icon { color: var(--color-hp-text); }
.node.type-boss .stamp { width: var(--stamp-size-boss); height: var(--stamp-size-boss); }
.node.type-boss .node-icon { width: var(--icon-xl); height: var(--icon-xl); color: var(--color-hp-text); }
.node.ahead { opacity: var(--opacity-ahead); }
.node.past { opacity: var(--opacity-faded); }
.node.walked .stamp { background: var(--color-page-low); box-shadow: var(--shadow-stamp-walked); }
.node.walked .node-icon { color: var(--color-torch-dim); }
.node.open .stamp { box-shadow: var(--shadow-stamp-open); background: var(--surface-stamp-open); }
.node.open .node-icon { color: var(--color-torch-hot); }
.node.open .node-label { color: var(--color-torch-hot); text-shadow: var(--shadow-text-lit); }
.node.here .stamp { box-shadow: var(--shadow-stamp-here); }
.node:active .stamp { transform: translateY(var(--press-depth)); }
.map-caption { margin: 0; text-align: center; font-family: var(--font-display); font-size: var(--type-xl); letter-spacing: var(--tracking-label); color: var(--color-text-dim); }

/* Landscape: the dungeon runs left to right instead of top to bottom. */
@media (orientation: landscape) {
  .map-paths g { transform: matrix(0, 1, 1, 0, 0, 0); }
  .node { left: calc(var(--along) * 100%); top: calc(var(--across) * 100%); }
}

/* ---------- Keep the HUD on one line: companions' seals take the title's room ---------- */

@media (max-width: 1280px) {
  .hud:is(:has(.allies), :has(.relics)) .title { display: none; }
  .hud:is(:has(.allies), :has(.relics)) .stat:not(.energy) .cap { display: none; }
  .hud:is(:has(.allies), :has(.relics)) .turn { margin-right: auto; }
}

/* ---------- Smaller iPads in portrait: keep the HUD on one line ---------- */

@media (max-width: 820px) {
  .hud { gap: var(--space-2) var(--space-4); padding: var(--space-1) var(--space-4); }
  /* The title is decoration; on narrower screens the numbers get its room. */
  .hud .title { display: none; }
  .hud .turn { margin-right: auto; }
  .stat { padding-left: var(--space-4); gap: var(--space-2); }
  .stat b { font-size: var(--type-xl); }
  /* With companions in the HUD, the icons carry the meaning and the captions give way (energy keeps its own). */
  .hud:is(:has(.allies), :has(.relics)) .stat:not(.energy) .cap { display: none; }
}

/* ---------- Phones: not the target, but keep it usable ---------- */

@media (max-width: 600px) {
  .hud .title { font-size: var(--type-xl); }
  .stat .cap { display: none; }
  .unit { min-width: 0; padding: var(--space-2); }
  .prompt { font-size: var(--type-sm); }
  .big-button { min-width: 0; font-size: var(--type-xl); padding: 0 var(--space-5); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: var(--dur-reduced) !important;
    animation-iteration-count: 1 !important;
    transition-duration: var(--dur-reduced) !important;
  }
}
