/* ============================================================
   THE RITE OF MAN — Direction A: Night Ops Expedition
   near-black / bone / torch amber. AAA loadout screen energy.
   ============================================================ */

@font-face {
  font-family: 'Oswald';
  src: url('../fonts/oswald-500.woff2') format('woff2');
  font-weight: 500;
  font-display: swap; /* Move 5a: not preloaded, so block = invisible text on slow links */
}
@font-face {
  font-family: 'Oswald';
  src: url('../fonts/oswald-600.woff2') format('woff2');
  font-weight: 600;
  font-display: block;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-400.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-500.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/plexmono-400.woff2') format('woff2');
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/plexmono-500.woff2') format('woff2');
  font-weight: 500;
  font-display: swap; /* Move 5a: not preloaded, so block = invisible text on slow links */
}

:root {
  --bg: #0B0E0D;
  --bg-raise: #10514f00; /* unused guard */
  --surface: #101514;
  --surface-2: #0E1312;
  --bone: #E7E2D3;
  --bone-dim: #A3Aca3;
  --bone-faint: rgba(231, 226, 211, 0.14);
  --amber: #E8A33D;
  --amber-soft: rgba(232, 163, 61, 0.35);
  --pine: #12201B;
  --display: 'Oswald', 'Arial Narrow', sans-serif;
  --body: 'Inter', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --measure: 40rem;
  --pad-x: clamp(1.25rem, 5vw, 3rem);

  /* screen-framing: cap the frame at ~Studio Display width with near-black
     margins on wide / ultra-wide monitors (Apple-style), which also un-crops
     the film. Height-aware so tall 4K/5K is never side-cropped (B1). Collapses
     to non-binding at ≤2560, so laptops/QHD are pixel-identical to before. */
  --frame-max: 2560px;                                  /* fallback: no-lvh browsers cap flat */
  --frame-max: max(2560px, calc(100lvh * 16 / 9));      /* never narrower than the 16:9 width of the current viewport height */
  --frame-gutter: max(0px, calc((100vw - var(--frame-max)) / 2));

  /* How far the bone edge-lines sit INSIDE the framed image, so a thin band of
     picture shows outside them and the edge reads as a mount rather than a
     border. Isaiah's call, 2026-07-31: "it kind of creates a little bit of an
     almost frame on the outsides. I actually like that."

     It was already happening by accident and only for some people: the lines
     were positioned from --frame-gutter (100vw, which counts the scrollbar)
     while the content centres in the box that does not, landing them ~6.5px in
     on a classic-scrollbar setup and flush on the overlay scrollbars macOS uses
     by default. Making it an explicit value means everyone sees the same frame.
     Tune this one number to taste. */
  --frame-line-inset: 7px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  background: var(--bg);
  /* Reserve the scrollbar's space permanently, so a scroll lock releasing is not
     a layout event. Isaiah, 2026-07-31, on a widescreen monitor with classic
     (non-overlay) scrollbars: the cold open's `overflow:hidden` removes the bar,
     so the content box is ~15px wider while it holds and snaps back when it
     releases — and everything centred, <main> and the cold open alike, jumped
     7.5px left at the handoff. Measured in Chromium: -7.50px without this line,
     0.00px with it.

     Nearly free: the page is always tall enough to scroll, so on a classic-
     scrollbar setup that 15px is already spoken for at every other moment. This
     only stops the lock from briefly reclaiming it. Under overlay scrollbars
     (the macOS default) the property reserves nothing and changes nothing.

     Compensating with padding while the lock is up would also work, but it means
     matching a width that varies by OS, browser and user setting. Reserving the
     space needs no number. Safari <16 ignores this and keeps the old 7.5px step:
     a graceful degrade, not a break.

     This also covers every other full-screen overlay that locks scroll — the act
     transition portal is the next one — so it is fixed once here, not per case. */
  scrollbar-gutter: stable;
}

