/* The same bones as The House Die: a bezel, a phosphor screen, typewriter labels.
   Goggles down swaps the palette for the rose one. */

/* Ebonhand: the host's own handwriting, for anything he would have written himself. */
@font-face {
  font-family: "Ebonhand";
  src: url("fonts/Ebonhand-Regular.otf") format("opentype");
  font-display: swap;
}

:root {
  --hand: "Ebonhand", "Special Elite", cursive;
  --ground: #121512;
  --text: #cfd6c4;
  --muted: #8e9587;
  --bezel: #2b2f29;
  --bezel-edge: #3d4239;
  --screen: #0b130f;
  --glow: #b7d3a8;
  --glow-dim: #5f7a5c;
  --wound: #d65f43;
  --tape: #d9cfb4;
  --ink: #1d1a16;
  --scan: rgba(183, 211, 168, 0.06);
  --mark: rgba(230, 240, 225, 0.55);
  /* Neck ink always sits on a dark ground, so one set of inks reads on both palettes. */
  --ink-ground: #0b130f;
  --ink-paper: #cfd6c4;
  --display: "Special Elite", "Courier New", monospace;
  --body: "Courier Prime", "Courier New", monospace;
  --readout: "VT323", "Courier New", monospace;
  color-scheme: dark;
}
/* Goggles on. Her four: #1D0008 wine-black, #693446 plum, #BB778C dusty rose, #FFEFF6 blush.
   The one extra, --muted, is a tint between her two lightest so small text reads on plum. */
:root[data-goggles="down"] {
  --ground: #1d0008;
  --text: #ffeff6;
  --muted: #dcb1c0;
  --bezel: #693446;
  --bezel-edge: #bb778c;
  --screen: #1d0008;
  --glow: #ffeff6;
  --glow-dim: #bb778c;
  --wound: #bb778c;
  --tape: #ffeff6;
  --ink: #693446;
  --scan: rgba(255, 239, 246, 0.05);
  --mark: rgba(255, 239, 246, 0.4);
  --ink-ground: #1d0008;
  --ink-paper: #ffeff6;
  --display: "Gaegu", "Comic Sans MS", cursive;
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.5;
  padding-inline: 16px;
  padding-block: 24px 48px;
}
.wrap {
  max-width: 560px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.wrap.desk { max-width: 1700px; }

.top { display: flex; flex-direction: column; gap: 2px; text-align: center; }
.eyebrow {
  margin: 0;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: 2rem;
  line-height: 1.15;
  text-wrap: balance;
}
h2, h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.25rem;
}
h3 { font-size: 1rem; color: var(--muted); margin-top: 6px; }
.house-number { font-size: clamp(5rem, 30vw, 9rem); line-height: 1; }
.who-line { margin: 0; min-height: 1.5em; color: var(--muted); }

