/* Grey box, one dark look on purpose: flat stone tiles and a single torch colour for the
   player. Layout: one phone-height screen. Top bar, the view (8 tiles wide, the player
   always in the middle), then the action buttons. */
:root {
  color-scheme: dark;
  --void: #0c0d10;       /* rock, fog and the page */
  --floor: #2a2c31;
  --hall: #222429;       /* corridor floor, a shade darker than rooms */
  --wall: #474b53;
  --wall-lip: #5a5f69;   /* the lit top edge of a wall block */
  --wall-face: #2b2e34;  /* the shaded foot of a wall's front face */
  --crate: #5a4630;      /* clutter: old wood, its lit lip, shaded foot and iron band; a shelf's darker wood */
  --crate-lip: #7a6142;
  --crate-foot: #3a2d1f;
  --crate-band: #2f2a26;
  --shelf: #4a3a28;
  --seam: #16171b;       /* the gap between tiles */
  --surface: #17191d;    /* bars, panels, cards */
  --edge: #2e3138;
  --ink: #e6e3dc;
  --muted: #8a8e97;
  --torch: #efb64c;      /* the player's tunic, and keyboard focus */
  --paper: #f1ece1;      /* the cut edge of every paper cutout */
  --outline: #231f1c;
  --skin: #e9b892;
  --hair: #4a3426;
  --leather: #6b4a2b;
  --steel: #c9d1d9;
  --dim: #b4532f;        /* embers, weakest to strongest: the hotter, the whiter */
  --bright: #f0a53a;
  --blazing: #fff1bf;
  --good: #7fcf8a;
  --boar: #7a4b8c;
  --moth: #2f7c86;
  --beetle: #5f7a34;
  --shade: #3a3460;
  --grub: #3e9a6a;
  --rat: #8b5e3c;
  --knight: #66707c;
  --toad: #96406e;
  --blast: rgb(255 214 140 / 0.75);
  --shadow: rgb(0 0 0 / 0.5);
  --danger: #e0533f;
  --danger-fill: rgb(224 83 63 / 0.38);
  --scrim: rgb(12 13 16 / 0.78);
  --font-glyph: "Martian Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --tile: 44px;
  --cols: 8;
  --step: 120ms;
  --tilt: 45deg;
  --camera: 660px;
  --wall-h: 31px;
  --fog: 0.8;
  --night: 0.85;     /* how dark it is past the torch's light */
  --heading: 0deg;
  --turn: 360ms;
}

*, *::before, *::after { box-sizing: border-box; }
html {
  height: 100%;
  padding-block: env(safe-area-inset-top, 0px) env(safe-area-inset-bottom, 0px);
  background: var(--void);
}
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--void);
  color: var(--ink);
  font: 15px/1.4 var(--font-ui);
  -webkit-text-size-adjust: 100%;
}
[hidden] { display: none !important; }
button, input { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--torch); outline-offset: 2px; }