body {
  background: var(--bg);
  color: var(--bone);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* screen-framing: the cap lever. Everything cinematic lives inside <main> on
   both pages, so capping it contains all the sticky/relative film stages.
   Margins show the page bg (near-black). Non-binding at ≤2560 (gutter 0). */
main { max-width: var(--frame-max); margin-inline: auto; }

::selection { background: var(--amber); color: #0B0E0D; }

.mono {
  font-family: var(--mono);
  font-weight: 400;
}

a { color: var(--bone); }
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
}

.skip {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 100;
  background: var(--amber);
  color: #0B0E0D;
  padding: 0.5rem 1rem;
  text-decoration: none;
  font-family: var(--mono);
  font-size: 0.8rem;
}
.skip:focus { left: 0; }

/* ---------- NAV ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem var(--pad-x);
  /* re-anchor the nav mark + links to the frame edge on ultra-wide (B3). The
     .is-scrolled blur bar intentionally stays full-bleed (a letterbox bar).
     At ≤2560 the gutter is 0 → identical to today. */
  padding-inline: calc(var(--frame-gutter) + var(--pad-x));
  transition: background-color 0.4s ease, border-color 0.4s ease;
  border-bottom: 1px solid transparent;
}
.nav.is-scrolled {
  background: rgba(11, 14, 13, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom-color: var(--bone-faint);
}
.nav-mark {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-decoration: none;
  white-space: nowrap;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
}
.nav-links a {
  text-decoration: none;
  color: var(--bone-dim);
  transition: color 0.25s ease;
  white-space: nowrap;
}
.nav-links a:hover { color: var(--amber); }
.nav-dot { color: var(--bone-faint); }

/* ---------- HERO ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 6rem var(--pad-x) 2.5rem;
  overflow: hidden;
}

.hero-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-photo picture,
.hero-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 80% 62% at 50% 44%, rgba(11, 14, 13, 0.18) 0%, rgba(11, 14, 13, 0.72) 100%),
    linear-gradient(to top, rgba(11, 14, 13, 0.85) 0%, rgba(11, 14, 13, 0.25) 35%, rgba(11, 14, 13, 0.3) 100%);
}
.hero-contours {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0.55;
}
.hero-contours svg {
  width: 100%;
  height: 100%;
  display: block;
}
.contour-drift { animation: drift 70s ease-in-out infinite alternate; }
.contour-drift-2 { animation: drift 90s ease-in-out infinite alternate-reverse; }
@keyframes drift {
  from { transform: translate3d(-1.2%, 0.4%, 0); }
  to   { transform: translate3d(1.2%, -0.4%, 0); }
}

.hero-torch {
  position: absolute;
  z-index: 0;
  width: min(120vw, 900px);
  aspect-ratio: 1;
  left: 50%;
  top: 52%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgba(232, 163, 61, 0.14) 0%,
    rgba(232, 163, 61, 0.05) 32%,
    rgba(232, 163, 61, 0) 62%);
  animation: flicker 7s ease-in-out infinite;
}
@keyframes flicker {
  0%, 100% { opacity: 0.85; }
  18% { opacity: 1; }
  34% { opacity: 0.78; }
  55% { opacity: 0.96; }
  71% { opacity: 0.82; }
  86% { opacity: 0.92; }
}

.hero-grid-ref {
  position: absolute;
  top: 4.6rem;
  right: var(--pad-x);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  color: var(--bone-dim);
  opacity: 0.7;
}

.hero-core { position: relative; z-index: 1; }

.eyebrow {
  font-size: clamp(0.62rem, 1.8vw, 0.75rem);
  letter-spacing: 0.32em;
  color: var(--amber);
  margin-bottom: clamp(1.4rem, 3.5vh, 2.4rem);
}

h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(3.1rem, 13.5vw, 8.5rem);
  line-height: 0.98;
  letter-spacing: 0.015em;
  text-wrap: balance;
}

.subline {
  margin-top: clamp(1.5rem, 3.5vh, 2.5rem);
  font-size: clamp(1rem, 2.6vw, 1.2rem);
  line-height: 1.65;
  color: var(--bone-dim);
  max-width: 34rem;
  margin-inline: auto;
}

.hero-foot {
  position: absolute;
  z-index: 1;
  bottom: 2rem;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
}
.microline {
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  color: var(--bone-dim);
}
.scroll-cue { height: 3rem; width: 1px; overflow: hidden; }
.scroll-line {
  display: block;
  width: 1px;
  height: 100%;
  background: linear-gradient(to bottom, transparent, var(--amber));
  animation: descend 2.6s ease-in-out infinite;
}
@keyframes descend {
  0% { transform: translateY(-100%); }
  55%, 100% { transform: translateY(100%); }
}

/* ---------- SECTION SCAFFOLD ---------- */

.sec {
  position: relative;
  padding: clamp(5.5rem, 14vh, 9.5rem) var(--pad-x);
  border-top: 1px solid rgba(231, 226, 211, 0.07);
}
.sec-inner {
  max-width: 68rem;
  margin-inline: auto;
}
.sec-inner.narrow { max-width: var(--measure); }
.narrow-block { max-width: var(--measure); }

.sec-ref {
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  color: var(--bone-dim);
  opacity: 0.75;
  margin-bottom: 1.4rem;
}
.sec-ref::before {
  content: '';
  display: inline-block;
  width: 1.6rem;
  height: 1px;
  background: var(--amber);
  vertical-align: middle;
  margin-right: 0.7rem;
}

h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.9rem, 6vw, 3.3rem);
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-bottom: clamp(1.8rem, 4vh, 2.8rem);
  text-wrap: balance;
}