.signal {
  position: sticky;
  top: 8px;
  z-index: 5;
  max-width: 560px;
  margin: 0 auto 12px;
  padding: 6px 12px;
  border-radius: 6px;
  background: var(--wound);
  color: var(--screen);
  text-align: center;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- cards and forms ---------- */

.card {
  background: var(--bezel);
  border: 2px solid var(--bezel-edge);
  border-radius: 14px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.card-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.plate label { font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.row, .inline { display: flex; flex-wrap: wrap; gap: 10px; }
.inline input { flex: 1 1 160px; }
.status { margin: 0; min-height: 1.5em; color: var(--text); }
.hint, .waiting { margin: 0; color: var(--muted); }
.waiting { text-align: center; font-family: var(--display); font-size: 1.15rem; }

input[type="text"], input[type="password"] {
  min-width: 0;
  width: 100%;
  border: 2px solid var(--bezel-edge);
  border-radius: 8px;
  background: var(--screen);
  color: var(--glow);
  font-family: var(--readout);
  font-size: 1.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 10px;
}
button {
  font-family: var(--display);
  font-size: 1rem;
  border-radius: 8px;
  cursor: pointer;
  padding: 8px 14px;
}
button:disabled { opacity: 0.5; cursor: not-allowed; }
.primary { border: 0; background: var(--wound); color: var(--screen); letter-spacing: 0.06em; }
.quiet, .goggles { border: 2px solid var(--bezel-edge); background: var(--ground); color: var(--text); }
.danger { border-color: var(--wound); color: var(--wound); }
.lock[data-open="true"], .room-pick[data-here="true"] { border-color: var(--glow); color: var(--glow); }
button:focus-visible, input:focus-visible, audio:focus-visible {
  outline: 2px solid var(--glow);
  outline-offset: 2px;
}

/* ---------- the monitor ---------- */

.monitor {
  background: var(--bezel);
  border: 2px solid var(--bezel-edge);
  border-radius: 22px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.screen {
  position: relative;
  background: var(--screen);
  color: var(--glow);
  border-radius: 12px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow: hidden;
}
.screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, var(--scan) 0 1px, rgba(0, 0, 0, 0) 1px 4px);
}
.feed {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 12px;
  font-family: var(--readout);
  font-size: 1.15rem;
  line-height: 1;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.rec { color: var(--wound); }
.scope { position: relative; height: clamp(150px, 42vw, 210px); }
.scope canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.ghost {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-size: clamp(7rem, 38vw, 11rem);
  line-height: 1;
  color: var(--glow);
  opacity: 0;
  filter: blur(1.5px);
  user-select: none;
}
.mark { position: absolute; display: none; pointer-events: none; user-select: none; }
/* The glass breaks from the top left corner and runs across the whole screen. */
.crack { inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: left top; }
.print { right: 6%; bottom: 3%; width: 40%; opacity: 0.7; transform: rotate(12deg); filter: drop-shadow(0 0 8px rgba(176, 208, 255, 0.35)); }
:root[data-goggles="up"] .screen[data-cracked="true"] .crack { display: block; }
:root[data-goggles="down"] .screen[data-cracked="true"] .print { display: block; }

/* ---------- the board ---------- */

.cassette {
  align-self: flex-start;
  border: 0;
  border-radius: 3px;
  background: var(--tape);
  color: var(--ink);
  font-family: var(--hand);
  font-size: 1.9rem;
  line-height: 1.1;
  padding: 8px 22px 6px;
  transform: rotate(-1.5deg);
}
audio { width: 100%; }

.necks { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.necks li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  background: var(--ink-ground);
  color: var(--ink-paper);
  border-radius: 8px;
  padding: 6px 10px;
}
.neck-name { min-width: 0; overflow-wrap: anywhere; }
.neck-ink { display: flex; flex-direction: column; align-items: flex-end; line-height: 1; }
.neck-num { font-family: var(--readout); font-size: 2.2rem; }
.neck-color { font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-paper); opacity: 0.7; }

/* The inks. Neighbors get their own lightness as well as their own hue: lime is acid bright
   beside a deeper green, cyan is pale aqua beside a true blue, indigo is deep, violet is
   pale lavender, purple is hot plum. */
[data-ink="red"] { color: #f0483f; }
[data-ink="orange"] { color: #ff9426; }
[data-ink="yellow"] { color: #f7e03c; }
[data-ink="lime"] { color: #c3f02e; }
[data-ink="green"] { color: #2fae5a; }
[data-ink="cyan"] { color: #3fe6e0; }
[data-ink="blue"] { color: #3d8dff; }
[data-ink="indigo"] { color: #5a4ee8; }
[data-ink="violet"] { color: #b9a4ff; }
[data-ink="purple"] { color: #cf3fe0; }

#safe-form { display: flex; flex-direction: column; gap: 10px; }
.dials { display: flex; flex-wrap: wrap; gap: 8px; }
.dials input { width: 3.2ch; flex: 1 1 3.2ch; max-width: 4.5ch; padding-inline: 4px; text-align: center; box-sizing: content-box; }

/* The lock on the door: a barrel of rings. The shading is laid over the palette's own
   colors, so it reads as one object with the goggles on or off. */
#word-form { display: flex; flex-direction: column; gap: 10px; }
.cryptex {
  display: flex;
  justify-content: center;
  gap: 2px;
  padding: 2px 18px;
  border: 2px solid var(--bezel-edge);
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.65), rgba(255, 255, 255, 0.1) 50%, rgba(0, 0, 0, 0.65)), var(--bezel-edge);
}
.cryptex[data-shut="true"] { opacity: 0.55; }
.ring { flex: 0 1 46px; min-width: 24px; display: flex; flex-direction: column; align-items: stretch; }
.ring-turn { border: 0; border-radius: 0; background: transparent; color: var(--text); padding: 3px 0; font-size: 0.7rem; line-height: 1; }
.ring-window {
  height: 92px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-inline: 1px solid rgba(0, 0, 0, 0.5);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0) 36%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0.8)), var(--tape);
  color: var(--ink);
  font-family: var(--display);
  cursor: ns-resize;
  touch-action: none;
  user-select: none;
}
.ring-face { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.ring-now { font-size: 1.9rem; line-height: 1; min-height: 1em; }
.ring-near { font-size: 1rem; line-height: 1; min-height: 1em; opacity: 0.5; transform: scaleY(0.7); }
.ring-window:focus-visible { outline: 2px solid var(--glow); outline-offset: -2px; }

.die-card { align-items: center; text-align: center; }
.die-who { margin: 0; }
.die { position: relative; width: min(100%, 220px); aspect-ratio: 1; display: grid; place-items: center; }
.die svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.die svg polygon, .die svg line { stroke: var(--glow-dim); stroke-width: 1.5; }
.num {
  position: relative;
  font-family: var(--readout);
  font-size: clamp(4.5rem, 26vw, 7rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--glow);
  padding-top: 0.08em;
}
.num.idle { font-size: clamp(2.5rem, 13vw, 3.5rem); color: var(--muted); }
.num.cruel { color: var(--wound); }
.die.rolling svg { animation: tumble 0.9s cubic-bezier(0.3, 0.7, 0.3, 1); }
@keyframes tumble {
  0% { transform: rotate(0deg) scale(1); }
  40% { transform: rotate(200deg) scale(0.9); }
  100% { transform: rotate(360deg) scale(1); }
}
.verdict {
  margin: 0;
  max-width: 26ch;
  min-height: 2.5em;
  font-family: var(--display);
  font-size: 1.35rem;
  line-height: 1.25;
  text-wrap: balance;
}
.verdict.cruel { color: var(--wound); }
.roll {
  border: 0;
  background: var(--wound);
  color: var(--screen);
  font-size: 1.5rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 12px 34px;
}

/* ---------- the control room ---------- */

/* Built for a wide screen: separate panels that sit side by side, each of which folds away. */
.modules { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); align-items: start; }
.module { display: block; padding: 0; }
.module > summary {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding: 12px 14px;
  cursor: pointer;
}
.module > summary::-webkit-details-marker { display: none; }
.module > summary::after { content: "\25BE"; margin-left: auto; color: var(--muted); transition: transform 0.15s; }
.module:not([open]) > summary::after { transform: rotate(-90deg); }
.module > summary:focus-visible { outline: 2px solid var(--glow); outline-offset: -2px; border-radius: 12px; }
.module-body { display: flex; flex-direction: column; gap: 12px; padding: 0 14px 14px; }

@media (min-width: 1000px) {
  .modules {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas: "rooms rooms" "guests room" "guests locks" "log log";
  }
  .m-rooms { grid-area: rooms; }
  .m-kitchen, .m-library, .m-sunroom, .m-basement { grid-area: room; } /* the room's panel follows the house, in the Den's spot */
  .m-guests { grid-area: guests; }
  .m-room { grid-area: room; }
  .m-locks { grid-area: locks; }
  .m-log { grid-area: log; }
}
@media (min-width: 1500px) {
  .modules {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.9fr) minmax(0, 0.8fr);
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "rooms rooms rooms" "guests room log" "guests locks log";
  }
}

/* Arranged by hand: once we drag anything, the panels become free widgets on a canvas. */
@media (max-width: 999px) { .wide-only { display: none; } }
.modules.widgets { display: block; position: relative; }
.modules.widgets .module { position: absolute; overflow: hidden; }
.modules.widgets .module-body { overflow: auto; }
.grip { display: none; }
.modules.arranging .module { outline: 2px dashed var(--glow-dim); outline-offset: 2px; }
.modules.arranging .module > summary { cursor: move; touch-action: none; user-select: none; }
.modules.arranging .grip {
  display: block;
  position: absolute;
  right: 0;
  bottom: 0;
  width: 26px;
  height: 26px;
  cursor: nwse-resize;
  touch-action: none;
  background: linear-gradient(135deg, transparent 50%, var(--glow) 50%);
}

/* The guests: one row each, with their own die on the end and the roll's line beneath.
   The rows fold onto more lines when their own panel is narrow, whatever the window is. */
.seats { display: flex; flex-direction: column; gap: 6px; container-type: inline-size; }
.seat {
  display: grid;
  grid-template-columns: 2ch auto minmax(100px, 1.2fr) minmax(100px, 1.2fr) minmax(140px, 1fr) auto auto auto minmax(0, auto) auto auto;
  grid-template-areas:
    "no seated name companion code ink letter wake flags keys die"
    "said said said said said said said said said said said";
  align-items: center;
  gap: 4px 10px;
  background: var(--screen);
  border: 2px solid transparent;
  border-radius: 8px;
  padding: 6px 10px;
}
.seat[data-seated="false"] { opacity: 0.6; }
.seat[data-die="holding"] { border-color: var(--wound); }
.seat-no { grid-area: no; font-family: var(--readout); font-size: 1.4rem; color: var(--muted); }
.check { grid-area: seated; display: flex; align-items: center; gap: 6px; font-size: 0.85rem; white-space: nowrap; }
.seat input[type="text"] { grid-area: name; font-family: var(--body); font-size: 1rem; letter-spacing: 0; text-transform: none; padding: 4px 8px; }
.seat input.seat-companion { grid-area: companion; }
.seat-code { grid-area: code; font-family: var(--readout); font-size: 1.15rem; color: var(--muted); overflow-wrap: anywhere; }
.chip {
  min-width: 2.6ch;
  font-family: var(--readout);
  font-size: 1.5rem;
  line-height: 1;
  text-align: center;
}
.seat .neck-ink { grid-area: ink; align-items: center; min-width: 52px; }
.seat-letter { grid-area: letter; }
.seat-wake { grid-area: wake; justify-self: start; }
.seat-flags { grid-area: flags; font-size: 0.8rem; color: var(--muted); }
.seat button { padding: 4px 10px; font-size: 0.9rem; }
.die.tiny { grid-area: die; width: 46px; }
.die.tiny .num { font-size: 1.6rem; }
.die.tiny .num.idle { font-size: 0.8rem; }
.seat-said {
  grid-area: said;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 12px;
  font-size: 0.9rem;
  text-align: right;
}
@container (max-width: 760px) {
  .seat {
    grid-template-columns: 52px auto 1fr auto;
    grid-template-areas:
      "no seated name code"
      "no seated companion code"
      "ink letter wake die"
      "flags flags keys keys"
      "said said said said";
  }
  .seat-flags:empty { display: none; }
}

.facts { margin: 0; display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; font-family: var(--readout); font-size: 1.3rem; line-height: 1.2; overflow-wrap: anywhere; }
/* Each number stays with its own color, however narrow the panel is. */
.facts dd span { display: inline-block; white-space: nowrap; margin-right: 1.2ch; }

.logs { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px 24px; }
.log { margin: 0; padding-left: 2.4ch; color: var(--text); }
.log:empty::before { content: "Nothing yet."; color: var(--muted); margin-left: -2.4ch; }
.log .faces { display: block; color: var(--muted); }

/* ---------- the Kitchen ---------- */

.replica { position: relative; border-radius: 10px; overflow: hidden; background: #070504; min-height: 180px; }
.replica canvas { display: block; touch-action: manipulation; }
.seam-picks-box summary { cursor: pointer; color: var(--muted); font-size: 0.85rem; }
.seam-picks { margin-top: 8px; }
.seam-picks button { padding: 4px 10px; font-size: 0.85rem; }
.feed-alarm { color: var(--wound); }

/* The chart of the rig beside the key rack. */
.marks-card { flex-direction: row; align-items: center; justify-content: space-between; gap: 14px; }
/* Her art fills it: the specimen sheet, or Pip's doll with the goggles on. */
.rig-chart { width: clamp(120px, 42%, 220px); height: auto; aspect-ratio: 3 / 4; flex: none; border-radius: 6px; }
:root[data-goggles="down"] .rig-chart .chart-art.up, :root:not([data-goggles="down"]) .rig-chart .chart-art.down { display: none; }
.rig-chart .nametag { font-family: var(--hand); fill: #2b1d12; opacity: 0.88; }
.rig-chart .pick { fill: #8e1414; stroke: #2a1212; stroke-width: 0.8; }
.rig-chart .handle { stroke: #6f6f6f; stroke-width: 1.6; stroke-linecap: round; }
.rig-chart .bug { fill: #2a2016; stroke: #5c4a32; stroke-width: 0.5; }
.rack { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
.hook { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 2px; min-width: 50px; font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.key-icon { display: block; }
.key-icon path { fill: none; stroke: var(--bezel-edge); stroke-width: 2.6; stroke-linecap: round; }
.hook .key-icon { width: 34px; height: 34px; }
.hook .key-picture { display: block; height: 44px; width: auto; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.7)); }
.hook[data-held="true"] { color: var(--text); }
.hook[data-held="true"] .key-icon path, .key-toggle[data-held="true"] .key-icon path { stroke: #c99a45; }

/* The symbols, drawn small in the control room. */
.glyph { display: inline-block; vertical-align: -3px; }
.glyph path, .glyph circle { fill: none; stroke: currentColor; stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; }
.glyph .dot { fill: currentColor; stroke: none; }

/* The Kitchen panel: one line per replica. */
.pairs { display: flex; flex-direction: column; gap: 6px; }
.pair { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; background: var(--screen); border: 2px solid transparent; border-radius: 8px; padding: 6px 10px; }
.pair[data-waiting="true"] { border-color: var(--wound); }
.pair-name { min-width: 7ch; font-family: var(--display); }
.pair-packet, .pair-picks, .pair-key { font-size: 0.85rem; color: var(--muted); }
.pair-key[data-found="true"] { color: #c99a45; }
.pair-seams { display: flex; gap: 6px; }
.cell { display: flex; flex-direction: column; align-items: center; min-width: 34px; padding: 2px 4px; border: 1px solid var(--bezel-edge); border-radius: 6px; font-family: var(--readout); font-size: 0.95rem; color: var(--muted); }
.cell[data-open="true"] { color: var(--wound); border-color: var(--wound); }
.cell[data-key="true"] { color: #c99a45; border-color: #c99a45; }
.pair button { padding: 3px 9px; font-size: 0.85rem; }
.pair-sound[data-open="false"] { border-color: var(--wound); color: var(--wound); }

/* Each guest's keys, in their row. */
.seat-keys { grid-area: keys; display: flex; gap: 1px; }
.seat .key-toggle { padding: 2px; border: 0; background: transparent; }
.key-toggle .key-icon { width: 18px; height: 18px; }

/* The dark falls in from the edges of the table. */
.replica::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(ellipse 70% 62% at 50% 54%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.82) 100%); }

/* ---------- the Tools menu ---------- */

#control { position: relative; }
.tools-menu { position: absolute; top: 0; right: 0; z-index: 30; }
.tools-menu > summary { list-style: none; cursor: pointer; padding: 8px 14px; border-radius: 8px; font-family: var(--display); }
.tools-menu > summary::-webkit-details-marker { display: none; }
.tools-menu > summary::after { content: " \25BE"; color: var(--muted); }
.tools-menu[open] > summary { border-color: var(--glow); color: var(--glow); }
.tools-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 240px;
  padding: 10px;
  background: var(--bezel);
  border: 2px solid var(--bezel-edge);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
}
.tools-list button { text-align: left; }
.arranging-bar {
  position: sticky;
  top: 8px;
  z-index: 25;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 14px;
  padding: 8px 12px;
  background: var(--bezel);
  border: 2px solid var(--glow);
  border-radius: 10px;
}

/* ---------- the Library ---------- */

/* Her bookcase, with her twenty books standing in its bare runs. */
.shelf { position: relative; aspect-ratio: 1; border-radius: 10px; overflow: hidden; background: #120d0a; }
.shelf-picture { position: absolute; inset: 0; display: block; width: 100%; height: 100%; user-select: none; }
.books { position: absolute; inset: 0; }
.book {
  position: absolute;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: none;
  cursor: pointer;
  transform-origin: 50% 100%;
  transition: transform 0.22s ease, opacity 0.3s ease;
}
/* Her spines were lit evenly; on the shelf they sit in the same lamplight as everything else. */
.book img { display: block; width: 100%; height: 100%; pointer-events: none; filter: brightness(0.82) saturate(0.92) drop-shadow(-2px 1px 2px rgba(0, 0, 0, 0.75)); }
.book:not(:disabled):hover, .book:not(:disabled):focus-visible { transform: translateY(-4%); }
.book:focus-visible { outline: 2px solid var(--glow); outline-offset: 1px; }
.book:disabled { cursor: default; }
.book[data-out="true"] { opacity: 0; }
.shelf::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(ellipse 85% 85% at 50% 45%, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.45) 100%); }

/* The book in their hands: it turns to show its cover, then falls open. */
.taken { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4%; background: rgba(8, 5, 3, 0.74); backdrop-filter: blur(2px); perspective: 1400px; }
.taken[hidden] { display: none; }
.tome { position: relative; width: 52%; aspect-ratio: 488 / 720; transform-style: preserve-3d; }
.tome-cover { position: absolute; inset: 0; display: block; width: 100%; height: 100%; border-radius: 3px; transform-origin: 0 50%; backface-visibility: hidden; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.7); transition: transform 0.9s cubic-bezier(0.3, 0.7, 0.2, 1); }
.tome[data-open="true"] .tome-cover { transform: rotateY(-168deg); }
.tome-inside { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 3px; background: linear-gradient(90deg, #b9a47c, #e9dcbf 6%, #efe4ca 90%, #cdb991); box-shadow: inset 0 0 18px rgba(80, 50, 20, 0.45); }
/* Plain pages: lines of print too faint to read. */
.tome-inside.plain { background: repeating-linear-gradient(180deg, transparent 0 9px, rgba(60, 40, 20, 0.14) 9px 10px) 12% 10% / 76% 80% no-repeat, linear-gradient(90deg, #b9a47c, #e9dcbf 6%, #efe4ca 90%, #cdb991); }
/* The hollow. Her picture goes here once she makes it; until then, a dark cavity in the pages. */
/* The hollow: her pictures. With the goggles on the key sits in the nest she left in the marshmallows. */
.tome-inside.hollow { background: url(library/hollow.jpg) center / cover; }
.tome-inside.hollow.pip { background-image: url(library/hollow-pip.jpg); }
.tome-inside.hollow.pip .hollow-key { transform: translate(9%, -3%) rotate(-12deg); }
.hollow-key { position: relative; width: 40%; transform: rotate(-12deg); filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.7)); }
.taken-actions { justify-content: center; }

/* Her Ask Again machine, laid out in her own picture's pixels (a 1254 square): the window in
   the box, and the handle hung so its pivot sits on the boss at the side. */
.lever-row { display: flex; align-items: center; gap: 18px; }
.lever { position: relative; flex: none; width: min(200px, 46vw); aspect-ratio: 1; padding: 0; border: 0; background: none; cursor: pointer; }
.lever:disabled { cursor: default; }
.lever:focus-visible { outline: 2px solid var(--glow); outline-offset: 4px; border-radius: 8px; }
.lever > img { position: absolute; display: block; user-select: none; pointer-events: none; }
.lever-box { inset: 0; width: 100%; height: 100%; }
.lever-window { position: absolute; left: 38.2%; top: 48.09%; width: 19.94%; height: 29.11%; overflow: hidden; background: #0b0806; }
.lever-window::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 9px 9px -4px rgba(0, 0, 0, 0.85), inset 0 -9px 9px -4px rgba(0, 0, 0, 0.85); pointer-events: none; }
/* Her seven tiles, 6 down to 0, twice over, so the drum can spin past and land. */
.lever-drum { position: absolute; top: 0; left: 10.2%; width: 79.6%; height: 1400%; background: url(library/lever-drum.jpg) top / 100% 100% no-repeat; }
.lever-handle { left: 17.19%; top: -2.17%; width: 90%; height: 90%; transform-origin: 84.13% 80.38%; }
.lever-cap { left: 86.92%; top: 64.19%; width: 11.96%; height: 11.96%; }
.lever[data-snapped="true"] .lever-handle { transform: scaleY(-0.55) rotate(-14deg); filter: brightness(0.75); }
.lever[data-locked="true"] > img, .lever[data-locked="true"] .lever-window { filter: brightness(0.7); }
.pulls { margin: 0; color: var(--muted); font-size: 0.95rem; }
/* Pip's machine, with the goggles on: his painted box with the crow on top, laid out in her picture's pixels too. */
html[data-goggles="down"] .lever-window { left: 39.23%; top: 64.27%; width: 20.89%; height: 18.02%; background: #2a1a10; }
html[data-goggles="down"] .lever-drum { left: 0; width: 100%; background-image: url(library/lever-drum-pip.jpg); }
html[data-goggles="down"] .lever-handle { left: 0; top: 0; width: 100%; height: 100%; transform-origin: 85.49% 76.16%; }
html[data-goggles="down"] .lever-cap { left: 81.66%; top: 72.33%; width: 7.66%; height: 7.66%; }

/* What the Library leaves at the throat, on the chart of the rig. */
.rig-chart .wire { fill: none; stroke: #8e1414; stroke-linecap: round; }
.rig-chart .cut { stroke: #c01818; stroke-width: 1.2; stroke-linecap: round; }
.rig-chart .mallow { fill: #fff6ea; stroke: #b9a58a; stroke-width: 0.5; }

/* Her machine is art, never greyed out while it waits; the drum and the line already say why. */
.lever:disabled, .book:disabled, .rig-lock:disabled { opacity: 1; }

/* The magnifying glass over the shelf: the spines, larger, inside her ring. */
.loupe { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none; }
.loupe[hidden] { display: none; }
.loupe-lens { position: absolute; border-radius: 50%; overflow: hidden; background: #120d0a; }
.loupe-lens::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 42%), radial-gradient(circle, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0.35) 100%); }
.loupe-stage { position: absolute; top: 0; left: 0; transform-origin: 0 0; }
.loupe-stage > img, .loupe-books { position: absolute; inset: 0; width: 100%; height: 100%; }
.loupe-books img { position: absolute; display: block; filter: brightness(0.9) saturate(0.95); }
.loupe-ring { position: absolute; display: block; filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.6)); }
.shelf .book, .shelf img { -webkit-touch-callout: none; user-select: none; }
.shelf-hint { margin: 0; color: var(--muted); font-size: 0.9rem; }

/* ---------- the Sunroom ---------- */

/* The way in: the greenhouse itself, dimmed, with the door on it. */
.greenhouse { position: relative; display: block; width: 100%; aspect-ratio: 3 / 2; padding: 0; border: 2px solid var(--bezel-edge); border-radius: 10px; overflow: hidden; background: #000; }
.greenhouse img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(0.55); }
.greenhouse span { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 10px 18px; border-radius: 8px; background: var(--wound); color: var(--screen); letter-spacing: 0.06em; white-space: nowrap; }

/* Her game always plays over the whole screen. Stepping back to the board leaves it running. */
.game-frame { position: fixed; inset: 0; z-index: 100; overflow: hidden; background: #000; }
.game-frame.away { visibility: hidden; pointer-events: none; }
.game-stage { position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; display: flex; flex-direction: column; transform: translate(-50%, -50%); }
/* A phone held upright: the game is drawn sideways, so it reads once the phone is turned. */
.game-stage.turned { transform: translate(-50%, -50%) rotate(90deg); }
.game-bar { flex: none; display: flex; padding: 4px 8px; background: #000; }
.game-bar button { padding: 2px 10px; font-size: 0.85rem; }
.game-stage iframe { flex: 1; display: block; width: 100%; min-height: 0; border: 0; }
.turn-phone { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; padding: 24px; background: var(--ground); text-align: center; }
.turn-phone p { margin: 0; max-width: 22em; font-family: var(--display); font-size: 1.15rem; text-wrap: balance; }
.turn-icon { width: 110px; height: 110px; fill: none; stroke: var(--glow); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.turn-body { transform-box: view-box; transform-origin: 60px 54px; animation: turn-phone 2.6s ease-in-out infinite; }
@keyframes turn-phone {
  0%, 20% { transform: rotate(0deg); }
  50%, 85% { transform: rotate(-90deg); }
  100% { transform: rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) { .turn-body { animation: none; transform: rotate(-90deg); } }
html.in-game, html.in-game body { overflow: hidden; }

/* What the Sunroom leaves on the chart of the rig: the boxes at the hips, and what the vise did. */
.rig-chart .vise { fill: rgba(40, 36, 30, 0.1); stroke: #3b352c; stroke-width: 0.9; }
.rig-chart .hand { stroke: none; mix-blend-mode: multiply; opacity: 0.85; }
.rig-chart .hand.b1 { fill: #6b3a7a; }
.rig-chart .hand.b2 { fill: #9a2a2a; }
.rig-chart .hand.b3 { fill: #7a0e0e; }
.rig-chart .hand.b4 { fill: #4a0404; }
.rig-chart .drop { fill: #8fc3ea; opacity: 0.9; }

/* ---------- the Basement ---------- */

/* Each face shows only its own picture. */
:root[data-goggles="down"] .face-up, :root:not([data-goggles="down"]) .face-down { display: none; }

/* Her blueprint, the front view. The buttons sit over the padlocks she drew, label and all. */
.rig-sheet { position: relative; width: 100%; max-width: 440px; margin: 0 auto; aspect-ratio: 620 / 724; border-radius: 8px; overflow: hidden; }
.rig-sheet img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.rig-lock { position: absolute; padding: 0; border: 0; border-radius: 6px; background: transparent; }
.rig-lock[data-which="library"] { left: 58.4%; top: 6.6%; width: 31.1%; height: 10.2%; }
.rig-lock[data-which="sunroom"] { left: 62.1%; top: 32.9%; width: 28.2%; height: 8.8%; }
.rig-lock[data-which="kitchen"] { left: 62.6%; top: 66.3%; width: 34.5%; height: 9.4%; }
.rig-lock[data-which="rig"] { left: 64.8%; top: 81.2%; width: 28.7%; height: 8.6%; }
.rig-lock[data-state="ready"] { cursor: pointer; box-shadow: 0 0 0 2px rgba(201, 154, 69, 0.9), 0 0 14px rgba(201, 154, 69, 0.55); animation: lock-ready 1.8s ease-in-out infinite; }
.rig-lock:disabled { cursor: default; }
/* An opened lock gets a word in Elias's hand, in red ink, scrawled across its label. */
.rig-lock[data-state="open"]::after, .rig-lock[data-state="full"]::after {
  content: "open";
  position: absolute;
  right: 4%;
  top: 50%;
  font-family: var(--hand);
  font-size: clamp(2.2rem, 10vw, 3.4rem);
  line-height: 1;
  color: #a01818;
  -webkit-text-stroke: 0.6px #a01818;
  text-shadow: 0 0 3px rgba(240, 225, 200, 0.9);
  transform: translateY(-50%) rotate(-9deg);
  pointer-events: none;
}
.rig-lock[data-state="full"]::after { content: "full"; }
@keyframes lock-ready { 50% { box-shadow: 0 0 0 2px rgba(201, 154, 69, 0.4), 0 0 4px rgba(201, 154, 69, 0.2); } }
@media (prefers-reduced-motion: reduce) { .rig-lock[data-state="ready"] { animation: none; } }

/* Pip's ghost train, her art. The car rolls up close on the fairground's own rails, its own track running
   off the bottom edge toward us. Her view from behind, heading into the tunnel, comes next. */
.train-stage { position: relative; width: 100%; aspect-ratio: 1448 / 1086; border-radius: 10px; overflow: hidden; }
.train-stage .fairground { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.train-car { position: absolute; left: 25.7%; bottom: -12%; width: 56%; aspect-ratio: 480 / 523; }
.train-car img { display: block; width: 100%; height: 100%; }
/* The keyholes on the car glow: gold and breathing when a key can turn, a steady blush ring once open. */
.keyhole-glow { position: absolute; width: 9%; aspect-ratio: 1; border-radius: 50%; transform: translate(-50%, -50%); pointer-events: none; }
.keyhole-glow[data-which="kitchen"] { left: 31.6%; top: 27.4%; }
.keyhole-glow[data-which="library"] { left: 50.2%; top: 27.4%; }
.keyhole-glow[data-which="sunroom"] { left: 68.8%; top: 27.4%; }
.keyhole-glow[data-state="ready"] { box-shadow: 0 0 0 1.5px rgba(255, 224, 180, 0.95), 0 0 10px rgba(255, 205, 160, 0.85); animation: lock-ready 1.8s ease-in-out infinite; }
.keyhole-glow[data-state="open"] { box-shadow: 0 0 0 1.5px rgba(255, 239, 246, 0.95), 0 0 10px rgba(255, 170, 200, 0.9); }
/* The keys turn here, one button per emblem. */
.lap-locks { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; }
.lap-lock { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 84px; padding: 6px 8px; border: 2px solid var(--bezel-edge); border-radius: 10px; background: var(--ground); color: var(--text); font-family: var(--display); font-size: 0.85rem; }
.lap-lock img { display: block; width: 56px; height: auto; border-radius: 8px; }
.lap-lock:disabled { opacity: 1; cursor: default; }
.lap-lock[data-state="shut"] img { filter: grayscale(0.6) brightness(0.7); }
.lap-lock[data-state="ready"] { cursor: pointer; border-color: #ffd9b0; box-shadow: 0 0 12px rgba(255, 205, 160, 0.55); }
.lap-lock[data-state="open"] { border-color: #ffeff6; }
@media (prefers-reduced-motion: reduce) { .keyhole-glow[data-state="ready"] { animation: none; } }

.sound-row { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 0.9rem; }
.sound-row input { flex: 1; accent-color: var(--wound); }

/* In the seat: nothing at all, for as long as they are there. */
.in-the-seat { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center; background: #000; }
.in-the-seat p { margin: 0; font-family: var(--hand); font-size: 1.4rem; color: rgba(255, 255, 255, 0.14); }
html.in-the-dark, html.in-the-dark body { overflow: hidden; }

/* The key tray: the keys still to be used, each carried by a finger or a mouse to its lock. */
.key-tray { display: flex; justify-content: center; flex-wrap: wrap; gap: 14px; padding: 8px 0; }
.tray-key { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 8px; border: 2px dashed transparent; border-radius: 10px; background: transparent; color: var(--text); touch-action: none; cursor: grab; }
.tray-key img { display: block; height: 64px; width: auto; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6)); pointer-events: none; }
.tray-key img.pip-key { height: 96px; }
.tray-key .key-icon { width: 44px; height: 44px; }
.tray-key .key-icon path { stroke: #c99a45; }
/* A paper tag tied to each key, with its room in Elias's hand. */
.key-tag { padding: 1px 8px; border-radius: 3px; background: #e9dcc0; color: #2b1d12; font-family: var(--hand); font-size: 1.05rem; line-height: 1.3; transform: rotate(-4deg); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
:root[data-goggles="down"] .key-tag { background: #ffeff6; color: #693446; font-family: var(--display); font-size: 0.9rem; }
.tray-key[data-chosen="true"] { border-color: var(--glow); }
.tray-key.carried { position: relative; z-index: 20; cursor: grabbing; }
.rig-lock.key-over, .lap-lock.key-over { outline: 3px solid var(--glow); outline-offset: 2px; }

/* The party screen: everyone whose companion is out waits here while the others catch up. */
.at-the-party { position: fixed; inset: 0; z-index: 85; display: flex; align-items: center; justify-content: center; padding: 24px; background: radial-gradient(ellipse at center, rgba(60, 30, 20, 0.92), #0b0806 75%); }
:root[data-goggles="down"] .at-the-party { background: linear-gradient(rgba(29, 0, 8, 0.55), rgba(29, 0, 8, 0.85)), url("basement/fairground.jpg") center / cover no-repeat; }
.party-card { max-width: 30em; display: flex; flex-direction: column; gap: 14px; text-align: center; }
.party-line { margin: 0; font-family: var(--display); font-size: 1.35rem; line-height: 1.4; color: var(--text); text-wrap: balance; }
.party-wait { margin: 0; color: var(--muted); }
html.at-the-party, html.at-the-party body { overflow: hidden; }
/* If the finale needs a tap to play, its button floats above whichever screen they are on. */
.finale-card:not([hidden]) { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 95; }

/* Choosing each rig's answer in the control room. */
.feed-choice, .feed-note { font-family: var(--body); font-size: 0.9rem; padding: 4px 8px; border: 2px solid var(--bezel-edge); border-radius: 6px; background: var(--ground); color: var(--text); }
.feed-note { min-width: 14em; }
