/* The wordmark face: Cormorant Garamond, pinned to weight 600 and subsetted to
   caps, lower case and digits (8.6 KB). Chosen against the original Myst cover
   art for its splayed M, extreme stroke contrast and fine downward-wedge serifs
   on the T. Self-hosted — no CDN, no third-party request. SIL OFL, see
   fonts/OFL.txt.

   Lower case is in the subset because the book's cover reads "PhreakMyst", not
   PHREAKMYST; the wordmark here is still caps only. */
@font-face {
  font-family: 'Cormorant Caps';
  src: url('/fonts/cormorant-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020, U+0030-0039, U+0041-005A, U+0061-007A;
}

/* Palette lifted from the game client (Phreaknyst client/style.css) so the teaser
   and the game read as the same object. */
:root {
  --bg: #050706;
  --panel: #0d1311;
  --edge: #1d2a25;
  --ink: #7fe0b0;
  --ink-dim: #4e8f74;
  --text: #d6e6df;
  --muted: #7d918a;

  --mono: ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas,
          "DejaVu Sans Mono", "Liberation Mono", monospace;
  /* Georgia first in the fallback: it is the widely-available face whose
     proportions are least jarring if the woff2 never arrives. */
  --display: 'Cormorant Caps', Georgia, 'Times New Roman', Times, serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
}

body {
  min-height: 100vh;
  min-height: 100dvh; /* mobile: exclude the collapsing URL bar */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  /* A faint pool of phosphor behind the wordmark, so the page isn't flat black. */
  background-image: radial-gradient(
    ellipse 90% 60% at 50% 38%,
    #0d1a14 0%,
    var(--bg) 70%
  );
}

/* CRT scanlines — decorative, sits above the background and below the text. */
.scanlines {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: repeating-linear-gradient(
    180deg,
    #0000 0px,
    #0000 2px,
    #00000038 3px,
    #00000038 4px
  );
}

.stage {
  position: relative;
  z-index: 2;
  width: 100%;
  /* Wide enough that the wordmark at its 6.5rem cap still sits inside the
     stage rather than spilling past it. Below this the stage is just 100%. */
  max-width: 900px;
  text-align: center;
}

/* Wordmark */

.mark h1 {
  margin: 0;
  color: var(--ink);
  font-family: var(--display);
  /* Cormorant's caps are small for its em, so this runs larger than the
     monospace it replaced to land at the same optical size. */
  /* 10 tracked caps have to fit the viewport minus the 20px body padding each
     side. Driven by vw, with the tracking floor in em so the two scale together
     — at 390px this lands the ink at ~318px in a 350px column. */
  font-size: clamp(2rem, 11vw, 6.5rem);
  font-weight: 600;
  /* The Myst logo is very widely tracked; that spacing is half the look. */
  letter-spacing: clamp(0.09em, 0.9vw, 0.2em);
  /* Letter-spacing adds a trailing space after the final glyph, which centring
     counts as ink — the word lands half a letter-space left of true centre.
     Nudge back by exactly half. */
  text-indent: clamp(0.045em, 0.45vw, 0.1em);
  line-height: 1.05;
  /* Lighter glow than the monospace had: this face has hairline strokes that a
     heavy bloom turns to mush. */
  text-shadow: 0 0 14px #7fe0b038, 0 0 40px #7fe0b01f;
}

.tagline {
  margin: 14px 0 0;
  color: var(--muted);
  font-size: clamp(0.72rem, 2.6vw, 0.95rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* Countdown */

.countdown {
  margin: clamp(36px, 8vh, 64px) 0 0;
  /* Hold the row's height before the script paints, so nothing jumps — and
     centre within that reserve, or the slack all pools underneath the clock. */
  min-height: 5.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.countdown .fallback {
  margin: 0;
  color: var(--ink);
  font-size: clamp(1rem, 4vw, 1.5rem);
  letter-spacing: 0.1em;
}

.clock {
  display: flex;
  justify-content: center;
  gap: clamp(10px, 4vw, 34px);
  margin: 0;
}

.unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-width: clamp(56px, 17vw, 96px);
}

.unit .value {
  color: var(--ink);
  font-size: clamp(1.9rem, 9vw, 3.75rem);
  font-weight: 700;
  line-height: 1;
  /* Tabular figures stop the digits from shuffling width each second. */
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 14px #7fe0b03d;
}

.unit .label {
  color: var(--ink-dim);
  font-size: clamp(0.56rem, 2.1vw, 0.72rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

/* The state shown once the countdown reaches zero. */
.open {
  margin: 0;
  color: var(--ink);
  font-size: clamp(1.4rem, 6vw, 2.5rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-shadow: 0 0 20px #7fe0b04d;
}

.open a {
  color: inherit;
  text-decoration-color: var(--ink-dim);
  text-underline-offset: 6px;
}

.open a:hover,
.open a:focus-visible {
  text-decoration-color: var(--ink);
}

/* Visible only to assistive tech. Clipped rather than display:none, which
   would take it out of the accessibility tree entirely. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The glow and the scanlines are the only motion-ish effects here; drop the
   scanlines for anyone who has asked for less of that. */
@media (prefers-reduced-motion: reduce) {
  .scanlines { display: none; }
}

/* Very short landscape viewports (a phone turned sideways) — tighten the stack
   so the wordmark and the clock both stay above the fold. */
@media (max-height: 520px) {
  .countdown { margin-top: 24px; min-height: 0; }
}

/* ------------------------------------------------------------------------- *
   /enter — where the book's linking panel lands you. The page is the film
   and nothing else: its titles are burnt into the first seven seconds of it,
   so there is no HTML text to keep in sync with them. Everything below is
   scoped to .reel, so the book, the teaser and the 404 are untouched.
 * ------------------------------------------------------------------------- */

.reel {
  /* Undo the teaser's centred, padded stage: this page is edge to edge. */
  display: block;
  padding: 0;
  overflow: hidden;
  background: #000;
  background-image: none;
}

.film {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh; /* mobile: fill past the collapsing URL bar */
  z-index: 1;
  /* Always contain, never cover. The titles are burnt into the frame and the
     longest of them is 74% of its width, so any crop at all starts eating
     letters — and the film is the whole page, so a viewer who cannot see all
     of it is missing the thing they came for. Whatever the frame does not
     fill, the blurred plate behind it does. */
  object-fit: contain;
  background: transparent;
}

.reel-backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  /* The bare room — the poster has a title on it, and a blurred green smear
     behind the frame is not the idea. Always painted: with the frame always
     contained, there is nearly always some page for it to fill. */
  background: #000 url('/enter/fill.webp') center / cover no-repeat;
  /* Scaled up so the blur has material to work with at the edges instead of
     smearing the page background inwards. */
  transform: scale(1.15);
  filter: blur(34px) saturate(0.75) brightness(0.55);
}

/* The teaser's scanline overlay sits at z-index 1, which is the film here. */
.reel .scanlines { z-index: 2; }

/* Controls, once it is running. Present rather than pretty: a film this long
   needs a way to stop it (WCAG 2.2.2) and a way to silence it. Deliberately
   small and dim — the first seven seconds are a title card, and these must
   not upstage it. */

.reel-controls[hidden] { display: none; }

.reel-controls {
  position: fixed;
  z-index: 4;
  top: max(16px, env(safe-area-inset-top));
  right: max(16px, env(safe-area-inset-right));
  display: flex;
  align-items: center;
  gap: 8px;
}

.reel-btn {
  display: grid;
  place-items: center;
  width: 44px; /* a real touch target */
  height: 44px;
  padding: 0;
  border: 1px solid #1d2a2580;
  border-radius: 999px;
  background: #05070699;
  color: var(--text);
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 140ms ease, border-color 140ms ease;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.reel-btn:hover,
.reel-btn:focus-visible {
  opacity: 1;
  border-color: var(--ink-dim);
  color: var(--ink);
}

.reel-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reel-btn svg[hidden] { display: none; }
/* The play triangle is the one solid glyph in the set. */
.reel-btn .i-play { fill: currentColor; stroke-width: 1; }

/* Shown only where the browser refused to start the film with its sound on.
   The song does not begin until 0:07, so there is time for this to be read
   and acted on before anything is missed. A click anywhere does the same. */
.reel-nudge {
  order: -1; /* to the left of the buttons */
  color: var(--ink);
  font-size: 0.62rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  white-space: nowrap;
  text-shadow: 0 0 10px #000, 0 0 18px #7fe0b04d;
  animation: nudge 2.4s ease-in-out infinite;
}

.reel-nudge[hidden] { display: none; }

@keyframes nudge {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/* Press to play — and again once the film has run out. The only thing on the
   page until the film is running, so it is the one control allowed any size. */

.reel-start {
  position: fixed;
  z-index: 3;
  /* Under the title, not on it. The cards are centred at 0.46 of the frame
     height and stand about 0.07 of it tall, which puts their baseline within
     half a percent of the frame's mid-line — and the frame is centred in the
     viewport under both contain and cover. So the viewport's own mid-line is
     the title's baseline at every size, and the button only has to start
     below it. */
  top: calc(50% + 22px);
  left: 50%;
  translate: -50% 0;
  display: grid;
  place-items: center;
  width: clamp(76px, 18vw, 112px);
  aspect-ratio: 1;
  padding: 0;
  border: 1px solid var(--ink-dim);
  border-radius: 999px;
  background: #050706b8;
  color: var(--ink);
  cursor: pointer;
  box-shadow: 0 0 34px #7fe0b021;
  transition: background 140ms ease, border-color 140ms ease, scale 140ms ease;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.reel-start[hidden] { display: none; }

/* Solid, unlike the line icons in the corner — and nudged right, against the
   optical off-centre a circle always gives a triangle. */
.reel-start svg {
  width: 38%;
  fill: currentColor;
  margin-left: 8%;
}

.reel-start:hover,
.reel-start:focus-visible {
  border-color: var(--ink);
  background: #0d1311e0;
  scale: 1.04;
}

@media (prefers-reduced-motion: reduce) {
  .reel-start { transition: none; }
  .reel-start:hover, .reel-start:focus-visible { scale: 1; }
}

.reel-home {
  position: fixed;
  z-index: 4;
  left: max(16px, env(safe-area-inset-left));
  bottom: max(16px, env(safe-area-inset-bottom));
  color: var(--muted);
  font-size: clamp(0.6rem, 2.4vw, 0.72rem);
  letter-spacing: 0.22em;
  text-decoration: none;
  opacity: 0.65;
}

.reel-home:hover,
.reel-home:focus-visible {
  color: var(--ink);
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .reel-nudge { animation: none; opacity: 1; }
}