.body p + p { margin-top: 1.3em; }
.body em { font-style: italic; color: var(--bone); }
.body strong { font-weight: 500; color: var(--bone); }
.body { color: #C9C6B9; }

.the-lie { color: var(--bone); }

/* ---------- §4 THE MAP ---------- */

.sec-map .narrow-block { margin-bottom: clamp(3rem, 7vh, 4.5rem); }

.cave-figure { margin: 0; }
.cave-svg {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid rgba(231, 226, 211, 0.1);
  background: #0A0D0C;
}
.mono-svg { font-family: var(--mono); }
.torch-halo { animation: halo 6s ease-in-out infinite; transform-origin: 690px 462px; }
@keyframes halo {
  0%, 100% { opacity: 0.8; }
  40% { opacity: 1; }
  65% { opacity: 0.75; }
}
.cave-caption {
  margin-top: 0.9rem;
  font-size: 0.62rem;
  letter-spacing: 0.22em;
  color: var(--bone-dim);
  opacity: 0.7;
}

/* ---------- §5 THREE ACTS ---------- */

.acts-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: rgba(231, 226, 211, 0.12);
  border: 1px solid rgba(231, 226, 211, 0.12);
}
.act-card {
  background: var(--surface-2);
  padding: clamp(1.6rem, 3vw, 2.4rem);
  display: flex;
  flex-direction: column;
  min-height: 100%;
  transition: background-color 0.3s ease;
}
.act-card:hover { background: #121816; }
.act-card.is-current {
  box-shadow: inset 3px 0 0 var(--amber);
}
.act-num {
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  color: var(--bone-dim);
  margin-bottom: 1.6rem;
}
.act-card.is-current .act-num { color: var(--amber); }
.act-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  letter-spacing: 0.04em;
  line-height: 1;
}
.act-who {
  font-style: italic;
  color: var(--bone-dim);
  margin-top: 0.5rem;
  margin-bottom: 1.1rem;
}
.act-body {
  font-size: 0.95rem;
  line-height: 1.7;
  color: #C9C6B9;
}
.acts-under {
  margin-top: 2rem;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  color: var(--bone-dim);
  text-align: center;
}

.act-card-link {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.act-open {
  margin-top: auto;
  padding-top: 1.4rem;
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  color: var(--amber);
  transition: letter-spacing 0.25s ease;
}
.act-card-link:hover .act-open,
.act-card-link:focus-visible .act-open {
  letter-spacing: 0.2em;
}
.act-locked {
  display: block;
  margin-top: auto;
  padding-top: 1.4rem;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  color: var(--bone-dim);
  opacity: 0.75;
}

/* ---------- §6 GUIDE'S NOTE ---------- */

.note-body { max-width: var(--measure); }
.note-body p {
  font-size: 1.18rem;
  line-height: 1.9;
  color: #DAD6C8;
}
.note-body p + p { margin-top: 1.8em; }
.note-sign {
  margin-top: 2.4rem;
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  color: var(--amber);
}

/* ---------- §6 SKELETON ---------- */

.skeleton {
  margin-top: clamp(2.5rem, 6vh, 3.8rem);
  border: 1px solid rgba(231, 226, 211, 0.14);
  background: var(--surface-2);
  padding: clamp(1.5rem, 4vw, 2.2rem);
}
.skeleton-title {
  font-size: 0.66rem;
  letter-spacing: 0.26em;
  color: var(--amber);
  font-weight: 500;
  margin-bottom: 1.3rem;
}
.skeleton-chain {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  row-gap: 0.55rem;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--bone);
}
.skeleton-chain li { white-space: nowrap; }
.skeleton-chain li:not(:last-child)::after {
  content: '→';
  color: var(--amber);
  margin: 0 0.65rem;
}
.skeleton-meta {
  margin-top: 1.3rem;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  color: var(--bone-dim);
}