.game {
  position: relative;
  height: 100%;
  max-width: 560px;
  margin-inline: auto;
  padding-inline: 16px;
  padding-block: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ─── Top bar ─── */
.hud { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 44px; }
.stats { display: flex; gap: 14px; margin: 0; }
.stats div { display: grid; gap: 1px; }
.stats div[hidden] { display: none; }
.stats dt { font-size: 10px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.stats dd { margin: 0; font: 600 16px/1.2 var(--font-glyph); font-variant-numeric: tabular-nums; }
.stats dd.low { color: var(--danger); }
.seed {
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font: 500 12px var(--font-glyph);
  white-space: nowrap;
  cursor: pointer;
}
.seed span { color: var(--ink); }

/* ─── The view ─── */
.stage { position: relative; flex: 1; min-height: 0; display: flex; justify-content: center; }
.view {
  position: relative;
  width: calc(var(--tile) * var(--cols));
  height: 100%;
  overflow: hidden;
  background: var(--void);
  border-radius: 6px;
  cursor: pointer;
  touch-action: none; /* taps and holds belong to the game, not to page scrolling or pull-to-refresh */
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  perspective: var(--camera);
  perspective-origin: 50% 50%;
}
/* The floor turns and leans back around the middle of the view, where the player stands.
   The board slides on it; flat tiles share one layer, while wall faces and the player stand up. */
.plane {
  position: absolute;
  inset: 0;
  transform: rotateX(var(--tilt)) rotateZ(var(--heading));
  transform-style: preserve-3d;
  transition: transform var(--turn) ease-in-out;
}
.board { position: absolute; left: 0; top: 0; transform-style: preserve-3d; transition: transform var(--step) ease-out; }
.flat { position: absolute; left: 0; top: 0; }
.t, .actor {
  position: absolute;
  left: calc(var(--x) * var(--tile));
  top: calc(var(--y) * var(--tile));
  width: var(--tile);
  height: var(--tile);
}
.t.floor { background: var(--floor); box-shadow: inset 0 0 0 1px var(--seam); }
.t.hall { background: var(--hall); }
/* The Drowned Halls' water: shallow, walked; deep, not. */
.t.floor.shallow { background: #3a6f7a; }
.t.floor.deep { background: #12222e; box-shadow: none; }
/* The Bone Pits: an open pit, walls of stacked bones, shelves of bones in the tunnel walls. */
.t.floor.deep.pit { background: radial-gradient(closest-side, #000 70%, #17130f); }
.t.wall.bones.wall { background: #b9ad94; box-shadow: inset 0 3px 0 #d9cdb4, inset 0 0 0 1px #6f6656; }
.t.wall.bones.loculus { background: linear-gradient(to bottom, var(--wall) 0 30%, #a89c84 30% 70%, var(--wall) 70%); }
.face.bones.wall { background: repeating-linear-gradient(to bottom, #cdbfa3 0 5px, #9d917a 5px 7px); }
.face.clutter.column { --cw: 0.66; --ch: calc(var(--tile) * 0.95); background: linear-gradient(to bottom, #8d867b 0 4px, #6f685e 4px, #4d4740); }
.face.clutter.column.lid { background: #8d867b; box-shadow: inset 0 0 0 2px #5d574f; }
.face.clutter.skulls { --cw: 0.5; --ch: calc(var(--tile) * 0.95); background: repeating-linear-gradient(to bottom, #d9cdb4 0 6px, #8f846f 6px 8px); }
.face.clutter.skulls.lid { border-radius: 50%; background: #d9cdb4; }
.face.clutter.heap { --cw: 0.78; --ch: calc(var(--tile) * 0.22); background: #a39780; }
.face.clutter.heap.lid { border-radius: 40%; background: radial-gradient(circle at 40% 40%, #d9cdb4, #8f846f); }
.t.wall { background: var(--wall); box-shadow: inset 0 3px 0 var(--wall-lip), inset 0 0 0 1px var(--seam); }
/* A vault's seal: a wall with light leaking round it. */
.t.wall.door {
  background: linear-gradient(rgb(240 165 58 / 0.4), rgb(240 165 58 / 0.18)), var(--wall);
  box-shadow: inset 0 0 0 2px var(--bright), 0 0 16px rgb(240 165 58 / 0.65);
}
/* Stairs: a square in the floor with flat treads going down into the dark (Kevin, Oct 15, 2026:
   rectangles like flat stairs, not a > ). */
.t.stairs { display: grid; place-items: center; }
.t.stairs .steps {
  width: 74%; height: 74%; border-radius: 2px;
  background:
    linear-gradient(to bottom, transparent, rgb(0 0 0 / 0.7)),
    repeating-linear-gradient(to bottom, var(--wall-lip) 0 16%, var(--wall-face) 16% 25%);
  box-shadow: inset 0 0 0 1px var(--seam), 0 0 0 1px var(--wall);
}

/* ─── Paper cutouts ───
   An actor's feet are the middle of its box. Read right to left: stand it up facing the
   camera, move it a quarter tile toward the camera, and undo the floor's turn. Standing on
   the camera's side of the tile keeps it in front of the wall faces ahead. */
.actor {
  transform-style: preserve-3d;
  transform:
    rotateZ(calc(var(--heading) * -1))
    translateY(calc(var(--tile) * 0.25))
    rotateX(calc(var(--tilt) * -1));
  transition: left var(--step) ease-out, top var(--step) ease-out, transform var(--turn) ease-in-out;
}
/* The card itself, standing on its bottom edge. It turns on its upright axis (--face) to
   look left or right, like a paper puppet. */
.paper {
  position: absolute;
  left: 50%;
  bottom: 50%;
  transform-origin: 50% 100%;
  transform: rotateY(var(--face, 0deg));
  transition: transform 180ms ease-out, rotate 160ms ease-out;
}
/* Lies flat on the floor under the feet. */
.shadow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--tile) * 0.64);
  height: calc(var(--tile) * 0.64);
  margin: calc(var(--tile) * -0.32) 0 0 calc(var(--tile) * -0.32);
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--shadow), transparent);
  transform: rotateX(var(--tilt)) translateZ(1px);
}

.hero { width: calc(var(--tile) * 0.74); height: calc(var(--tile) * 1.02); margin-left: calc(var(--tile) * -0.37); }
.hero svg { display: block; width: 100%; height: 100%; overflow: visible; }
.hero .cut { fill: var(--paper); stroke: var(--paper); stroke-width: 6; stroke-linejoin: round; }
.hero .blade, .hero .body, .hero .belt, .hero .hilt, .hero .head, .hero .hair {
  stroke: var(--outline);
  stroke-width: 1.2;
  stroke-linejoin: round;
}
.hero .blade { fill: var(--steel); }
.hero .body { fill: var(--tunic, var(--torch)); }
.hero .belt, .hero .hilt { fill: var(--leather); }
.hero .head { fill: var(--skin); }
.hero .hair { fill: var(--hair); }
.hero .eye { fill: var(--outline); }
/* Long hair, chosen at camp. */
.hero [class*="style-"] { display: none; }
.hair-long .hero .style-long, .hair-braid .hero .style-braid, .hair-bun .hero .style-bun, .hair-pony .hero .style-pony,
.hair-curly .hero .style-curly, .hair-messy .hero .style-messy, .hair-beard .hero .style-beard { display: inline; }
.hair-curly .hero .crop, .hair-messy .hero .crop { display: none; }
.hero .tie { fill: var(--tunic, var(--torch)); stroke: var(--outline); stroke-width: 1; }
/* The Wicker shield: on the arm while carried, up in front while the guard is raised. */
.hero .shield { display: none; transform-box: fill-box; transform-origin: center; transition: transform 160ms ease-out; }
.has-buckler .hero .shield { display: inline; }
.braced .hero .shield { transform: translate(11px, -9px) scale(1.35); }
.hero .shield-cut { fill: var(--paper); stroke: var(--paper); stroke-width: 5; }
.hero .shield-face { fill: var(--steel); stroke: var(--outline); stroke-width: 1.2; }
.hero .shield-boss { fill: var(--leather); stroke: var(--outline); stroke-width: 1; }

.card {
  width: calc(var(--tile) * 0.8);
  height: calc(var(--tile) * 0.8);
  margin-left: calc(var(--tile) * -0.4);
  display: grid;
  place-items: center;
  border: 3px solid var(--paper);
  border-radius: 5px;
  color: var(--paper);
  box-shadow: 0 0 0 1px var(--outline);
}
.card b { font: 600 calc(var(--tile) * 0.42) / 1 var(--font-glyph); }
.card.boar { background: var(--boar); }
.card.moth { background: var(--moth); }
.card.beetle { background: var(--beetle); }
.card.shade { background: var(--shade); }
.card.grub { background: var(--grub); }
.card.rat { background: var(--rat); }
.card.toad { background: var(--toad); }
/* An elite (CONFIG.elites): a gold edge and a glow, so it reads as worth the trouble. */
.elite .card { border-color: var(--torch); color: var(--torch); box-shadow: 0 0 0 1px var(--outline), 0 0 calc(var(--tile) * 0.3) calc(var(--tile) * 0.04) rgb(239 182 76 / 0.8); }
/* A fallen delver: a grey paper figure lying flat on its side, under everything standing. */
.corpse {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--tile) * 0.9);
  height: calc(var(--tile) * 1.35);
  margin: calc(var(--tile) * -0.675) 0 0 calc(var(--tile) * -0.45);
  transform: rotateX(var(--tilt)) translateZ(1px) rotate(78deg);
  cursor: pointer;
}
.corpse svg { width: 100%; height: 100%; overflow: visible; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.corpse .edge { stroke: var(--outline); stroke-width: 6.5; }
.corpse .edge circle { fill: var(--outline); }
.corpse .bone { stroke: #ddd6c6; stroke-width: 3.6; }
.corpse .bone circle { fill: #ddd6c6; stroke-width: 0; }
.corpse .socket { fill: var(--outline); }
.body-token:not(.lit) > * { opacity: calc(1 - var(--fog)); }
.mc-letter.body { background: #5c5e66; font-family: var(--font-ui); }

/* A creature holding an ember (a Rat with one of yours, a Stonegnaw, Hoard-Mother) glows, and holds it up. */
.carrying .card { box-shadow: 0 0 calc(var(--tile) * 0.18) var(--torch); }
.carrying .card::after {
  content: "";
  position: absolute;
  top: calc(var(--tile) * -0.12);
  right: calc(var(--tile) * -0.12);
  width: calc(var(--tile) * 0.26);
  height: calc(var(--tile) * 0.26);
  border: 2px solid var(--paper);
  border-radius: 50%;
  background: var(--bright);
  box-shadow: 0 0 6px var(--bright);
}
.pips { position: absolute; left: 0; right: 0; bottom: 3px; display: flex; justify-content: center; gap: 2px; }
.pips span { width: 4px; height: 4px; border-radius: 50%; background: var(--paper); }
.pips span.lost { opacity: 0.25; }

/* Asleep (z) and wary (?): a mark over the card. A hunter has none. */
.mark {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 0.86);
  translate: -50% 0;
  font: 700 calc(var(--tile) * 0.3) / 1 var(--font-glyph);
  color: var(--muted);
}
.asleep .mark, .wary .mark { display: block; }
.asleep .mark::after { content: 'z'; }
.wary .mark::after { content: '?'; color: var(--torch); }
.stunned .mark { display: none; }

/* What ails a creature, or you: a glow for burning and poison, a tremble for fright. */
.monster.burning .card, .player.burning .hero { filter: drop-shadow(0 0 4px rgb(240 140 40)); }
.monster.poisoned:not(.burning) .card, .player.poisoned:not(.burning) .hero { filter: drop-shadow(0 0 4px rgb(150 200 80)); }
.monster.frightened .card, .player.frightened .hero { animation: tremble 0.18s linear infinite alternate; }
@keyframes tremble { from { translate: -1px 0; } to { translate: 1px 0; } }

/* States a player can read: leaning back, and reeling with stars overhead. */
.winding .card { rotate: -10deg; }
.stunned .card { rotate: 14deg; }
.stars {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 0.86);
  translate: -50% 0;
  color: var(--torch);
  font-size: calc(var(--tile) * 0.26);
  white-space: nowrap;
  animation: reel 0.9s ease-in-out infinite alternate;
}
.stunned .stars { display: block; }
@keyframes reel { from { rotate: -12deg; } to { rotate: 12deg; } }

/* Turn order: a number badge on each monster's top-left corner while the 1·2·3 button is on,
   clear of the stun stars above the middle. */
.order {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 0.62);
  margin-left: calc(var(--tile) * -0.58);
  width: calc(var(--tile) * 0.34);
  height: calc(var(--tile) * 0.34);
  place-items: center;
  border: 2px solid var(--paper);
  border-radius: 50%;
  background: var(--torch);
  color: var(--void);
  font: 600 calc(var(--tile) * 0.2) / 1 var(--font-glyph);
  transform: translateZ(2px); /* in front of the card even while it turns to look */
}
.show-order .order { display: grid; }
.monster.selected .card { box-shadow: 0 0 0 1px var(--outline), 0 0 0 4px var(--torch); }

/* Monsters outside the lit area are as dim as the fog around them. */
.monster:not(.lit) > * { opacity: calc(1 - var(--fog)); }
/* In your area but past the torch's light, a monster is a shadow: dim, but there. */
.monster.lit.dim > * { opacity: 0.45; }
/* With the torch out, every monster near enough is a shadow, whatever room it's in, and
   those further than you can make out shadows aren't seen at all. */
.torch-out .monster.dim:not(.unseen) > * { opacity: 0.45; }
.torch-out .monster.unseen > * { opacity: 0; }
/* In another room or hall, a monster can't be seen at all, unless something you wear shows it:
   as a hint (where, never what), or in full. */
.monster.far > * { opacity: 0; }
.monster.far.hinted > * { opacity: 0.55; filter: brightness(0) drop-shadow(0 0 3px var(--muted)); }
.monster.seen > * { opacity: 1 !important; filter: none !important; }
/* A Black-glass visor: the stairs look like floor until you're next to them. */
.board.stairs-hidden .t.stairs .steps { visibility: hidden; }

/* Floating numbers and marks over a cutout's head. */
.float span {
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 0.95);
  transform: translateX(-50%);
  color: var(--ink);
  font: 600 calc(var(--tile) * 0.36) / 1 var(--font-glyph);
  text-shadow: 0 1px 0 var(--void), 0 0 4px var(--void);
  white-space: nowrap;
  pointer-events: none;
}
.float.bad span { color: var(--danger); }
.float.note span { color: var(--torch); }
.float.good span { color: var(--good); }
.float.heal span { color: var(--good); font-size: calc(var(--tile) * 0.44); }

/* Down at 0 with the last turn running: the hero sags. */
.downed .hero { rotate: -22deg; filter: grayscale(0.6); }

/* Loot on the floor: small paper tokens, fanned out when several share a tile. */
.loot { position: absolute; left: 0; top: 0; transform-style: preserve-3d; }
.props { position: absolute; left: 0; top: 0; transform-style: preserve-3d; } /* the camp's standing things */
.loot-token .shadow { width: calc(var(--tile) * 0.4); height: calc(var(--tile) * 0.4); margin: calc(var(--tile) * -0.2) 0 0 calc(var(--tile) * -0.2); }
.loot-token:not(.lit) > * { opacity: calc(1 - var(--fog)); }
/* An Ash tongue: embers show wherever they lie. */
.loot-token.sensed > * { opacity: 1; filter: drop-shadow(0 0 5px var(--torch)); }
.loot-token.glimmer > * { opacity: 1; filter: drop-shadow(0 0 6px var(--torch)); }
.token {
  display: grid;
  place-items: center;
  margin-left: calc(var(--tile) * (-0.18 + var(--n) * 0.14));
  width: calc(var(--tile) * 0.36);
  height: calc(var(--tile) * 0.36);
  border: 2px solid var(--paper);
  box-shadow: 0 0 0 1px var(--outline);
}
/* Embers glow: the stronger, the whiter and the wider the glow. */
.token.ember { border-radius: 50%; color: var(--outline); font: 600 calc(var(--tile) * 0.2) / 1 var(--font-glyph); }
.token.ember.dim { background: var(--dim); box-shadow: 0 0 0 1px var(--outline), 0 0 6px var(--dim); }
.token.ember.glowing { background: var(--bright); box-shadow: 0 0 0 1px var(--outline), 0 0 9px var(--bright); }
.token.ember.bright { background: var(--blazing); box-shadow: 0 0 0 1px var(--outline), 0 0 13px var(--blazing); }
/* The two strongest, deeper than floor 40: white-hot, then near white with a gold halo. */
.token.ember.blazing { background: #fff8e6; box-shadow: 0 0 0 1px var(--outline), 0 0 16px #ffe9a8; }
.token.ember.radiant { background: #ffffff; box-shadow: 0 0 0 1px var(--outline), 0 0 20px #ffd76a, 0 0 6px #fff; }
.token.thing { border-radius: 4px; background: var(--paper); color: var(--outline); }
.token.thing svg { width: 80%; height: 80%; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
/* Gear's condition, the same look everywhere it shows: a cracked piece is worn, yellowed paper with
   a faint crack behind its picture (worn, not crossed out); a reinforced one has rivets; broken junk
   is greyed and dark. */
.token.thing.cracked, .slot.filled.cracked {
  background-color: #ddd0b6;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Cpath d='M3 5 L12 13 L9 18 L19 23 L16 28 L27 33 L25 38' fill='none' stroke='%236b4a2b' stroke-opacity='0.35' stroke-width='1.1' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E");
  background-size: 100% 100%;
  box-shadow: inset 0 0 10px rgb(107 74 43 / 0.45);
}
.slot.filled.cracked.picked, .slot.filled.cracked.over { box-shadow: 0 0 0 3px var(--torch), inset 0 0 10px rgb(107 74 43 / 0.45); }
.token.thing.broken { background: #8d8a83; filter: brightness(0.7); }
.slot.filled.broken { background: #8d8a83; color: #3b3834; }
.slot.filled.reinforced, .token.thing.reinforced {
  background-image: radial-gradient(circle, var(--steel) 0 2px, var(--outline) 2.5px 3px, transparent 3.5px),
    radial-gradient(circle, var(--steel) 0 2px, var(--outline) 2.5px 3px, transparent 3.5px);
  background-size: 12px 12px;
  background-position: right 3px bottom 3px, left 3px bottom 3px;
  background-repeat: no-repeat;
}

/* On the stairs: go deeper, or head home. */
.stairs-card {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 64px; /* above the turn buttons */
  display: grid;
  gap: 8px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 10px;
  cursor: default;
}
.stairs-card p { margin: 0; font-size: 13px; text-align: center; text-wrap: balance; }
.stairs-card .row { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; }
.stairs-card .btn { min-height: 44px; padding: 0 8px; }
.end-lines { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.end-lines li { color: var(--ink); font-size: 14px; line-height: 1.35; }
.end-lines li:empty { display: none; }
/* Share and Dare someone, side by side (a row with neither is gone). */
.end .end-card .row.end-buttons { display: flex; gap: 8px; margin: 10px 0 4px; }
.end-buttons .btn { flex: 1 1 0; }
.end-buttons .btn[hidden] { display: none; }
.end .end-card .row.end-buttons:not(:has(.btn:not([hidden]))) { display: none; }
/* A dare's verdict: both scores side by side, the winner's bright. */
.dare-verdict { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px; padding: 10px; border: 1px solid var(--edge); border-radius: 10px; text-align: center; }
.dare-verdict div { display: grid; }
.dare-verdict b { font: 700 26px/1.1 var(--font-glyph); font-variant-numeric: tabular-nums; color: var(--muted); }
.dare-verdict span { font-size: 12px; color: var(--muted); }
.dare-verdict i { font-style: normal; font-size: 12px; color: var(--muted); }
.dare-verdict.won div:first-child b, .dare-verdict.lost div:last-child b, .dare-verdict.tie b { color: var(--torch); }
.dare-verdict.won { border-color: var(--torch); }
.end-lines .prize { color: var(--good); }
/* While you were gone: each piece of news, the marks it brought on the right. */
.camp-news-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.camp-news-list li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 10px 12px; border: 1px solid var(--edge); border-radius: 10px; background: var(--surface); }
.camp-news-list li span { min-width: 0; }
.camp-news-list li b { color: var(--good); font-variant-numeric: tabular-nums; white-space: nowrap; }
.camp-news-total { margin: 4px 0 0; color: var(--muted); }
.end-card { max-height: 100%; overflow-y: auto; }
/* Your lost bag on the floor: a paper satchel with a torch-coloured edge, so it reads as yours. */
.token.lost-bag {
  width: calc(var(--tile) * 0.48);
  height: calc(var(--tile) * 0.48);
  margin-left: calc(var(--tile) * -0.24);
  border-color: var(--torch);
  border-radius: 6px;
  background: var(--paper);
  color: var(--outline);
}
.token.lost-bag svg { width: 80%; height: 80%; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.end { touch-action: auto; } /* typing and scrolling inside the card */
.moment { display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--edge); }
.moment label { font-weight: 600; }
.moment-more:not([hidden]) { display: grid; gap: 6px; }
.moment textarea {
  width: 100%;
  min-height: 56px;
  padding: 8px 10px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--void);
  color: var(--ink);
  font: 16px/1.35 var(--font-ui); /* 16px keeps phones from zooming in */
  resize: vertical;
}
.moment .keys { margin: 0; font-size: 12px; }
.rating-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; font-weight: 600; }
.rating { display: flex; }
.rating-star {
  width: 40px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--edge);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}
.rating-star.on { color: var(--torch); }

/* Red: tiles that take damage on the monsters' next turn. Each sits just above the floor as
   its own plane (a shared raised layer didn't get drawn). */
.dangers { position: absolute; left: 0; top: 0; transform-style: preserve-3d; }
.danger {
  position: absolute;
  left: calc(var(--x) * var(--tile));
  top: calc(var(--y) * var(--tile));
  width: var(--tile);
  height: var(--tile);
  transform: translateZ(1px);
  background: var(--danger-fill);
  box-shadow: inset 0 0 0 2px var(--danger);
  animation: warn 0.7s ease-in-out infinite alternate;
}
@keyframes warn { from { opacity: 0.55; } to { opacity: 1; } }
/* A Sunglass: pale, what monsters in your light would wind up next turn. */
.danger.soon { background: none; box-shadow: inset 0 0 0 2px var(--danger); opacity: 0.4; animation: none; }
/* An Orb weaver's web, coming next turn: pale, not red, as it doesn't hurt. */
.danger.snag, .danger.knock { background: rgb(228 230 240 / 0.3); box-shadow: inset 0 0 0 2px rgb(238 240 248 / 0.9); }
/* The Attack preview: every tile your weapon can reach now. */
.danger.aim { background: rgb(240 170 60 / 0.22); box-shadow: inset 0 0 0 2px rgb(240 170 60 / 0.75); animation: none; }
/* Your reach over a red tile: the red shows through, ringed in yellow inside its edge. */
.danger.aim.over { background: none; box-shadow: none; outline: 2px solid rgb(240 170 60 / 0.95); outline-offset: calc(var(--tile) * -0.2); }
/* What the creature whose card is open can see: where it would spot you. */
.danger.sight { background: rgb(240 220 150 / 0.16); box-shadow: inset 0 0 0 1px rgb(240 220 150 / 0.35); animation: none; }
/* Burning ground: anything that steps on it takes 1. */
.danger.smoulder {
  background: radial-gradient(circle at 50% 60%, rgb(255 200 90 / 0.6), rgb(230 90 30 / 0.35) 55%, rgb(230 90 30 / 0.1) 80%);
  box-shadow: inset 0 0 0 1px rgb(240 140 40 / 0.8);
  animation: flicker 0.45s ease-in-out infinite alternate;
}
@keyframes flicker { from { opacity: 0.65; } to { opacity: 1; } }

/* Hazards, flat on the floor (rules/hazards.js): ice, webs, fungus, and spore clouds over them.
   Past your light they're dim, like loot. */
.hazards { position: absolute; left: 0; top: 0; transform-style: preserve-3d; }
.hazard {
  position: absolute;
  left: calc(var(--x) * var(--tile));
  top: calc(var(--y) * var(--tile));
  width: var(--tile);
  height: var(--tile);
  transform: translateZ(0.5px);
  opacity: 0.35;
}
.hazard.lit { opacity: 1; }
.hazard svg { display: block; width: 100%; height: 100%; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.hazard.ice {
  background: linear-gradient(135deg, rgb(160 205 250 / 0.22) 0 38%, rgb(235 248 255 / 0.5) 44% 50%, rgb(160 205 250 / 0.22) 56%);
  box-shadow: inset 0 0 0 1px rgb(190 225 255 / 0.55);
}
.hazard.web svg { stroke: rgb(230 228 215 / 0.85); stroke-width: 0.9; }
.hazard.fungus svg .cap { fill: rgb(132 98 158); stroke: rgb(52 36 64); stroke-width: 1; }
.hazard.fungus svg .spot { fill: rgb(214 226 140); }
.hazard.cloud {
  transform: translateZ(3px);
  background: radial-gradient(circle, rgb(160 205 95 / 0.55), rgb(160 205 95 / 0.2) 65%, transparent 80%);
  animation: drift 1.4s ease-in-out infinite alternate;
}
.hazard.cloud:not(.lit) { opacity: 0.35; animation: none; }
@keyframes drift { from { opacity: 0.6; scale: 0.92; } to { opacity: 1; scale: 1.05; } }
/* What brewed things leave on the floor: light from a Glow bottle or a Sun drop, a Salt line,
   Lure meat. */
.hazard.glowing { opacity: 1; background: radial-gradient(circle, rgb(255 226 150 / 0.28), rgb(255 226 150 / 0.12) 70%); }
.hazard.salt { background: radial-gradient(circle, rgb(240 238 228 / 0.85) 0 2px, transparent 3px) 0 0 / 25% 25%; }
.hazard.lure { background: radial-gradient(circle, rgb(170 60 52) 0 22%, rgb(110 40 34) 26%, transparent 30%); }
/* Hoard-Mother's nest: straw and a glow of stolen embers. */
.hazard.nest {
  background: radial-gradient(circle at 30% 35%, rgb(255 150 60 / 0.75) 0 6%, transparent 9%),
    radial-gradient(circle at 68% 62%, rgb(255 120 40 / 0.7) 0 5%, transparent 8%),
    radial-gradient(circle at 55% 25%, rgb(255 190 90 / 0.6) 0 4%, transparent 7%),
    repeating-linear-gradient(35deg, rgb(150 118 70 / 0.45) 0 2px, transparent 2px 6px),
    rgb(90 60 30 / 0.35);
}
/* A cold camp (rules/campfire.js): a ring of stones round ash, coals glowing in it until they're out. */
.hazard.campfire, .hazard.ashring {
  border-radius: 50%;
  background: radial-gradient(circle, rgb(40 34 30 / 0.85) 0 45%, transparent 47%);
  box-shadow: inset 0 0 0 3px #8a857c;
  scale: 0.8;
}
/* One coal glowing for each one left. */
.hazard.campfire.coals-1 {
  background: radial-gradient(circle at 50% 50%, rgb(255 140 50 / 0.95) 0 8%, transparent 11%),
    radial-gradient(circle, rgb(40 34 30 / 0.85) 0 45%, transparent 47%);
}
.hazard.campfire.coals-2 {
  background: radial-gradient(circle at 42% 46%, rgb(255 140 50 / 0.95) 0 8%, transparent 11%),
    radial-gradient(circle at 58% 56%, rgb(255 110 40 / 0.9) 0 7%, transparent 10%),
    radial-gradient(circle, rgb(40 34 30 / 0.85) 0 45%, transparent 47%);
}
.hazard.campfire.coals-3 {
  background: radial-gradient(circle at 42% 48%, rgb(255 140 50 / 0.95) 0 8%, transparent 11%),
    radial-gradient(circle at 58% 56%, rgb(255 110 40 / 0.9) 0 7%, transparent 10%),
    radial-gradient(circle at 52% 38%, rgb(255 190 90 / 0.9) 0 6%, transparent 9%),
    radial-gradient(circle, rgb(40 34 30 / 0.85) 0 45%, transparent 47%);
}
/* Ingredients look picked, not made: a green-grey paper. */
.token.thing.ingredient, .slot.filled.ingredient, .chron-icon.ingredient { background: #cfdcb4; }
.flash {
  position: absolute;
  left: calc(var(--x) * var(--tile));
  top: calc(var(--y) * var(--tile));
  width: var(--tile);
  height: var(--tile);
  transform: translateZ(2px);
  background: var(--blast);
  animation: blast 420ms ease-out forwards;
}
@keyframes blast { from { opacity: 1; } to { opacity: 0; } }
/* A wall face: stood up at the tile's south edge, then turned to its own side (--side).
   Faces turned away from the camera aren't drawn. */
.face {
  position: absolute;
  left: calc(var(--x) * var(--tile));
  top: calc(var(--y) * var(--tile) + (var(--tile) - var(--wall-h)) / 2);
  width: var(--tile);
  height: var(--wall-h);
  transform: rotateZ(var(--side)) translate3d(0, calc(var(--tile) / 2), calc(var(--wall-h) / 2)) rotateX(-90deg);
  backface-visibility: hidden;
  background: linear-gradient(to bottom, var(--wall-lip) 0 2px, var(--wall) 2px, var(--wall-face));
  box-shadow: inset 0 0 0 1px var(--seam);
}
.face.door { background: linear-gradient(to top, rgb(240 165 58 / 0.7), rgb(240 165 58 / 0.15) 35%, var(--wall-face) 70%); box-shadow: inset 0 0 0 1px var(--seam), inset 4px 0 0 rgb(240 165 58 / 0.5), inset -4px 0 0 rgb(240 165 58 / 0.5); }
.view.instant .plane, .view.instant .board, .view.instant .actor, .view.instant .paper, .view.instant .compass, .view.instant .glow { transition: none; transition-delay: 0s; }

/* Rooms and corridors the player isn't in fade toward the dark. */
.t, .face { opacity: calc(1 - var(--fog)); }
.t.lit, .face.lit { opacity: 1; }
/* The torch's warm light on the floor, centred on you. It's drawn once at its widest (--max
   tiles across from the middle) and scaled down to what the torch reaches: resizing a big
   tilted layer every turn made phones flash black. */
.glow {
  position: absolute;
  left: calc((var(--x) + 0.5 - var(--max)) * var(--tile));
  top: calc((var(--y) + 0.5 - var(--max)) * var(--tile));
  width: calc(var(--max) * 2 * var(--tile));
  height: calc(var(--max) * 2 * var(--tile));
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(239 182 76 / 0.2), rgb(239 182 76 / 0.08) 60%, transparent);
  transform: translateZ(1px) scale(var(--scale, 1));
  pointer-events: none;
  transition: left var(--step) ease-out, top var(--step) ease-out, transform 0.4s ease-out;
}
/* The glow flickers like fire, and gutters when the torch is low. Only its opacity moves. */
.glow { animation: flicker 2.6s ease-in-out infinite; }
.torch-low .glow { animation: gutter 2.6s ease-in-out infinite; }
@keyframes flicker { 0%, 100% { opacity: 1; } 22% { opacity: 0.86; } 47% { opacity: 0.97; } 71% { opacity: 0.82; } }
@keyframes gutter { 0%, 100% { opacity: 0.9; } 18% { opacity: 0.6; } 36% { opacity: 0.92; } 58% { opacity: 0.5; } 78% { opacity: 0.85; } 90% { opacity: 0.65; } }
@media (prefers-reduced-motion: reduce) { .glow, .torch-low .glow { animation: none; } }
/* The torch's light inside your area: dim just past its edge, dark beyond. */
.t.lit.dusk, .face.lit.dusk { opacity: 0.5; }
.t.lit.dark, .face.lit.dark { opacity: calc(1 - var(--night)); }

/* The view's edges fade into the dark, so a room or hallway running past the edge reads as open. */
.fog {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to right, var(--void), transparent calc(var(--tile) * 0.9)),
    linear-gradient(to left, var(--void), transparent calc(var(--tile) * 0.9)),
    linear-gradient(to bottom, var(--void), transparent calc(var(--tile) * 1.6)),
    linear-gradient(to top, var(--void), transparent calc(var(--tile) * 1.6));
}

/* Quarter-turn buttons in the view's bottom corners. */
.turn-btn {
  position: absolute;
  bottom: 12px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  font: 600 22px/1 var(--font-ui);
  cursor: pointer;
  touch-action: manipulation;
}
.turn-btn.left { left: 12px; }
.turn-btn.right { right: 12px; }
.turn-btn:active { background: var(--edge); }

/* What ails you, a chip each, along the bottom of the view between the turn buttons. */
.states {
  position: absolute;
  left: 64px;
  right: 64px;
  bottom: 18px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px;
  pointer-events: none;
}
.state {
  padding: 3px 9px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--surface);
  font: 600 12px/1.3 var(--font-glyph);
  white-space: nowrap;
}
.state.burning { color: rgb(244 150 60); border-color: rgb(244 150 60 / 0.6); }
.state.poisoned { color: rgb(160 210 95); border-color: rgb(160 210 95 / 0.6); }
.state.frightened { color: var(--danger); border-color: var(--danger); }
.state.snared, .state.slowed { color: rgb(180 215 250); border-color: rgb(180 215 250 / 0.6); }
.state.stunned { color: var(--torch); border-color: var(--torch); }
.state.steady { color: var(--muted); }
/* A weapon's own move (a Bone knife's free step): lit when ready, dim while it rests. */
.state.skill.ready { color: var(--ink); border-color: var(--ink); }
.state.skill.now { color: var(--surface); background: var(--ink); border-color: var(--ink); }
.state.skill.resting { color: var(--muted); }

/* The turn-order switch, in the view's top-left corner. */
.order-btn {
  position: absolute;
  top: 12px;
  left: 12px;
  min-width: 44px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--edge);
  border-radius: 16px;
  background: var(--surface);
  color: var(--muted);
  font: 600 12px var(--font-glyph);
  cursor: pointer;
  touch-action: manipulation;
}
.order-btn[aria-pressed="true"] { background: var(--torch); border-color: var(--torch); color: var(--void); }
/* Aa, under 1·2·3: the names of things on the ground. */
.names-btn { top: 52px; }
.loot-name {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 0.42 + var(--n, 0) * 13px);
  transform: translateX(-50%);
  white-space: nowrap;
  font: 600 10px/1.2 var(--font-ui, inherit);
  color: #f3e6cf;
  text-shadow: 0 1px 2px #000, 0 0 4px #000;
  pointer-events: none;
}
.show-names .loot-token.lit .loot-name { display: block; }

/* A monster's card, over the bottom of the view. */
.monster-card {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 64px;
  display: grid;
  gap: 6px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 10px;
  box-shadow: 0 10px 30px var(--scrim);
  cursor: default;
}
.monster-card p { margin: 0; font-size: 14px; line-height: 1.4; }
.monster-card .mc-meta { color: var(--muted); font-size: 13px; }
.mc-head { display: flex; align-items: center; gap: 10px; font-weight: 600; }
.mc-health { margin-left: auto; color: var(--muted); font: 600 12px var(--font-glyph); }
.mc-letter {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 2px solid var(--paper);
  border-radius: 4px;
  color: var(--paper);
  font: 600 15px / 1 var(--font-glyph);
}
.mc-letter.boar { background: var(--boar); }
.mc-letter.moth { background: var(--moth); }
.mc-letter.beetle { background: var(--beetle); }
.mc-letter.shade { background: var(--shade); }
.mc-letter.grub { background: var(--grub); }
.mc-letter.rat { background: var(--rat); }
.mc-letter.toad { background: var(--toad); }

/* The torch: turns of light left on this floor, top middle of the view. */
.torch-meter {
  position: absolute;
  top: 12px;
  left: 50%;
  width: min(128px, calc(100% - 192px)); /* narrow screens: clear of the corner buttons */
  height: 32px;
  translate: -50% 0;
  overflow: hidden;
  border: 1px solid var(--edge);
  border-radius: 16px;
  background: var(--surface);
  padding: 0;
  font: inherit;
  cursor: pointer;
  touch-action: manipulation;
}
.torch-meter:active { border-color: var(--bright); }
.torch-fill {
  position: absolute;
  inset: 0;
  transform-origin: left;
  transform: scaleX(var(--left, 1));
  background: rgb(239 182 76 / 0.32);
  transition: transform var(--step) linear;
}
.torch-text {
  position: relative;
  display: grid;
  place-items: center;
  height: 100%;
  color: var(--ink);
  font: 600 11px / 1 var(--font-glyph);
}
.torch-meter.low .torch-fill { background: rgb(224 83 63 / 0.4); }
.torch-meter.out { border-color: var(--danger); }
.torch-meter.out .torch-text { color: var(--danger); }

/* Sound on and off, beside the compass. */
.sound-btn {
  position: absolute;
  top: 12px;
  right: 52px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  touch-action: manipulation;
}
.sound-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sound-btn .cross { display: none; }
.sound-btn.off .wave { display: none; }
.sound-btn.off .cross { display: inline; }

/* Points to map north however the view is turned. */
.compass {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--surface);
  pointer-events: none;
  transform: rotate(var(--heading));
  transition: transform var(--turn) ease-in-out;
}
.compass span {
  position: absolute;
  top: 3px;
  left: 50%;
  transform: translateX(-50%);
  color: var(--torch);
  font: 600 11px/1 var(--font-glyph);
}
/* A Sunward needle, under the compass: an arrow toward the stairs. */
.needle {
  position: absolute;
  top: 52px;
  right: 12px;
  width: 32px;
  height: 32px;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--surface);
  pointer-events: none;
  transform: rotate(calc(var(--heading) + var(--to-stairs, 0deg)));
  transition: transform var(--turn) ease-in-out;
}
.needle[hidden] { display: none; }
.needle::after {
  content: "";
  position: absolute;
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-bottom: 11px solid var(--torch);
  border-top: 0;
}
.compass::after { /* a short needle from the middle toward the N */
  content: "";
  position: absolute;
  top: 15px;
  left: 50%;
  width: 0;
  height: 0;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-bottom: 7px solid var(--muted);
  border-top: 0;
}

.toast {
  position: absolute;
  top: 52px; /* under the torch meter and the corner buttons */
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100% - 24px);
  margin: 0;
  padding: 7px 14px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 999px;
  font-size: 13px;
  text-align: center;
  text-wrap: balance;
  pointer-events: none;
}

/* ─── Run end ─── */
.end { position: absolute; inset: 0; display: grid; place-items: center; padding: 16px; background: var(--scrim); cursor: default; }
.end-card {
  width: 100%;
  max-width: 300px;
  display: grid;
  gap: 12px;
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 12px;
}
.end-card h2 { margin: 0; font: 600 17px/1.3 var(--font-glyph); text-wrap: balance; }
.end-card p { margin: 0; color: var(--muted); }
.end-card .row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

/* ─── Buttons ─── */
.controls { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
#attack-button[aria-pressed="true"] { background: var(--torch); border-color: var(--torch); color: var(--void); }
.btn {
  min-height: 48px;
  padding: 0 14px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font-weight: 500;
  cursor: pointer;
  touch-action: manipulation;
}
.btn:active:not(:disabled) { background: var(--edge); }
.btn:disabled { color: var(--muted); opacity: 0.5; cursor: default; }
.btn[aria-expanded="true"] { border-color: var(--torch); }
.btn.primary { background: var(--torch); border-color: var(--torch); color: var(--void); }
.btn.small { min-height: 44px; padding: 0 12px; }

/* ─── Test settings ─── */
.panel {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 2;
  display: grid;
  gap: 10px;
  padding: 12px 16px 16px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 12px;
  box-shadow: 0 16px 48px var(--scrim);
  max-height: 50%; /* keeps the player, in the middle of the view, in sight while adjusting */
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* ─── Sandbox bar ─── */
.sandbox-bar { display: flex; gap: 4px; }
.sandbox-bar .btn { flex: 1 1 auto; min-width: 0; padding: 0 4px; font-size: 13px; white-space: nowrap; }
/* Respawn on: the button's edge takes the torch's colour. */
.sandbox-bar .btn.on { border-color: var(--torch); color: var(--torch); }
.sandbox-bar .btn[aria-pressed="true"] { background: var(--torch); border-color: var(--torch); color: var(--void); }

/* ─── Gear: what you wear, a slot a part, over the bag, 3 × 2 ─── */
.panel.gear { max-height: 92%; }
/* minmax(0, 1fr): a long name wraps inside its slot rather than widening the column (Kevin, Oct 16,
   2026: filled bag slots came out bigger than the worn ones, and off line with them). The same gap as
   the worn grid's, so bag columns sit under the worn ones. */
.slots, .worn { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; width: min(100%, 252px); margin-inline: auto; }
.slot { min-width: 0; min-height: 0; overflow: hidden; overflow-wrap: break-word; hyphens: auto; }
.slot svg { flex-shrink: 0; }
/* A count beside charges (Ember darts ×10, 10/10): the count goes top right, clear of them. */
.slot:has(.charges) .count { left: auto; right: 6px; }
/* Worn: helm and charm centred on top, weapon, boots and off hand below. */
.worn { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.worn .slot { grid-column: span 2; }
.worn .slot:first-child { grid-column: 2 / span 2; }
.gear-label { width: min(100%, 252px); margin: 2px auto -4px; font: 600 11px var(--font-ui); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.slot {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 3px;
  padding: 5px 3px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--void);
}
.slot { position: relative; color: var(--muted); }
.slot.empty { border-style: dashed; }
.slot.keep { border: 2px solid var(--torch); }
.slot.keep.empty { border-style: dashed; }
/* A worn slot is the size of a bag slot (Kevin, Oct 16, 2026; it used to be shorter, to fit the
   dungeon's Gear panel); empty, it names its part. */
.slot.part { padding: 4px; gap: 2px; }
.slot.part .part-name { font-size: 10px; }
/* In the dungeon's Gear panel the slots are a little smaller, so five worn and nine in the bag fit a
   phone without scrolling. */
.panel.gear .slots, .panel.gear .worn, .panel.gear .gear-label { width: min(100%, 228px); }
.slot.part .part-name { font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.slot .kept { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--torch); }
.slot.filled { background: var(--paper); color: var(--outline); cursor: pointer; }
.slot.filled.ember.dim { background: var(--dim); }
.slot.filled.ember.glowing { background: var(--bright); }
.slot.filled.ember.bright { background: var(--blazing); }
.slot.filled.ember.blazing { background: #fff8e6; }
.slot.filled.ember.radiant { background: #ffffff; box-shadow: inset 0 0 8px #ffd76a; }
.slot.picked { box-shadow: 0 0 0 3px var(--torch); }
.slot.target { cursor: pointer; outline: 1px dashed var(--torch); outline-offset: -5px; }
.slot svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.slot span { font-size: 10.5px; font-weight: 600; line-height: 1.1; text-align: center; }
.slot .count { position: absolute; top: 4px; left: 6px; font: 600 12px var(--font-glyph); }
.slot .worth { position: absolute; top: 4px; right: 6px; font: 600 11px var(--font-glyph); font-style: normal; }
.item-info { display: grid; gap: 8px; justify-items: start; min-height: 64px; }
/* The off hand while a two-handed weapon is worn: greyed, can't be filled. */
.worn .slot.blocked { opacity: 0.45; border-style: solid; }
.worn .slot.blocked .blocked-note { font: italic 600 10px var(--font-ui); color: var(--muted); }
/* In the Gear panel what you tapped stays in sight at the bottom, however long the bag. */
/* min-height: max-content, or the panel's grid squeezes it to 64px when the bag is long. */
.panel.gear .item-info { min-height: max-content; position: sticky; bottom: -16px; z-index: 1; margin: 0 -16px -16px; padding: 10px 16px 16px; background: var(--surface); border-top: 1px solid var(--edge); }
.item-info p { margin: 0; }
.add-row { display: flex; flex-wrap: wrap; gap: 6px; }
.give-items { display: grid; gap: 6px; }
.give-items p { margin: 4px 0 0; }

/* Dragging a slot: a ghost follows the finger; the slot it would land on lights up. */
.slot.filled { touch-action: none; user-select: none; -webkit-user-select: none; }
.slot.dragging { opacity: 0.35; }
.slot.over, .drop-zone.over { box-shadow: 0 0 0 3px var(--torch); }
.slot.ghost {
  position: fixed;
  z-index: 10;
  margin: 0;
  pointer-events: none;
  opacity: 0.92;
  box-shadow: 0 10px 24px var(--scrim);
  rotate: -4deg;
}
.drop-zone {
  justify-self: stretch;
  display: grid;
  place-items: center;
  min-height: 56px;
  border: 2px dashed var(--muted);
  border-radius: 8px;
  color: var(--muted);
  font-weight: 600;
}

.slider { display: grid; grid-template-columns: 4.5em 1fr 4.5em; align-items: center; gap: 10px; min-height: 44px; }
.slider input { width: 100%; margin: 0; accent-color: var(--torch); }
.slider output { color: var(--muted); font: 13px var(--font-glyph); font-variant-numeric: tabular-nums; text-align: right; }
.panel-head { display: flex; align-items: center; justify-content: space-between; }
.panel h2 { margin: 0; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.panel fieldset { display: grid; margin: 0; padding: 0; border: 0; }
.panel legend { padding: 0; font-weight: 600; }
.panel label { display: flex; align-items: center; gap: 10px; min-height: 44px; cursor: pointer; }
.panel input[type="radio"], .panel input[type="checkbox"] { width: 20px; height: 20px; margin: 0; accent-color: var(--torch); }
.seed-row { display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 8px; }
.seed-row input {
  min-width: 0;
  min-height: 44px;
  padding: 0 10px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--void);
  font: 16px var(--font-glyph);
}
.keys { margin: 0; color: var(--muted); font-size: 13px; }

@media (prefers-reduced-motion: reduce) {
  .plane, .board, .actor, .paper, .compass { transition: none; }
  .danger, .stars, .flash, .hazard, .card, .hero { animation: none; }
  .flash { opacity: 0; }
}

/* What lies where you stand, under the bag in the Gear panel; and the Gear button's dot for it. */
.ground-slots:not([hidden]) { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; width: min(100%, 252px); margin-inline: auto; }
.relic-slots:not([hidden]) { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; width: min(100%, 252px); margin-inline: auto; }
#gear-button { position: relative; }
#gear-button.underfoot::after {
  content: "";
  position: absolute;
  top: 6px;
  right: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--bright);
}

/* ─── Camp ───────────────────────────────────────────────────────────────────
   Between runs: the fire and how big the camp has grown up top, the camp to walk about in, and
   a bar of places at the bottom. It covers the whole game; the places' panels cover it. */
.camp {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--void);
}
.camp h3 { margin: 12px 0 0; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.camp-head { display: flex; align-items: center; gap: 10px; padding: 10px 16px 8px; }
.camp-about { display: grid; gap: 3px; min-width: 0; flex: 1; }
.camp-head h2 { margin: 0; font-size: 17px; }
/* The game's name, over the camp's. */
.camp-title { margin: 0 0 8px; font: 700 22px/1.1 var(--font-glyph); letter-spacing: 0.12em; text-transform: uppercase; color: var(--torch); }
/* What's waiting for you, under the camp's goal: small chips, the ones you can act on buttons. */
.camp-status { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.camp-status .chip { padding: 4px 9px; border: 1px solid var(--edge); border-radius: 999px; background: var(--surface); color: var(--muted); font: 500 12px/1.3 var(--font-ui); }
.camp-status .chip b { color: var(--bright); }
.camp-status button.chip { color: var(--ink); border-color: var(--torch); cursor: pointer; }
/* The camp's next goal, over its bar. */
.camp-top-goal.great { cursor: pointer; }
.camp-top-goal.great .camp-bar span { background: var(--torch); }
.camp-top-goal.great .camp-bar { position: relative; height: 8px; border-radius: 4px; overflow: visible; }
.camp-top-goal.great .camp-bar span { border-radius: 4px; }
.camp-top-goal .camp-bar em { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--muted); }
.camp-top-goal .camp-bar em.lit { top: 0; bottom: 0; background: var(--void); }
.camp-bar { width: 100%; height: 5px; margin-top: 6px; border-radius: 3px; background: var(--edge); overflow: hidden; }
.camp-bar span { display: block; height: 100%; width: 0; background: var(--bright); transition: width 0.6s ease-out; }
.camp-next { margin: 2px 0 0; color: var(--ink); font-size: 13px; text-wrap: balance; }
.camp-next .goal { display: inline-block; margin-right: 4px; padding: 1px 6px; border-radius: 4px; background: var(--torch); color: var(--void); font: 700 10px/1.5 var(--font-ui); letter-spacing: 0.06em; text-transform: uppercase; vertical-align: 1px; }
.camp-head .keys { margin: 0; font-size: 12px; }
.settings-version { margin-top: 24px; text-align: center; }
/* Start over from nothing, in Settings: out of the way, two taps. */
.camp-wipe { margin-top: 28px; color: var(--muted); }

/* The camp, in the dungeon's view (ui/campmap.js): its things stand up as paper cutouts. */
.camp-map {
  flex: 1;
  min-height: 0;
  /* Trodden earth, not the dungeon's stone; the rock past the light, near black. */
  --floor: #4b3a29;
  --hall: #4b3a29;
  --seam: #3b2d1f;
  --wall: #1c1814;
  --wall-lip: #26201a;
  --wall-face: #12100d;
}
/* The fire's light on the ground: warmer and stronger than a torch's. */
.camp-map .glow { background: radial-gradient(closest-side, rgb(255 196 100 / 0.42), rgb(239 160 60 / 0.16) 65%, transparent); }
.camp-view { border-radius: 0; }
.prop { pointer-events: none; }
.prop[data-prop] .prop-card, .prop[data-prop] .prop-label { pointer-events: auto; cursor: pointer; }
.prop-card { width: calc(var(--tile) * 1.2); height: calc(var(--tile) * 1.2); margin-left: calc(var(--tile) * -0.6); }
.prop-card svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke: var(--outline);
  stroke-width: 1.4;
  stroke-linejoin: round;
  stroke-linecap: round;
  filter: drop-shadow(0 0 1px var(--paper)) drop-shadow(0 0 1px var(--paper));
}
.prop.k-tent .prop-card, .prop.k-house .prop-card { scale: 1.25; transform-origin: 50% 100%; }
.prop.k-wall .prop-card { scale: 1.1 1.25; transform-origin: 50% 100%; }
.prop.k-fire .prop-card svg { filter: drop-shadow(0 0 10px var(--bright)); }
.prop-label {
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tile) * 1.15);
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  color: #f3e6cf;
  text-shadow: 0 1px 2px #000, 0 0 4px #000;
}
.prop.k-stairs .prop-label { bottom: calc(50% + var(--tile) * 0.2); }
.prop-card .camp-badge { position: absolute; top: -4px; right: -6px; }
.camp-badge {
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--bright);
  color: #1b130a;
  font: 700 11px/16px var(--font-glyph);
  font-style: normal;
  text-align: center;
}
/* A sign stands on top of its block (--lift, in tiles), in the middle of it. */
.actor.prop {
  transform:
    translateZ(calc(var(--lift, 0) * var(--tile) + 2px))
    rotateZ(calc(var(--heading) * -1))
    translateY(calc(var(--tile) * 0.2))
    rotateX(calc(var(--tilt) * -1));
}
.prop-card { width: calc(var(--tile) * 0.9); height: calc(var(--tile) * 0.9); margin-left: calc(var(--tile) * -0.45); }
.prop.k-fire .prop-card { width: calc(var(--tile) * 1.1); height: calc(var(--tile) * 1.1); margin-left: calc(var(--tile) * -0.55); }
.prop-label { bottom: calc(50% + var(--tile) * 0.95) !important; }
.prop.k-stairs .prop-label { bottom: calc(50% + var(--tile) * 0.15) !important; }

/* The camp's blocks: the dungeon's clutter, in the camp's colours. --cw is its width and --ch its
   height (src/campmap.js blockHeight); the sides are --side-c, the top --top-c. */
.face.clutter.camp { --cw: 0.84; background: linear-gradient(to bottom, var(--top-c) 0 2px, var(--side-c) 2px, color-mix(in srgb, var(--side-c), #000 35%)); }
.face.clutter.camp.lid { background: var(--top-c); box-shadow: inset 0 0 0 1px var(--seam), inset 0 0 0 3px color-mix(in srgb, var(--top-c), #000 15%); }
.face.clutter.k-fire { --cw: 0.7; --ch: calc(var(--tile) * 0.14); --side-c: #6b655d; --top-c: #2b1d12; }
.face.clutter.k-fire.lid { background: radial-gradient(closest-side, #ffcf6b, #e0782e 55%, #2b1d12); }
.face.clutter.k-apothecary { --ch: calc(var(--tile) * 0.3); --side-c: #6e4a2c; --top-c: #8a6240; }
.face.clutter.k-apothecary.t2, .face.clutter.k-apothecary.t3, .face.clutter.k-apothecary.t4 { --cw: 0.92; --ch: calc(var(--tile) * 0.45); }
.face.clutter.k-smith { --cw: 0.62; --ch: calc(var(--tile) * 0.35); --side-c: #5b3d24; --top-c: #6f747c; }
.face.clutter.k-smith.t2, .face.clutter.k-smith.t3, .face.clutter.k-smith.t4 { --cw: 0.9; --ch: calc(var(--tile) * 0.55); --side-c: #59524b; --top-c: #3a302a; }
.face.clutter.k-trader { --cw: 0.9; --ch: calc(var(--tile) * 0.35); --side-c: #7a5233; --top-c: #9b6e45; }
.face.clutter.k-trader.t3, .face.clutter.k-trader.t4 { --ch: calc(var(--tile) * 0.5); --side-c: #7a5233; --top-c: #b0603a; }
.face.clutter.k-garden, .face.clutter.k-plot { --cw: 0.9; --ch: calc(var(--tile) * 0.12); --side-c: #5a4128; --top-c: #3e2c1c; }
.face.clutter.k-chronicle { --cw: 0.55; --ch: calc(var(--tile) * 0.4); --side-c: #6e5a48; --top-c: #8a7660; } /* a stone the book rests on */
.face.clutter.k-bedroll { --cw: 0.75; --ch: calc(var(--tile) * 0.12); --side-c: #6e5a44; --top-c: #8f7a5c; }
.face.clutter.k-pack { --cw: 0.8; --ch: calc(var(--tile) * 0.14); --side-c: #8a6a4a; --top-c: #b39b6d; }
.face.clutter.k-training { --cw: 0.5; --ch: calc(var(--tile) * 0.08); --side-c: #6b655d; --top-c: #8a847a; }
.face.clutter.k-lift { --cw: 0.9; --ch: calc(var(--tile) * 0.2); --side-c: #4e5157; --top-c: #6f747c; }
.face.clutter.k-tent { --cw: 0.9; --ch: calc(var(--tile) * 0.6); --side-c: #b5a07a; --top-c: #d8c79f; }
.face.clutter.k-pole { --cw: 0.2; --ch: calc(var(--tile) * 1.1); --side-c: #6e4a2c; --top-c: #ffcf6b; }
.face.clutter.k-pole.lid { box-shadow: 0 0 10px 4px rgb(255 196 100 / 0.7); }
.face.clutter.k-wall { --cw: 1; --ch: calc(var(--tile) * 0.95); --side-c: #6e4a2c; --top-c: #8a5f3a; background: repeating-linear-gradient(to right, #6e4a2c 0 22%, #4f3520 22% 25%); }
.face.clutter.k-house { --cw: 0.95; --ch: calc(var(--tile) * 0.95); --side-c: #cbb994; --top-c: #7b3f2c; }
.face.clutter.k-house:not(.lid) { background: linear-gradient(to bottom, #cbb994 0 40%, #ffcf6b 40% 60%, #cbb994 60%); }

/* What things are made of. */
.prop .wood { fill: #8a5f3a; }
.prop .iron { fill: #6f747c; }
.prop .cloth, .prop .canvas { fill: #c9b48a; }
.prop .door { fill: #3a2a1c; }
.prop .goods { fill: #b0603a; }
.prop .wheel { fill: #5b3d24; }
.prop .pot { fill: #4a4a50; }
.prop .steam { stroke: #d8d2c4; }
.prop .sack { fill: #b39b6d; }
.prop .glass { fill: #7fb0a0; }
.prop .forge { fill: #5b5550; }
.prop .ember { fill: var(--blazing); }
.prop .soil { fill: #3e2c1c; }
.prop .leaf { fill: #7fa65a; }
.prop .paper { fill: #eadfc6; }
.prop .cover { fill: #6b2f24; }
.prop .ink { stroke: #6b5a44; }
.prop .roll { fill: #9a6a4a; }
.prop .straw { fill: #d2b25e; }
.prop .lamp { fill: var(--bright); filter: drop-shadow(0 0 4px var(--bright)); }
.prop .roof { fill: #7b3f2c; }
.prop .plaster { fill: #d6c7a6; }
.prop .window { fill: var(--bright); }
.prop .beam, .prop .rope { stroke: #8a5f3a; stroke-width: 2; }
.prop .cage { fill: #6f747c; }
.prop .logs { stroke: #5b3d24; stroke-width: 2.5; }
.prop .flame { fill: var(--bright); stroke: var(--blazing); animation: campflame 1.6s ease-in-out infinite alternate; transform-origin: 50% 90%; }
@keyframes campflame { from { transform: scale(1, 1); } to { transform: scale(0.94, 1.06); } }
@media (prefers-reduced-motion: reduce) { .prop .flame { animation: none; } }
.camp-say {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 76px;
  z-index: 3;
  margin: 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgb(20 18 24 / 0.92);
  color: var(--ink);
  font-size: 14px;
  text-align: center;
}
/* The bar of places. */
/* 12px from the bottom, as the dungeon's buttons are (.game), so every screen's bar sits at the same
   height (Kevin, Oct 16, 2026). No safe-area inset here: the page (html) already keeps clear of the
   phone's bar, and adding it again set the camp's bar higher than a panel's (Kevin, Oct 26, 2026). */
.camp-nav { padding: 8px 8px 12px; }
.camp-row { display: flex; gap: 6px; }
.camp-row[hidden] { display: none; }
.camp-row .btn { position: relative; flex: 1 1 0; min-width: 0; min-height: 48px; padding: 0 4px; font-size: 12px; }
.camp-row [data-sheet][aria-expanded="true"] { border-color: var(--torch); }
/* The Camp and You sheets: a list over the map, just above the bar (over it, so the map stays put). */
.camp-nav { position: relative; }
.camp-sheet {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 100%;
  z-index: 4;
  max-height: 60vh;
  overflow-y: auto;
  box-shadow: 0 -6px 18px rgb(0 0 0 / 0.5);
  padding: 10px 10px 4px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: var(--surface);
}
.camp-sheet[hidden] { display: none; }
.camp-sheet h3 { margin: 0 0 6px; font-size: 13px; color: var(--muted); font-weight: 600; }
.camp-sheet-list { display: grid; gap: 6px; padding-bottom: 6px; }
.camp-sheet-list .btn { display: flex; justify-content: space-between; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px; font-size: 14px; text-align: left; }
.camp-sheet-list small { color: var(--torch); font-size: 12px; }
.camp-row .camp-badge { position: absolute; top: -5px; right: -3px; }
.camp-row .camp-badge[hidden] { display: none; }
/* Your delver: the button at camp, and its sheet. */
.camp-char {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 6px 0 0;
  padding: 10px 14px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.camp-char b { color: var(--ink); font-size: 15px; }
.camp-char b::after { content: " ›"; color: var(--muted); }
.char-preview { justify-self: center; width: 96px; height: 132px; position: relative; }
.char-preview.in-3d { width: min(280px, 80vw); height: 320px; margin-inline: auto; }
.char-preview .char-3d { width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: grab; }
.char-preview .shadow { display: none; }
.char-preview .paper { position: static; width: 100%; height: 100%; margin: 0; transform: none; }
.char-label { font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.char-name { min-height: 44px; padding: 0 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--surface); color: var(--ink); font: inherit; font-size: 16px; }
.swatches { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.swatch { height: 44px; border: 2px solid var(--edge); border-radius: 10px; background: var(--swatch); cursor: pointer; }
.swatch[aria-checked="true"] { border-color: var(--paper); box-shadow: 0 0 0 2px var(--torch); }
.char-looks { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.char-looks .btn { padding-inline: 4px; }
.char-looks .btn[aria-checked="true"] { border-color: var(--torch); color: var(--torch); }
.camp-board .dot { display: inline-block; width: 9px; height: 9px; margin-right: 6px; border-radius: 50%; background: var(--dot); vertical-align: 1px; }
.camp-marks {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 6px 0 0;
  padding: 10px 14px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
}
.camp-marks b { color: var(--bright); font: 600 18px var(--font-glyph); }
/* At home: what the next run starts with, laid out like the Gear panel. */
.camp-home { display: grid; gap: 10px; }
.camp-home .gear-label { margin-bottom: -4px; }
.camp-home .keys { margin: 0; }
.slot.sun { box-shadow: inset 0 0 0 2px rgb(240 165 58 / 0.7); }
.slot.dark { box-shadow: inset 0 0 0 2px #6c4a8c; }
.slot .charges { position: absolute; left: 6px; top: 4px; font: 600 11px var(--font-glyph); color: var(--outline); }
.slot .charges.off { opacity: 0.55; }
.slot:has(.charges.off) > svg { opacity: 0.45; }
#camp-recharge { min-height: 44px; }
.camp-home-note { margin: 0; }
.camp-ways { display: grid; gap: 8px; }
/* On the stairs, the ways down sit in the middle of the screen. */
#stairs-ways:not([hidden]) { flex: 1; align-content: center; }
.camp-ways .btn { min-height: 48px; display: flex; justify-content: center; align-items: center; gap: 8px; padding-block: 0; }
.camp-ways small { font: 400 11px var(--font-glyph); opacity: 0.75; }
.camp-board { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; counter-reset: rank; }
.camp-board li {
  counter-increment: rank;
  display: grid;
  grid-template-columns: 22px 1fr auto;
  grid-template-areas: "rank who light" "rank how light";
  column-gap: 8px;
  align-items: center;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--surface);
}
.camp-board li::before { content: counter(rank); grid-area: rank; color: var(--muted); font: 600 12px var(--font-glyph); }
.camp-board li.empty { display: block; color: var(--muted); font-size: 13px; }
.camp-board li.empty::before { content: none; }
.camp-board li.you { box-shadow: inset 0 0 0 1px var(--torch); }
.camp-board .who { grid-area: who; font-weight: 600; font-size: 14px; }
.camp-board .who i { margin-left: 6px; color: var(--bright); font: 400 11px var(--font-glyph); font-style: normal; }
.camp-board .how { grid-area: how; color: var(--muted); font-size: 12px; }
.camp-board b { grid-area: light; color: var(--bright); font: 600 15px var(--font-glyph); }
/* The Chronicle opens over the camp. */
/* As wide as the game and the camp (.game), not the whole screen. */
.chronicle {
  position: fixed;
  inset: 0;
  width: min(100%, 560px);
  margin-inline: auto;
  z-index: 21;
  overflow-y: auto;
  display: grid;
  align-content: start;
  gap: 12px;
  padding: 16px;
  background: var(--void);
}
/* A camp panel's bar sits at the bottom of the screen, like the camp's: its tabs and Back. */
.chronicle { display: flex; flex-direction: column; }
.panel-nav {
  position: sticky;
  bottom: -16px;
  z-index: 2;
  margin: auto -16px -16px;
  padding: 8px 8px calc(12px + env(safe-area-inset-bottom)); /* fixed to the screen's edge, so it clears the phone's bar itself */
  background: var(--void);
  box-shadow: 0 -8px 16px var(--void);
}
.panel-nav .btn[aria-pressed="true"] { background: var(--edge); border-color: var(--bright); color: var(--bright); }
.chronicle h2 { margin: 0; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.chronicle-list { display: grid; gap: 10px; }
.chron { display: grid; grid-template-columns: 28px 1fr; gap: 12px; padding: 12px; border: 1px solid var(--edge); border-radius: 10px; background: var(--surface); }
.chron h4 { margin: 0 0 4px; font-size: 15px; }
.chronicle-list h3 { margin: 8px 0 0; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.chron-icon { display: grid; place-items: center; width: 28px; height: 28px; border: 2px solid var(--paper); border-radius: 6px; background: var(--paper); color: var(--outline); }
/* An item's id is one of its icon's classes (embers colour by it), and a few ids are also board effects' classes
   (.flash, .shadow, .mark, .needle): keep those from moving or hiding the icon. */
.chron-icon { position: relative; inset: auto; margin: 0; transform: none; translate: none; animation: none; transition: none; opacity: 1; pointer-events: auto; font: inherit; }
.chron-icon svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.chron-icon.ember { border-radius: 50%; }
.chron-icon.ember.dim { background: var(--dim); }
.chron-icon.ember.glowing { background: var(--bright); }
.chron-icon.ember.bright { background: var(--blazing); }
.chron-icon.ember.blazing { background: #fff8e6; }
.chron-icon.ember.radiant { background: #ffffff; }
.chron p { margin: 0; font-size: 13px; line-height: 1.45; color: var(--ink); }
/* The Apothecary: each recipe's ingredients, those you're short of greyed. */
.chron.brew h4 small { font-weight: 400; color: var(--muted); }
.chron.brew h4 small.unfound { margin-left: 4px; padding: 1px 6px; border: 1px solid var(--torch); border-radius: 999px; color: var(--torch); font-size: 11px; white-space: nowrap; }
.chron.brew .recipe { margin-top: 6px; font-size: 12px; color: var(--muted); }
.chron.brew .recipe .have { color: var(--good); }
.chron.brew .btn { margin-top: 8px; }

/* The light counter in the top bar swells when an ember goes in the bag. */
.stats dd.pulse { animation: swell 0.45s ease-out; }
@keyframes swell { from { transform: scale(1.4); color: var(--bright); } to { transform: none; } }
/* What the Apothecary just learned, at the top of its list. */
.chronicle-list .said { margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--surface); color: var(--good); font-size: 14px; }
/* The garden: an empty plot is bare earth; a ready plot shows on the Garden's card. */
.chron-icon.plot-empty { background: #6b5a43; border-color: #6b5a43; }

/* Clutter (gen/floor.js): a box on a floor tile, lower than a wall and a little inset, with a
   lid on top. --cw is how much of the tile it covers, --ch how tall it stands. */
.face.clutter {
  --cw: 0.8; --ch: calc(var(--tile) * 0.42);
  left: calc((var(--x) + (1 - var(--cw)) / 2) * var(--tile));
  top: calc(var(--y) * var(--tile) + (var(--tile) - var(--ch)) / 2);
  width: calc(var(--cw) * var(--tile));
  height: var(--ch);
  transform: rotateZ(var(--side)) translate3d(0, calc(var(--cw) * var(--tile) / 2), calc(var(--ch) / 2)) rotateX(-90deg);
  background: linear-gradient(to bottom, var(--crate-lip) 0 2px, var(--crate) 2px, var(--crate-foot));
  box-shadow: inset 0 0 0 1px var(--seam), inset 0 calc(var(--ch) / 2 - 1px) 0 -1px var(--crate-band);
}
.face.clutter.lid {
  top: calc((var(--y) + (1 - var(--cw)) / 2) * var(--tile));
  height: calc(var(--cw) * var(--tile));
  transform: translateZ(var(--ch));
  background: var(--crate-lip);
  box-shadow: inset 0 0 0 1px var(--seam), inset 0 0 0 3px var(--crate);
}
.face.clutter.barrel { --cw: 0.66; --ch: calc(var(--tile) * 0.5); }
.face.clutter.barrel.lid { border-radius: 50%; }
.face.clutter.prop { --cw: 0.32; --ch: calc(var(--tile) * 0.95); background: linear-gradient(to bottom, var(--crate-lip) 0 2px, var(--shelf) 2px, var(--crate-foot)); } /* a Mines support */
.face.clutter.prop.lid { background: var(--shelf); }
.face.clutter.cart { --cw: 0.62; --ch: calc(var(--tile) * 0.45); background: linear-gradient(to bottom, #6b6c70 0 3px, #5c4431 3px, #3b2c20); } /* a Mines cart */
.face.clutter.cart.lid { background: #4a4b4f; box-shadow: inset 0 0 0 3px #6b6c70, inset 0 0 0 6px #3b2c20; }
.face.clutter.shelf { --cw: 0.9; --ch: calc(var(--tile) * 0.62); background: linear-gradient(to bottom, var(--crate-lip) 0 2px, var(--shelf) 2px 46%, var(--crate-foot) 46% 54%, var(--shelf) 54%, var(--crate-foot)); }
.face.clutter.shelf.lid { background: var(--shelf); }

/* Hoard-Mother: a boss's card, bigger than the rest and gold-edged, like the embers she sits on. */
.card.hoardmother { background: var(--rat); border-color: var(--bright); scale: 1.35; transform-origin: 50% 100%; }

/* A run the test tools were used in, flagged beside its score on the board. */
.test-flag { font: 600 0.62em/1 var(--font-ui, inherit); font-style: normal; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); border: 1px solid var(--muted); border-radius: 4px; padding: 1px 4px; margin-right: 6px; vertical-align: 2px; }

/* The Crypts. A coffin: a long stone box, lower than a wall; opened, its lid is gone and the inside
   shows dark. */
.face.clutter.coffin { --cw: 0.84; --ch: calc(var(--tile) * 0.36); background: linear-gradient(to bottom, #8d8a82 0 2px, #6e6b64 2px, #4a4843); }
.face.clutter.coffin.lid { background: #8d8a82; box-shadow: inset 0 0 0 1px var(--seam), inset 0 0 0 3px #77746c, inset 0 calc(var(--tile) * 0.3) 0 calc(var(--tile) * -0.27) #6e6b64; }
.face.clutter.coffin.lid.opened { background: #1d1c1a; box-shadow: inset 0 0 0 1px var(--seam), inset 0 0 0 4px #6e6b64; }
/* Bones on the floor. */
.hazard.bones svg { fill: none; stroke-linecap: round; }
/* The hands in the Drowned Halls' shallows, once they've grabbed. */
.hazard.hands { background: radial-gradient(ellipse 30% 22% at 38% 55%, rgb(214 222 212 / 0.8), transparent), radial-gradient(ellipse 30% 22% at 64% 44%, rgb(214 222 212 / 0.8), transparent); }
.card.crab { background: #a07a64; }
/* The Angler's lure, and its feelers across the shallows (seen only in light). */
.hazard.beacon { background: radial-gradient(circle, rgb(225 255 240 / 0.95) 0 12%, rgb(150 240 210 / 0.6) 22%, transparent 55%); }
.hazard.feeler { background: linear-gradient(160deg, transparent 44%, rgb(220 214 200 / 0.85) 46% 54%, transparent 56%); }
.card.angler { background: #3c5a58; }
.hazard.bones .edge { stroke: var(--outline); stroke-width: 5; }
.hazard.bones .edge circle { fill: var(--outline); }
.hazard.bones .bone { stroke: #cfc7b4; stroke-width: 2.8; }
.hazard.bones .bone circle { fill: #cfc7b4; stroke-width: 0; }
/* Replays (src/replay.js): the bar while one plays, and the list to pick from. */
.replay-bar { align-items: center; flex-wrap: wrap; row-gap: 2px; }
/* Where the replay is, on a line of its own over the buttons. */
.poses-bar { margin-top: 4px; }
/* The silhouette check: the cutouts alone, so the board's marks and numbers go. */
.view.silhouette .board { visibility: hidden; }
.replay-at { order: -1; flex: 1 0 100%; text-align: center; font: 600 12px/1.2 var(--font-ui); color: var(--muted); }
body.replaying .end, body.replaying .stairs-card, body.replaying .controls { display: none !important; }
.replays-list { display: grid; gap: 8px; margin-top: 8px; }
.replay-row { display: flex; align-items: center; gap: 10px; justify-content: space-between; padding: 8px 0; border-top: 1px solid var(--edge); }
.replay-row > div { min-width: 0; overflow-wrap: anywhere; }

/* The dead's cards. */
.card.knight { background: var(--knight); border-color: var(--bright); scale: 1.35; transform-origin: 50% 100%; }
.mc-letter.knight { background: var(--knight); }
/* The Sleeping Knight's tomb: a carved stone slab on the floor. */
.hazard.tomb {
  background: linear-gradient(to bottom, #9a958b 0 3px, #77736b 3px calc(100% - 3px), #57544e calc(100% - 3px));
  box-shadow: inset 0 0 0 1px var(--seam), inset 0 0 0 5px #6b6861;
  border-radius: 3px;
  opacity: 0.9;
}
.card.ghoul { background: #5d6b4f; }
.card.cadaver { background: #6f6a60; }
/* The Fossor (floor 40's boss) and his graves: an open hole, dark earth round its lip. */
.card.fossor { background: #4a4036; border-color: var(--bright); scale: 1.35; transform-origin: 50% 100%; }
.hazard.grave { background: radial-gradient(ellipse 42% 46% at 50% 50%, #050403 62%, #3b2c1e 70%, rgb(59 44 30 / 0) 100%); }
/* The Skull-roller: 2 tiles square, its card twice the size (the 3D view takes the scale too). */
.actor.monster.big .paper { scale: 2; }
.card.roller { background: #8a8072; border-color: var(--bright); }
.card.sinker { background: #4c5f5a; }
.card.drowned { background: #3e5566; }
.card.floater { background: #6d7570; }
.card.snapper { background: #5d6b3f; }
.card.oldsnapper { background: #45512e; }
.card.eel { background: #8f9a98; }
.monster.eel .mark { display: none; } /* (never asleep or wary as others are) */
.card.wailer { background: #6d6286; }
/* The Mines' creatures. */
.card.miner { background: #7a6446; }
.card.centipede { background: #8a4a2e; }
.card.weaver { background: #5b5566; }
.card.stonegnaw { background: #4a4038; }
.card.spider { background: #2f2a33; scale: 1.35; transform-origin: 50% 100%; }
.card.sac { background: #d9d4c4; color: #2f2a33; }
.card.spiderling { background: #4b4452; }
/* The Great spider up in the dark: faint, out of reach. */
.actor.up { opacity: 0.45; }
/* A long creature's body segment: a smaller card; a plated one wears a shell. */
.card.seg { scale: 0.78; transform-origin: 50% 100%; }
.card.seg.plated { box-shadow: inset 0 0 0 3px #c9b38a, inset 0 -6px 0 3px rgb(0 0 0 / 0.25); }

/* A sleeping Cadaver looks like any other body. */
.monster .disguise { display: none; }
/* A sleeping Cadaver is drawn among the dead (ui/view.js lyingDead), its card hidden, unless your
   gear shows it. An Owl-feather cap catches it stirring. */
.monster.cadaver.asleep:not(.seen) { visibility: hidden; }
/* The drowned (the Drowned Halls): a sleeping Floater lies among the dead too, a body in the water;
   a sleeping Sinker isn't drawn at all, only a dark shape under the water close by (ui/view.js). */
.monster.floater.asleep:not(.seen), .monster.sinker.asleep:not(.seen) { visibility: hidden; }
.sunk-token { pointer-events: none; display: grid; place-items: center; }
/* A creature that looks like part of the floor (the Old snapper, a mossy rock) isn't drawn. */
.monster.disguised:not(.seen) { visibility: hidden; }
.t.floor.deep.rock { background: radial-gradient(circle at 50% 55%, #56604a 0 34%, #12222e 36%); }
.sunk-token .sunk { width: 70%; height: 42%; border-radius: 50%; background: radial-gradient(closest-side, rgb(8 14 18 / 0.7), rgb(8 14 18 / 0)); }
.body-token.dead { pointer-events: none; }
.body-token.stirring .corpse { animation: stir 2.6s ease-in-out infinite; }
@keyframes stir { 0%, 82%, 100% { translate: 0 0; } 88% { translate: 1px -1px; } 94% { translate: -1px 0; } }

/* The camp's Settings panel. */
.settings-row { width: 100%; margin-top: 8px; }

/* The first-time tip card (ui/tips.js): floats above the bottom bar and blocks nothing. */
.intro {
  position: fixed; z-index: 40; left: 50%; bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%); width: min(calc(100% - 32px), 420px);
  padding: 12px 14px 12px; border: 1px solid var(--torch); border-radius: 12px;
  background: var(--surface); color: var(--ink); box-shadow: 0 10px 30px rgb(0 0 0 / 0.5);
}
.intro[hidden] { display: none; }
.intro-row { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }

/* The opening (ui/intro.js): the story of the Long Night, a picture and a line at a time, over
   everything. The pictures are placeholders for now. */
.story {
  position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column; justify-content: center;
  gap: 18px; padding: 24px 16px calc(24px + env(safe-area-inset-bottom, 0px)); background: var(--void); color: var(--ink);
}
.story[hidden] { display: none; }
/* A player's page (main.js openProfile): their records, best scores and dares. */
.profile { display: grid; gap: 12px; }
.profile h3 { margin: 6px 0 0; }
.profile-light { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.profile-light div { display: grid; gap: 2px; padding: 12px 14px; border: 1px solid var(--torch); border-radius: 10px; background: var(--surface); }
.profile-light b { font: 600 26px/1.1 var(--font-glyph); color: var(--torch); font-variant-numeric: tabular-nums; }
.profile-light span { font-size: 13px; color: var(--muted); }
.profile-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.profile-stats div { display: grid; gap: 2px; padding: 10px; border: 1px solid var(--edge); border-radius: 10px; background: var(--surface); }
.profile-stats b { font: 600 20px/1.1 var(--font-glyph); color: var(--torch); font-variant-numeric: tabular-nums; }
.profile-stats span { font-size: 12px; color: var(--muted); }
#camp-board li[data-player] { cursor: pointer; }

/* Dares (src/dare.js): on the stairs, and on the end card. */
.stairs-dares { display: grid; gap: 10px; margin-top: 16px; }
.stairs-dares h3 { margin: 0; }
/* The Great Fire's panel (ui/camp.js showGreatFire): a bar with a notch at each perk. */
.gf-bar { position: relative; height: 10px; border-radius: 5px; background: var(--surface); overflow: hidden; }
.gf-bar i { position: absolute; inset: 0 auto 0 0; background: var(--torch); }
.gf-bar em { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--void); }
.gf-perks li { grid-template-columns: 1fr auto; grid-template-areas: "who light" "how light"; }
.gf-perks li::before { content: none; }
.gf-perks li.lit { box-shadow: inset 3px 0 0 var(--torch); }
.gf-perks li:not(.lit) b { color: var(--muted); }
/* A dare as a tile (main.js dareTile): two lines, the score, More; opened, the kit and the button. */
.dare-tiles { display: grid; gap: 4px; }
.dare-tile { border-radius: 8px; background: var(--surface); }
.dare-tile.act { box-shadow: inset 3px 0 0 var(--torch); }
.dare-tile summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "who light more" "how light more";
  column-gap: 10px;
  row-gap: 2px;
  align-items: center;
  padding: 10px 10px 10px 12px;
  list-style: none;
  cursor: pointer;
}
.dare-tile summary::-webkit-details-marker { display: none; }
.dare-tile .who { grid-area: who; font-weight: 700; font-size: 14px; }
.dare-tile .how { grid-area: how; color: var(--muted); font-size: 12px; }
.dare-tile b { grid-area: light; color: var(--bright); font: 600 16px var(--font-glyph); }
.dare-tile .more { grid-area: more; padding: 6px 10px; border: 1px solid var(--edge); border-radius: 6px; color: var(--ink); font-size: 12px; }
.dare-tile .more::after { content: ' ▾'; color: var(--muted); }
.dare-tile[open] .more::after { content: ' ▴'; }
.dare-more { display: grid; gap: 6px; padding: 2px 12px 12px; border-top: 1px solid var(--edge); padding-top: 10px; }
.dare-more p { margin: 0; font-size: 13px; }
.dare-more p span { display: inline-block; min-width: 72px; color: var(--muted); }
.dare-more .btn { margin-top: 4px; }
.end-dare { display: grid; gap: 6px; margin: 4px 0 10px; }
.end-dare[hidden] { display: none; }
.end-dare-to { display: flex; flex-wrap: wrap; gap: 8px; }
.end-dare-to:empty { display: none; }
.end-dare-to .btn { flex: 1 1 auto; }
.dare-link { width: 100%; min-height: 72px; padding: 10px 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--void); color: var(--ink); font: 14px/1.4 var(--font-ui); resize: none; }

/* The sign-in screen (ui/account.js), over everything before the game starts. */
.account { justify-content: flex-start; padding-top: max(48px, env(safe-area-inset-top, 0px)); overflow-y: auto; }
.account-title { margin: 0 auto; font: 600 28px/1.2 var(--font-glyph); color: var(--torch); text-align: center; letter-spacing: 0.04em; }
.account-form { width: min(100%, 420px); margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
.account-form[hidden], .account-field[hidden] { display: none; }
.account-form.inline { width: auto; margin: 8px 0; }
.account-form .story-text { margin-bottom: 4px; }
.account-field { display: flex; flex-direction: column; gap: 4px; font: 600 12px/1 var(--font-ui); color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
.account-field input { min-height: 48px; padding: 0 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--surface); color: var(--ink); font: 16px var(--font-ui); text-transform: none; letter-spacing: 0; }
.account-field input:focus { outline: 2px solid var(--torch); outline-offset: 1px; }
.account-error { min-height: 1.4em; color: var(--torch); }
.account-link { align-self: center; border: 0; background: none; color: var(--muted); font: 500 14px var(--font-ui); padding: 10px; cursor: pointer; text-decoration: underline; }
.story-skip { position: absolute; top: 12px; right: 12px; border: 0; background: none; color: var(--muted); font: 600 14px/1 var(--font-ui); padding: 10px; cursor: pointer; }
.story-art {
  width: min(100%, 420px); aspect-ratio: 4 / 3; margin-inline: auto; display: grid; place-items: center; padding: 16px;
  border: 1px dashed var(--edge); border-radius: 12px; text-align: center; font: italic 14px/1.4 var(--font-ui); color: var(--muted);
  background: radial-gradient(circle at 50% 70%, rgb(239 182 76 / 0.18), transparent 60%), var(--surface);
}
.story-text { width: min(100%, 420px); margin: 0 auto; font-size: 18px; line-height: 1.5; text-align: center; }
.story-row { width: min(100%, 420px); margin: 0 auto; display: flex; justify-content: space-between; align-items: center; }
.story-step { font: 600 12px/1 var(--font-ui); color: var(--muted); }

/* The camp grows (ui/grows.js): the opening's screen, a tier's welcome and who came with it. */
.grows { gap: 14px; overflow-y: auto; justify-content: safe center; }
.grows-head { margin: 0; text-align: center; font: 700 12px/1 var(--font-ui); letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); }
.grows-name { margin: 0; text-align: center; font-size: 26px; color: var(--torch); text-shadow: 0 0 18px rgb(239 182 76 / 0.45); }
.grows .story-art { aspect-ratio: 16 / 9; }
.grows-came { width: min(100%, 420px); margin: 0 auto; padding: 0; list-style: none; display: grid; gap: 8px; }
.grows-came:empty { display: none; }
.grows-came li { padding: 10px 12px; border: 1px solid var(--edge); border-radius: 10px; background: var(--surface); font-size: 14px; line-height: 1.4; }
.grows-came b { display: block; color: var(--torch); }
.grows-row { justify-content: center; }

/* A first-time tip (ui/tips.js): the introduction's card, smaller. */
.tip .tip-text { margin: 0; font-size: 14px; line-height: 1.45; }
.tip .intro-row { margin-top: 8px; }
/* The bag's tip, inside the Gear panel: in the flow, pushing the bag down. */
.intro.tip.inline { position: static; transform: none; width: auto; margin: 0 0 12px; box-shadow: none; }
/* A tip pointing at the torch: just under it, an arrow up to it, and the torch glows. And the Gear
   button glows while the loot tip asks you to open it. */
.intro.tip.pointing { bottom: auto; }
.intro.tip.pointing::before {
  content: ''; position: absolute; top: -9px; left: calc(var(--arrow, 50%) - 9px); width: 16px; height: 16px;
  background: var(--surface); border-left: 1px solid var(--torch); border-top: 1px solid var(--torch); transform: rotate(45deg);
}
#torch.pointed, #gear-button.beckon { animation: beckon 1.1s ease-in-out infinite; }
@keyframes beckon {
  0%, 100% { box-shadow: 0 0 0 0 rgb(239 182 76 / 0); }
  50% { box-shadow: 0 0 0 4px rgb(239 182 76 / 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  #torch.pointed, #gear-button.beckon { animation: none; box-shadow: 0 0 0 3px rgb(239 182 76 / 0.55); }
}

/* Test, a small button under Aa (Kevin, Oct 15, 2026: the Map took its place on the bar). */
.test-btn { top: 92px; }

/* The map (ui/map.js): the whole screen (Kevin, Oct 15, 2026), its own turn and zoom buttons at
   the foot, drag to look around. It turns with the view, so up is up on the screen. */
.map-modal {
  position: fixed; z-index: 55; inset: 0; display: flex; flex-direction: column; gap: 8px;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 16px calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--void);
}
.map-modal[hidden] { display: none; }
.map-head { display: flex; justify-content: space-between; align-items: center; font: 600 15px/1 var(--font-ui); color: var(--ink); }
.map-art { flex: 1; min-height: 0; overflow: hidden; touch-action: none; cursor: grab; border: 1px solid var(--edge); border-radius: 12px; }
.map-pan { width: 100%; height: 100%; display: grid; place-items: center; transform-origin: 50% 50%; }
.map-pan svg { width: 100%; height: 100%; transition: transform 360ms ease; }
.map-art .floor { fill: #6d717a; }
.map-art .wall { fill: #2b2e34; }
.map-art .shallow { fill: #4f8592; }
.map-art .deep { fill: #1c3442; }
.map-art .deep.pit { fill: #050403; }
.map-art .stairs { fill: var(--bright); }
.map-art .you { fill: var(--torch); stroke: var(--void); stroke-width: 0.06; }
/* Embers seen glowing in the dark (or shown by an Ash tongue): a warm dot, bigger the brighter. */
.map-art .glint { fill: var(--torch); stroke: var(--void); stroke-width: 0.05; }
.map-art .glint.bright, .map-art .glint.blazing { fill: #ffe7a8; }
.map-art .glint.radiant { fill: #fff; }
/* The cold camp on the map: a flame in a ring of stones, grey once the coals are out. */
.map-art .camp-at { transition: transform 360ms ease; cursor: pointer; }
.map-art .camp-tap { fill: transparent; }
.map-art .camp-ring { fill: var(--void); stroke: #a39e94; stroke-width: 0.14; }
.map-art .camp-flame { fill: #ff8a3a; }
.map-art .camp-at.out .camp-flame { fill: #6d717a; }
.map-note { margin: 0; font-size: 12px; text-align: center; }
.map-tools { display: flex; justify-content: space-between; }
.map-tools .turn-btn { position: static; }
.map-art .you-at { transition: transform 360ms ease; }

/* A run's end, told at camp (Kevin, Oct 15, 2026): its card over the camp, Done alone. */
.camp > .end.at-camp { z-index: 35; }
.end.at-camp .row { grid-template-columns: 1fr; }

/* ─── The 3D view (src/ui/scene3d.js), in testing ───
   Three.js draws the floor, walls, cutouts and light into a canvas under the board. The board
   stays on top for taps, red tiles, hazards, marks and floating words; what the canvas draws
   instead is hidden here, but still takes taps. */
.view canvas.scene3d { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.view.three .flat, .view.three .face, .view.three .glow, .view.three .dangers, .view.three .hazards { visibility: hidden; }
/* The cards stay where they are, blank (they still take taps, and their animations still play, for
   the 3D view to copy); only the health pips show, over the picture. */
.view.three .actor > .shadow, .view.three .corpse svg, .view.three .monster .disguise { visibility: hidden; }
.view.three .paper { background: none !important; border-color: transparent !important; box-shadow: none !important; }
.view.three .paper > :not(.pips):not(.camp-badge), .view.three .card::after { visibility: hidden; }
/* A creature's health shows as tears in its card instead (Kevin, Oct 29, 2026). */
.view.three .monster .pips { visibility: hidden; }

/* The bedroll's You view: unlocks and relics. */
.camp-home .you-label { width: auto; margin: 6px 0 -4px; }
.you-list { margin: 0; padding-left: 20px; display: grid; gap: 4px; }
.you-relic { margin: 0; }

/* The bedroll: its parts keep their height (a long list ran over the hint below it), and Storage
   and Equipped at the bottom light up as places to drop a dragged thing. */
#camp-pack > * { flex-shrink: 0; }
/* A fixed height for its tiles: phones worked out square tiles' height before their width and laid
   the grid out too short. And a dragged card goes over the camp's screens, not under them. */
.camp-home .slots .slot, .camp-home .worn .slot { aspect-ratio: auto; height: 78px; }
body > .slot.ghost { z-index: 40; }
.panel-nav .btn.over { box-shadow: 0 0 0 3px var(--torch); }

/* A place to drop, full width between worn and the bag (Kevin, Oct 16, 2026): To storage in the
   bedroll; in the dungeon, what lies on the ground here, and where you drop things. Its dashes march
   while something is dragged. */
.drop-band {
  --ant: var(--muted);
  display: grid;
  gap: 6px;
  padding: 10px 12px;
  border-radius: 6px;
  background-image: linear-gradient(90deg, var(--ant) 50%, transparent 0), linear-gradient(90deg, var(--ant) 50%, transparent 0),
    linear-gradient(0deg, var(--ant) 50%, transparent 0), linear-gradient(0deg, var(--ant) 50%, transparent 0);
  background-size: 10px 2px, 10px 2px, 2px 10px, 2px 10px;
  background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
  background-position: 0 0, 0 100%, 0 0, 100% 0;
}
.drop-band[hidden] { display: none; }
.drop-band .band-label { margin: 0; font: 600 11px var(--font-ui); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.drop-band .keys { margin: 0; }
.drop-band.over { box-shadow: 0 0 0 3px var(--torch); }
.dragging-now .drop-band { --ant: var(--torch); animation: ants 0.5s linear infinite; }
.dragging-now .drop-band .band-label { color: var(--torch); }
@keyframes ants { to { background-position: 10px 0, -10px 100%, 0 -10px, 100% 10px; } }
@media (prefers-reduced-motion: reduce) { .dragging-now .drop-band { animation: none; } }

/* Storage's sort and kinds: a row of chips each, the one chosen lit. */
.store-tools { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.store-tools .chip { min-height: 36px; padding: 0 10px; font-size: 13px; }
.store-tools .chip[aria-pressed="true"] { background: var(--torch); border-color: var(--torch); color: var(--void); }

/* Storage's places to drop, frozen at the bottom over the buttons: Equip, To bag. */
#camp-pack .panel-nav { flex-wrap: wrap; }
.pack-drops { flex: 1 0 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pack-drops[hidden] { display: none; }
.pack-drops .drop-band { min-height: 56px; place-items: center; }

/* In 3D the camp's places are models: their icon cards go (Kevin, Oct 16, 2026); names stay. */
.view.three .prop-card svg { display: none; }


.camp-tier { margin: -4px 0 6px; font: 600 15px var(--font-ui); color: var(--ink); }

/* Test settings, opened from the camp's Settings: inside it, not over the dungeon's view. */
/* It scrolls with Settings: on its own it would hold on to the swipe (overscroll-behavior: contain)
   and Settings never scrolled (Kevin, Oct 16, 2026). */
.panel.in-camp { position: static; max-height: none; box-shadow: none; overflow: visible; overscroll-behavior: auto; }

/* Other delvers about the camp (ui/campmap.js): their names over them; taps pass through. */
.actor.visitor { pointer-events: none; }
.visitor-name { position: absolute; left: 50%; bottom: calc(50% + var(--tile) * 0.8); translate: -50% 0; font: 600 10px var(--font-ui); color: var(--ink); opacity: 0.8; white-space: nowrap; text-shadow: 0 1px 3px #000; }
/* Your hair style is set on the page; a visitor's own short crop shows whatever yours is. */
.actor.visitor:not(.hair-curly):not(.hair-messy) .hero .crop { display: inline; }

/* Someone gone quiet (AFK), or resting: a grey name. */
.actor.visitor.afk .visitor-name { color: var(--muted); opacity: 0.7; }

/* Under a delver's name, how their latest run ended. */
.visitor-name small { display: block; font: 500 8px var(--font-ui); color: var(--muted); text-align: center; }
.visitor-name { text-align: center; }

/* What you tapped, as a card beside it with an arrow to it (ui/itemtip.js), in the dungeon's Gear
   panel and the camp's Stash alike (Kevin, Oct 16, 2026). */
.camp-home { position: relative; }
.item-tip {
  position: absolute;
  z-index: 5;
  display: grid;
  gap: 8px;
  justify-items: start;
  padding: 12px;
  border: 1px solid var(--torch);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
  box-shadow: 0 10px 28px var(--scrim);
}
.item-tip p { margin: 0; }
.item-tip .tip-where { color: var(--muted); }
.item-tip .tip-type { margin-right: 2px; padding: 0 6px; border: 1px solid var(--edge); border-radius: 999px; color: var(--muted); font-size: 0.85em; white-space: nowrap; }
.item-tip::before {
  content: '';
  position: absolute;
  left: calc(var(--arrow, 50%) - 7px);
  top: -8px;
  border: 7px solid transparent;
  border-top: 0;
  border-bottom: 8px solid var(--torch);
}
.item-tip.above::before { top: auto; bottom: -8px; border-bottom: 0; border-top: 8px solid var(--torch); }

/* Tapping the torch: feed it an ember, or drain its light (main.js). Just under the meter. */
.torch-menu {
  position: absolute;
  top: 50px;
  left: 50%;
  translate: -50% 0;
  z-index: 5;
  display: flex;
  gap: 8px;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 10px;
  box-shadow: 0 10px 30px var(--scrim);
}
.torch-menu[hidden] { display: none; }
.torch-menu .btn { white-space: nowrap; }
