/* The Last Phantasmagoria. Look and layout: docs/DESIGN.md */
@font-face {
  font-family: 'Source Serif 4';
  src: url('fonts/sourceserif4/SourceSerif4%5Bopsz,wght%5D.woff2') format('woff2');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Source Serif 4';
  src: url('fonts/sourceserif4/SourceSerif4-Italic%5Bopsz,wght%5D.woff2') format('woff2');
  font-weight: 200 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Caveat';
  src: url('fonts/caveat/Caveat%5Bwght%5D.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

:root {
  --ground: #0b0a09;
  --wood: #241812;
  --wood-edge: #3a2a1f;
  --wood-press: #2f2017;
  --brass: #b08d4f;
  --lamp: #e2a548;
  --ink-light: #cfc6b8;
  --ink-dim: #8d857a;
  --paper: #b4a78b;
  --ink: #2a1d14;
  --voice: #9cc7b8;
  --serif: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --hand: 'Caveat', 'Source Serif 4', cursive;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; background: var(--ground); color: var(--ink-light); overflow: hidden; }
body {
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.4;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}
button { font: inherit; color: inherit; }

.app {
  height: 100%;
  width: 100%;
  display: grid;
  gap: 8px;
  padding: env(safe-area-inset-top) max(8px, env(safe-area-inset-right)) max(8px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left));
  grid-template-columns: minmax(150px, 16%) minmax(0, 1fr) auto minmax(124px, 12%);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "bar  bar     bar   bar"
    "rack stage   lever play"
    "pump caption lever play";
}

/* header */
.bar {
  grid-area: bar;
  display: flex;
  align-items: center;
  gap: 4px 14px;
  flex-wrap: wrap;
  min-height: 44px;
  border-bottom: 1px solid var(--wood-edge);
}
.jam {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; min-width: 44px; padding: 0 10px;
  color: var(--brass); font-size: 15px; text-decoration: underline; text-underline-offset: 3px;
}
.jam:focus-visible, .tool:focus-visible, .ctl:focus-visible, .btn:focus-visible, .dial:focus-visible, .lever:focus-visible, .plate:focus-visible {
  outline: 2px solid var(--lamp); outline-offset: 2px;
}
.bar-title { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: 0.02em; color: var(--ink-light); }
.bar-night { margin: 0; font-size: 15px; color: var(--ink-dim); font-variant-numeric: tabular-nums; flex: 1 1 auto; }
.bar-tools { display: flex; gap: 6px; margin-left: auto; }
.tool {
  min-height: 44px; min-width: 44px; padding: 0 10px;
  background: transparent; border: 1px solid var(--wood-edge); border-radius: 4px;
  font-size: 14px; color: var(--ink-light); cursor: pointer;
}
.tool[aria-pressed="false"] { color: var(--ink-dim); text-decoration: line-through; text-decoration-thickness: 1px; }
.tool[aria-expanded="true"] { border-color: var(--brass); color: var(--lamp); }

/* stage */
.stage {
  grid-area: stage;
  min-height: 0; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.stage canvas { display: block; touch-action: none; }
.caption {
  grid-area: caption;
  margin: 0; min-height: 46px;
  --cap: 17px;
  font-style: italic; font-size: var(--cap); text-align: center;
  line-height: calc(var(--cap) * 1.4);   /* fixed, so a bigger line never resizes the stage */
  color: var(--ink-light);
  opacity: 0; transition: opacity 0.6s;
}
/* every line is read at full strength; only its size and weight say how big the reaction was */
.caption.on { opacity: 1; }
.caption[data-size="2"] { font-size: calc(var(--cap) * 1.15); }
.caption[data-size="3"] { font-size: calc(var(--cap) * 1.3); font-weight: 600; }
.caption.voice { color: var(--voice); }
/* a demonstration step: the help's own words, upright, so it never reads as the crowd */
.caption.hint { font-style: normal; color: var(--paper); }

/* the instrument */
.ctl {
  position: relative;
  min-height: 48px; min-width: 48px;
  background: var(--wood); border: 2px solid var(--wood-edge); border-radius: 6px;
  color: var(--ink-light); cursor: pointer; touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
}
.ctl:active, .ctl.pressed { background: var(--wood-press); border-color: var(--brass); transform: translateY(1px); }
.ctl-label { font-size: 14px; letter-spacing: 0.03em; }

.rack-wrap { grid-area: rack; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
.rack {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px;
  align-content: start;
  /* rows give up height evenly when the column is short (1280x720, 1366x768), and the glass
     shrinks inside its tile, so the last row stays in view without scrolling */
  grid-auto-rows: minmax(0, max-content);
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--wood-edge) transparent;
}
.plate {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-height: 44px; padding: 4px;
  background: #110c09; border: 2px solid var(--wood-edge); border-radius: 4px;
  cursor: pointer; touch-action: manipulation; color: var(--ink-light);
}
.plate canvas { width: 100%; aspect-ratio: 1; flex: 0 1 auto; min-height: 0; object-fit: contain; display: block; border-radius: 2px; }
.plate-name { flex: none; font-size: 13px; line-height: 1.15; text-align: center; min-height: calc(2.3em + 4px); padding-top: 4px; display: flex; align-items: center; }
.plate-key { position: absolute; top: 4px; left: 6px; font-size: 14px; color: var(--ink-dim); }
.plate.in { border-color: var(--lamp); }
.plate.in .plate-name { color: var(--lamp); }
.plate.cue-first { animation: pulse 2.4s ease-in-out infinite; }
.plate.arrived { animation: arrive 4s ease-out 1; }
/* the voice's mark fills as the asked plate is shown: a line under the glass, above the name.
   Where names are hidden (phones, the reveal) it runs along the tile's bottom edge instead. */
.plate.asked .plate-name {
  align-self: stretch; justify-content: center;
  background: linear-gradient(var(--voice), var(--voice)) no-repeat left top / calc(var(--seen, 0.15) * 100%) 2px;
}
.plate.asked::after {
  content: ''; position: absolute; left: 8px; right: 8px; bottom: 2px; height: 2px;
  background: var(--voice); opacity: 0.8;
  transform-origin: left; transform: scaleX(var(--seen, 0.15));
  display: none;
}
@keyframes pulse { 0%, 100% { border-color: var(--wood-edge); } 50% { border-color: var(--brass); } }
@keyframes arrive { 0% { opacity: 0; } 100% { opacity: 1; } }
.note {
  margin: 0; min-height: 2.6em;
  font-family: var(--hand); font-size: 20px; line-height: 1.15; color: var(--paper);
  transition: opacity 0.4s;
}
.note.other-hand, .note.asking { font-family: var(--serif); font-style: italic; font-size: 15px; color: var(--voice); }
/* in a blackout the payoff caption is the only line lit */
.note.dark { opacity: 0.15; }

.pump { grid-area: pump; display: flex; gap: 8px; align-items: stretch; }
.bellows { flex: 1 1 auto; min-height: 64px; }
.bellows.refused { animation: refuse 0.25s; }
@keyframes refuse { 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
.dial {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-width: 72px; padding: 4px; touch-action: none; cursor: grab;
  user-select: none; -webkit-user-select: none;
}
.dial-face {
  position: relative; width: 52px; height: 52px; border-radius: 50%;
  background: #17100c; border: 3px solid var(--brass);
}
.dial-pointer {
  position: absolute; left: 50%; top: 4px; width: 3px; height: 20px; margin-left: -1.5px;
  background: var(--lamp); transform-origin: 50% 20px;
}

.lever-wrap { grid-area: lever; display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 0; }
.lever {
  position: relative; flex: 1 1 auto; width: 76px; min-height: 140px;
  touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none;
}
.lever-track {
  position: absolute; left: 50%; top: 22px; bottom: 22px; width: 14px; margin-left: -7px;
  background: #080606; border: 2px solid var(--wood-edge); border-radius: 7px;
}
.lever-ghost {
  position: absolute; left: 4px; width: 14px; height: 4px; margin-top: -2px;
  background: var(--lamp); border-radius: 2px; top: 0;
}
.lever-grip {
  position: absolute; left: 50%; width: 58px; height: 40px; margin: -20px 0 0 -29px; top: 0;
  background: var(--wood); border: 2px solid var(--brass); border-radius: 6px;
  box-shadow: inset 0 -8px 0 rgba(0, 0, 0, 0.25);
}
.lever.dragging .lever-grip { border-color: var(--lamp); }

.play { grid-area: play; display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.cap {
  flex: 0 1 auto; width: 100%; max-width: 168px; aspect-ratio: 1; min-height: 72px; max-height: 168px;
  align-self: center;
  border-radius: 50%;
  background: #17100c; border: 3px solid var(--brass);
  touch-action: none;
}
.cap[aria-pressed="true"] { background: #050404; border-color: var(--lamp); }
.cap[aria-pressed="true"] .ctl-label { color: var(--lamp); }
.cues { display: flex; flex-direction: column; gap: 6px; }
.cue { overflow: hidden; }
.cue-fill {
  position: absolute; left: 0; bottom: 0; height: 100%; width: 100%;
  background: rgba(0, 0, 0, 0.45); transform-origin: left; transform: scaleX(0);
}
.cue .ctl-label { position: relative; }
.cue.cooling .ctl-label { color: var(--ink-dim); }

/* sheet: title card, night intro, ticket page, ending. It replaces the controls, never the screen. */
.sheet {
  grid-area: sheet;
  display: none;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 10px 8px 16px;
}
.sheet h2 { margin: 0 0 8px; font-size: 30px; font-weight: 600; line-height: 1.1; color: var(--ink-light); }
.sheet .kicker { margin: 0 0 4px; font-size: 14px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-dim); }
.sheet p { margin: 0 0 12px; font-size: 17px; }
.sheet .goal { font-size: 19px; font-style: italic; }
.btn-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.btn {
  min-height: 48px; padding: 0 18px;
  background: var(--wood); border: 2px solid var(--brass); border-radius: 6px;
  font-size: 17px; color: var(--ink-light); cursor: pointer;
}
.btn.primary { border-color: var(--lamp); color: var(--lamp); }
.btn.quiet { border-color: var(--wood-edge); color: var(--ink-dim); }
.paper {
  background: var(--paper); color: var(--ink);
  padding: 14px 16px 16px; border-radius: 2px;
  box-shadow: inset 0 0 40px rgba(60, 40, 20, 0.35);   /* unslop-ignore: brown foxing at the edges of old ticket paper, an inset darkening, not a glow */
}
.sheet .paper { margin-bottom: 14px; }
.paper h3 { margin: 0 0 6px; font-size: 20px; font-weight: 600; }
.paper .hand { font-family: var(--hand); font-size: 23px; line-height: 1.2; margin: 0 0 4px; }
.paper .ledger { margin-top: 10px; border-top: 1px solid rgba(42, 29, 20, 0.35); padding-top: 8px; }
.paper .ledger p { font-family: var(--hand); font-size: 20px; margin: 0 0 2px; }
.ending-body p { font-size: 18px; }

/* side panels: the book and help. Each has a large close control and remembers its state. */
.panel {
  grid-row: rack-start / pump-end;
  grid-column: rack-start / rack-end;
  z-index: 2;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 10px;
  background: var(--ground);
  border: 1px solid var(--wood-edge);
}
.panel[hidden] { display: none; }
.panel .btn { width: 100%; margin-top: 12px; }
.help ul { margin: 0; padding-left: 18px; }
.help li { margin-bottom: 8px; font-size: 16px; }

/* modes */
.app:not([data-mode="show"]) {
  grid-template-columns: minmax(280px, 36%) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "bar   bar"
    "sheet stage"
    "sheet caption";
}
.app:not([data-mode="show"]) .rack-wrap,
.app:not([data-mode="show"]) .pump,
.app:not([data-mode="show"]) .lever-wrap,
.app:not([data-mode="show"]) .play { display: none; }
.app:not([data-mode="show"]) .sheet { display: block; }
.app:not([data-mode="show"]) .panel { grid-area: sheet; }
.app[data-mode="title"] .bar-title { display: none; }
.app:not([data-mode="show"]) #btnBook,
.app.book-open #btnBook { display: none; }
/* the reveal: the seats are silent, so no line under the screen; the rack holds one plate,
   named by the note under it, so its tile is glass only */
.app.reveal .caption.on { opacity: 0; }
.app.reveal .plate-name { display: none; }
.app.reveal .plate.arrived { animation-duration: 1.2s; }
/* title card, intro, ticket page and ending: the sheet's words sit at the middle of their column */
.app:not([data-mode="show"]) .sheet { display: flex; flex-direction: column; justify-content: center; justify-content: safe center; }

/* reduced motion: no shudder on a refused pump, no pulsing border; the caption and note still fade */
@media (prefers-reduced-motion: reduce) {
  .bellows.refused { animation: none; border-color: var(--ink-dim); }
  .plate.cue-first { animation: none; border-color: var(--brass); }
  .ctl:active, .ctl.pressed { transform: none; }
}

/* phone and narrow landscape */
@media (max-height: 520px) and (orientation: landscape) {
  .app { gap: 6px; }
  .bar-title { display: none; }
  .bar { min-height: 44px; border-bottom: 0; }
  .tool { padding: 0 8px; font-size: 13px; }
  .caption { min-height: 0; --cap: 15px; }
  .plate { padding: 3px 3px 6px; }
  .plate-name { display: none; }
  .plate.asked::after { display: block; }
  .note { font-size: 18px; min-height: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; }
  .lever { width: 64px; min-height: 100px; }
  .cap { min-height: 64px; max-height: 112px; max-width: 112px; }
  .cue { min-height: 44px; }
  .sheet h2 { font-size: 24px; }
  .sheet p { font-size: 16px; }
}

/* portrait: screen on top, controls below */
@media (orientation: portrait) {
  .app {
    gap: 6px;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-rows: auto auto auto auto minmax(250px, 1fr);
    grid-template-areas:
      "bar     bar     bar"
      "stage   stage   stage"
      "caption caption caption"
      "rack    rack    rack"
      "pump    lever   play";
    overflow-y: auto;
  }
  .app:not([data-mode="show"]) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr);
    grid-template-areas: "bar" "stage" "caption" "sheet";
  }
  /* the link and the tools share one row; the title and the night line share the one under it */
  .bar { gap: 0 6px; }
  .jam { padding: 0 6px; }
  .bar-title { order: 3; font-size: 14px; line-height: 1.3; white-space: nowrap; }
  .bar-night { order: 4; flex: 1 1 auto; font-size: 14px; line-height: 1.3; white-space: nowrap; }
  .bar-tools { order: 2; }
  .bar-tools { gap: 4px; }
  .tool { padding: 0 7px; font-size: 13px; }
  .cap { flex: 0 0 auto; width: 104px; height: 104px; min-height: 0; }
  .stage { aspect-ratio: 4 / 3; width: 100%; }
  .caption { min-height: 0; --cap: 15px; }
  .rack {
    display: flex; overflow-x: auto; overflow-y: hidden; gap: 6px;
    scroll-snap-type: x proximity;
  }
  .plate { flex: 0 0 80px; scroll-snap-align: start; }
  /* the cut edge fades where more glass waits, so a half plate reads as "scroll", not as a fault */
  .rack.more-right { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); }
  .rack.more-left { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 56px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 56px), transparent); }
  .rack.more-left.more-right {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent);
  }
  .note { min-height: 1.2em; font-size: 19px; }
  /* the bellows is a fixed handle, not a panel: it keeps its size and the column ends under the iris */
  .pump { flex-direction: column; justify-content: flex-start; }
  .bellows { flex: 0 0 auto; height: 88px; min-height: 0; }
  .lever { width: 72px; }
  .panel { grid-row: rack-start / pump-end; grid-column: 1 / -1; }
}

/* short portrait phones (360x640, 375x667): the column above is about 120 px too tall. The stage
   takes what is left, the cues become one row under the controls, the rack shows glass only
   (each plate keeps its name for screen readers and in the note when it goes in). */
@media (orientation: portrait) and (max-height: 720px) {
  .app {
    grid-template-rows: auto minmax(150px, 1fr) auto auto auto auto;
    grid-template-areas:
      "bar     bar     bar"
      "stage   stage   stage"
      "caption caption caption"
      "rack    rack    rack"
      "pump    lever   cap"
      "cues    cues    cues";
    overflow-y: hidden;
  }
  .stage { aspect-ratio: auto; height: auto; }
  .plate { flex-basis: 64px; padding: 3px 3px 6px; }
  .plate-name { display: none; }
  .plate.asked::after { display: block; }
  .note { font-size: 18px; min-height: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; }
  .play { display: contents; }
  .cap { grid-area: cap; width: 96px; height: 96px; }
  .cues { grid-area: cues; flex-direction: row; }
  .cue { flex: 1 1 0; min-height: 48px; padding: 0 4px; }
  .bellows { height: 64px; }
  .lever { min-height: 120px; }
  .panel { grid-row: rack-start / cues-end; }
}