/* ---------- §7 LOG CARD ---------- */

.log-card {
  margin-top: clamp(2.5rem, 6vh, 3.5rem);
  background: var(--surface);
  border: 1px solid rgba(231, 226, 211, 0.16);
  padding: clamp(1.4rem, 4vw, 2rem);
  transform: rotate(-0.5deg);
  position: relative;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}
.log-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 2.2rem;
  height: 2.2rem;
  background:
    linear-gradient(135deg, var(--amber) 0, var(--amber) 2px, transparent 2px) top left / 0.9rem 2px no-repeat,
    linear-gradient(135deg, var(--amber) 0, var(--amber) 2px, transparent 2px) top left / 2px 0.9rem no-repeat;
}
.log-card-head {
  display: flex;
  justify-content: space-between;
  font-size: 0.64rem;
  letter-spacing: 0.22em;
  color: var(--amber);
  margin-bottom: 1.8rem;
}
.log-line {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.05rem 0;
}
.log-label {
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  color: var(--bone-dim);
  flex-shrink: 0;
}
.log-rule {
  flex: 1;
  border-bottom: 1px dashed rgba(231, 226, 211, 0.28);
  min-height: 1px;
  transform: translateY(-2px);
}
.log-card-foot {
  margin-top: 1.6rem;
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  color: var(--bone-dim);
  opacity: 0.65;
  text-align: right;
}

/* ---------- §8 FINISH LINES ---------- */

.sec-finish { background: var(--surface-2); }
.finish-intro {
  color: #C9C6B9;
  max-width: var(--measure);
  margin-bottom: clamp(3rem, 8vh, 5rem);
}
.finish-lines {
  display: flex;
  flex-direction: column;
  gap: clamp(2.2rem, 6vh, 3.8rem);
  margin-bottom: clamp(3rem, 8vh, 5rem);
}
.finish-line {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.55rem, 5.4vw, 3.4rem);
  line-height: 1.15;
  letter-spacing: 0.015em;
  text-wrap: balance;
}
.finish-index {
  display: block;
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  color: var(--amber);
  margin-bottom: 0.7rem;
}
@media (min-width: 720px) {
  .finish-line:nth-child(2) { margin-left: 8%; }
  .finish-line:nth-child(3) { margin-left: 16%; }
}
.finish-closer {
  font-size: 0.95rem;
  color: var(--bone-dim);
  border-top: 1px solid rgba(231, 226, 211, 0.12);
  padding-top: 1.6rem;
  max-width: var(--measure);
}

/* ---------- §9 PRICE ---------- */

.price-list {
  list-style: none;
  margin-top: 2rem;
  border-top: 1px solid rgba(231, 226, 211, 0.12);
}
.price-list li {
  padding: 1.4rem 0;
  border-bottom: 1px solid rgba(231, 226, 211, 0.12);
  color: #C9C6B9;
}
.price-list strong {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.25rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--bone);
  margin-bottom: 0.3rem;
}

.rules {
  margin-top: clamp(2.6rem, 6vh, 3.6rem);
  border: 1px solid rgba(231, 226, 211, 0.14);
  background: var(--surface-2);
  padding: clamp(1.5rem, 4vw, 2.2rem);
}
.rules-title {
  font-size: 0.66rem;
  letter-spacing: 0.26em;
  color: var(--amber);
  font-weight: 500;
  margin-bottom: 1.2rem;
}
.rules-list {
  list-style: none;
  font-size: 0.95rem;
  color: #C9C6B9;
}
.rules-list li {
  padding: 0.55rem 0 0.55rem 1.4rem;
  position: relative;
}
.rules-list li::before {
  content: '·';
  position: absolute;
  left: 0.2rem;
  color: var(--amber);
}

.boundary {
  margin-top: clamp(2.6rem, 6vh, 3.6rem);
  border: 1px solid var(--amber-soft);
  padding: clamp(1.5rem, 4vw, 2.2rem);
  color: #C9C6B9;
  position: relative;
}
.boundary::before {
  content: '';
  position: absolute;
  top: -1px;
  left: -1px;
  width: 0.9rem;
  height: 0.9rem;
  border-top: 2px solid var(--amber);
  border-left: 2px solid var(--amber);
}
.boundary strong { color: var(--bone); font-weight: 500; }

/* ---------- §10 THE SEAT ---------- */

.sec-seat { padding-bottom: clamp(6rem, 16vh, 11rem); }
.roster {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.7rem;
  margin: clamp(2.4rem, 6vh, 3.6rem) 0;
  max-width: 46rem;
}
.seat-slot {
  aspect-ratio: 4 / 5;
  border: 1px dashed rgba(231, 226, 211, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}
.seat-num {
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  color: var(--bone-dim);
}
.seat-state {
  font-size: 0.52rem;
  letter-spacing: 0.2em;
  color: var(--bone-dim);
  opacity: 0.6;
}
.seat-slot.is-filled {
  border: 1px solid var(--amber);
  background: rgba(232, 163, 61, 0.07);
}
.seat-slot.is-filled .seat-num,
.seat-slot.is-filled .seat-state {
  color: var(--amber);
  opacity: 1;
}

.seat-body { margin-bottom: clamp(2.2rem, 5vh, 3rem); }

.cta-row { margin-top: 0.5rem; }
.cta {
  display: inline-block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: #0B0E0D;
  background: var(--amber);
  padding: 1.05rem 2.4rem;
  transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease;
}
.cta:hover {
  background: #F0B355;
  box-shadow: 0 0 44px rgba(232, 163, 61, 0.35);
}

/* ---------- FOOTER ---------- */

.footer {
  border-top: 1px solid rgba(231, 226, 211, 0.1);
  padding: 3rem var(--pad-x) 3.4rem;
  text-align: center;
}
.footer-mark {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.26em;
}
.footer-line {
  margin-top: 0.8rem;
  font-size: 0.64rem;
  letter-spacing: 0.2em;
  color: var(--bone-dim);
}

/* ---------- GRAIN ---------- */

.grain {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* screen-framing: thin bone hairline at the film/margin boundary so the edge
   reads as an intentional projected frame (B4). At ≤2560 the gutter is 0, so
   the lines sit at −1px → off-screen (clipped by body overflow-x:hidden). z 44
   keeps them under the HUD (z 45). */
body::before, body::after {
  content: ''; position: fixed; top: 0; bottom: 0; width: 1px;
  background: var(--bone-faint); z-index: 44; pointer-events: none;
}
/* Positioned from the CONTENT box, not 100vw, so they land in the same place as
   <main>'s edge whatever the scrollbar is doing, then step --frame-line-inset
   inward. Both pseudo-elements are position:fixed, so 100% here is the same
   initial containing block <main> centres in. */
body::before { left:  calc((100% - min(100%, var(--frame-max))) / 2 + var(--frame-line-inset)); }
body::after  { right: calc((100% - min(100%, var(--frame-max))) / 2 + var(--frame-line-inset)); }

/* ---------- REVEAL ---------- */

.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1), transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}
.reveal.in {
  opacity: 1;
  transform: none;
}

/* ---------- MOBILE ---------- */

@media (max-width: 860px) {
  .acts-grid { grid-template-columns: 1fr; }
  .roster { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 480px) {
  body { font-size: 1rem; }
  .nav { padding: 0.8rem 1.1rem; }
  .nav-mark { font-size: 0.62rem; letter-spacing: 0.16em; }
  .nav-links { font-size: 0.56rem; gap: 0.45rem; }
  .hero-grid-ref { display: none; }
  .skeleton-chain { flex-direction: column; }
  .skeleton-chain li:not(:last-child)::after { content: '↓'; display: block; margin: 0.15rem 0 0 0; }
  .log-label { min-width: 6.5rem; }
}

/* ---------- REDUCED MOTION ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .contour-drift, .contour-drift-2, .hero-torch, .scroll-line, .torch-halo {
    animation: none;
  }
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* homepage hero plate — mobile crop keeps the cave-mouth glow centered */
@media (max-width: 640px) {
  .hero-photo img { object-position: 55% 45%; }
}

/* ============================================================================
   DECODE + SOUND  —  plans/decode-and-scrub-audio.md
   ============================================================================ */

/* ---------- the decode hold ----------
   A block must not render final for a frame and then scramble. It is held at
   opacity 0 until its first decode fires, and the hold is FAIL-OPEN: the class
   is only ever added by audio.js, so if that script 404s, throws, or never runs
   (reduced motion, no Web Audio) the copy is simply visible. Nothing may hold
   copy that cannot prove it can let go. */
[data-decode].decode-hold {
  opacity: 0 !important;
}
[data-decode].is-decoding {
  /* the line is full length from frame one, so nothing may reflow mid-run */
  font-variant-ligatures: none;
  font-kerning: none;
}

/* ---------- THE DECODE'S TWO TONES (Isaiah, 2026-07-31) ----------
   Settled text lands at FULL weight and full opacity: the decode should read as
   copy arriving finished, not as copy fading up. Churning text sits behind it in
   the site's amber at reduced alpha, so the wave front is a visible edge between
   "resolved" and "still coming" rather than a uniform grey mush.

   Two runs, never per-character spans: the front is strictly left to right, so a
   line is always exactly [settled][churning]. Both tones are vars so they can be
   tuned by eye without touching the engine. */
:root {
  --decode-in: #E7E2D3;                      /* bone, full strength */
  --decode-out: rgba(232, 163, 61, 0.60);    /* amber at 60%, the hero's own accent */
}
[data-decode] .dc-in  { color: var(--decode-in); }
[data-decode] .dc-out { color: var(--decode-out); }
/* Inline spans, so wrapping and metrics are identical to the bare text node they
   replaced. `.dc` exists only as a seam for future treatment. */
[data-decode] .dc { display: inline; }

/* ---------- WPT 08's hold, fail-open (§13.21) ----------
   DORMANT ARM. Film 8 landed on July 31, so WPT 08 is a film scene and takes
   the `ef` path like every other waypoint; this block is the fallback that
   keeps the branch correct if WPT 08 ever goes static again. Its copy renders
   statically visible in that case, so "fire once on first reveal" cannot stop
   the rescramble by itself. The hold is added ONLY if an IntersectionObserver
   was successfully constructed and is observing, and it is released on the
   first of: decode start, a 6s timeout ARMED AT FIRST APPROACH (never at load
   — a reader takes minutes to reach WPT 08 and a from-load timer would release
   the hold long before he arrives, deleting the effect), or any thrown error. */
#wpt-08 .wpt-content.decode-hold-static {
  opacity: 0 !important;
}

/* ---------- the sound switch ----------
   Bottom-left, in the mono register. Deliberately NOT inside `.route-marker`
   (pointer-events: none, aria-hidden at <=640px) and NOT inside `.rail-left`
   (aria-hidden): an interactive control in either is unreachable. */
.sound-switch {
  position: fixed;
  left: calc(var(--frame-gutter, 0px) + clamp(0.9rem, 2vw, 1.6rem));
  bottom: clamp(0.9rem, 2.4vh, 1.6rem);
  z-index: 46;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.45em 0.7em;
  background: transparent;
  border: 0;
  color: var(--bone-dim);
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0.75;
  transition: opacity 0.3s ease, color 0.3s ease;
}
.sound-switch:hover,
.sound-switch:focus-visible { opacity: 1; color: var(--bone); }
.sound-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: transparent;
  border: 1px solid currentColor;
  transition: background-color 0.3s ease, border-color 0.3s ease;
}
.sound-switch.is-on { color: var(--bone); }
.sound-switch.is-on .sound-dot { background: var(--amber); border-color: var(--amber); }
/* THE SWITCH IS HONEST. While the browser is still waiting for a gesture the
   context is suspended and NO SOUND IS COMING OUT, so the switch must not read
   full-contrast ON. Reduced contrast plus a slow pulse says "armed, not yet
   running" without a second word of copy. A click here RESUMES; it does not
   turn the sound off. */
/* PENDING. No animation: the pulsing dot that shipped first read as a rendering
   fault rather than a state (Isaiah, 2026-07-31: "the sound on button's a
   little glitchy with the mouse"). A steady hollow amber ring at reduced
   contrast says armed-but-not-running without anything appearing to move. */
.sound-switch.is-pending { color: var(--bone-dim); opacity: 0.72; }
.sound-switch.is-pending .sound-dot {
  background: transparent;
  border-color: var(--amber);
  box-shadow: inset 0 0 0 1px rgba(232, 163, 61, 0.35);
}
@media (max-width: 640px) {
  .sound-switch { font-size: 0.55rem; padding: 0.5em 0.6em; }
}

/* ---------- the dev mixer (§13.22) ----------
   Two gates in JS: a ?mixer flag AND a non-production hostname. The styling is
   deliberately ugly. It is a tool, and it must never look shippable. */
.dev-mixer {
  position: fixed; right: 8px; bottom: 8px; z-index: 9999;
  width: 300px; max-height: 82vh; overflow: auto;
  padding: 10px; background: rgba(0,0,0,0.88); color: #E7E2D3;
  font: 11px/1.4 var(--mono); border: 1px solid #444;
}
.dev-mixer h4:first-child { margin-top: 0; }
.dev-mixer h4 { margin: 12px 0 8px; font-size: 11px; letter-spacing: 0.2em;
  color: var(--amber); border-bottom: 1px solid #333; padding-bottom: 4px; }
.dev-mixer label { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
.dev-mixer label span { width: 108px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-mixer label input { flex: 1; }
.dev-mixer label b { width: 34px; text-align: right; font-weight: 400; }
.dev-mixer-btns { display: flex; gap: 4px; margin: 0 0 8px 114px; }
.dev-mixer-btns button {
  flex: 1; padding: 2px; font: 9px var(--mono); letter-spacing: 0.1em;
  background: #1a1a1a; color: #888; border: 1px solid #333; cursor: pointer;
}
.dev-mixer-btns button.on { background: var(--amber); color: #000; }
/* the action bar sticks to the bottom of the panel: with ~26 dials above it,
   COPY must never require scrolling to reach */
.dev-mixer-bar { display: flex; gap: 4px; margin-top: 8px; position: sticky; bottom: 0;
  background: rgba(0, 0, 0, 0.92); padding-top: 6px; }
.dev-mixer-bar button {
  flex: 1; padding: 6px 4px;
  font: 10px var(--mono); letter-spacing: 0.1em;
  background: #1a1a1a; color: #E7E2D3; border: 1px solid #444; cursor: pointer;
}
.dev-mixer-bar button:hover { border-color: var(--amber); color: var(--amber); }
.dev-mixer pre { margin: 8px 0 0; font-size: 9px; white-space: pre-wrap; color: #9c9; }
/* The scrub mixer docks LEFT so it and the audio mixer can be open together. act-one.js
   ALSO sets this inline, on purpose: a cached stylesheet that predates this rule drops
   the override and the panel hides underneath the audio mixer, which reads as "the
   mixer is missing" rather than "the mixer moved". Belt and braces, cheaply. */
.dev-mixer-scrub { right: auto; left: 8px; }

/* ---------- reduced motion ----------
   No decode, no hold, no switch. audio.js returns before it initialises
   anything, so this only has to guarantee the copy is visible and the control
   is not offered. Honest silence, not a broken-looking switch. */
@media (prefers-reduced-motion: reduce) {
  [data-decode].decode-hold,
  #wpt-08 .wpt-content.decode-hold-static { opacity: 1 !important; }
  .sound-switch { display: none; }
}

/* mixer: the timing panel */
.dev-mixer-live {
  font: 10px var(--mono); color: var(--amber); letter-spacing: 0.04em;
  padding: 4px 0; border-bottom: 1px dotted #333; margin-bottom: 4px;
}
.dev-mixer-pick {
  width: 100%; margin: 4px 0; padding: 4px;
  font: 10px var(--mono); background: #1a1a1a; color: #E7E2D3; border: 1px solid #444;
}
