/* ==========================================================================
   Studio Substral — Design & Experience Doctrine v1
   Implementation stylesheet.

   Palette values are fixed rather than eyeballed: every foreground/background
   pairing used for text clears WCAG AA for small text (>= 4.5:1). Recorded
   ratios live in DOCTRINE-IMPLEMENTATION.md so future edits can be checked.
   ========================================================================== */

/* --- Typographic voices -------------------------------------------------- */

@font-face {
  font-family: 'Archivo Substral';
  src: url('../fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Plex Mono Substral';
  src: url('../fonts/plex-mono-400-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Plex Mono Substral';
  src: url('../fonts/plex-mono-500-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- Tokens -------------------------------------------------------------- */

:root {
  /* Materials */
  --substral-black: #11110f;
  --graphite: #1c1b18;
  --graphite-raised: #26241f;
  --mineral: #f0ede5;
  --mineral-sunk: #e4e0d5;

  /* One accent family: oxidized copper patina, tuned per environment */
  --patina: #7fa890;
  --patina-deep: #3d6b57;

  /* Editorial grotesk + technical mono */
  --grotesk: 'Archivo Substral', 'Archivo', 'Helvetica Neue', Helvetica, Arial,
    system-ui, sans-serif;
  --mono: 'Plex Mono Substral', 'IBM Plex Mono', ui-monospace, 'SFMono-Regular',
    Menlo, Consolas, monospace;

  /* Fluid measure. Extreme scale is intentional (doctrine §7), but each size
     is capped so the doctrine's own line breaks survive instead of rewrapping:
     the hero must read LOOK BENEATH / THE SURFACE., not three ragged lines. */
  --t-display: clamp(2.35rem, 10.8vw, 10.25rem);
  --t-closing: clamp(1.7rem, 7.2vw, 6.5rem);
  --t-statement: clamp(1.85rem, 6.4vw, 5.6rem);
  /* A statement set inside a half-width column has half the measure. */
  --t-statement-col: clamp(1.9rem, 4.4vw, 3.5rem);
  --t-section: clamp(1.6rem, 3.6vw, 2.9rem);
  --t-lede: clamp(1.15rem, 1.9vw, 1.65rem);
  --t-body: clamp(1rem, 1.05vw, 1.125rem);
  --t-mono: 0.6875rem;
  --t-mono-lg: 0.8125rem;

  /* Spatial system. Sections breathe; nothing is packed. */
  --gutter: clamp(1.25rem, 4vw, 4.5rem);
  --rail: clamp(0rem, 6vw, 7.5rem);
  --act: clamp(6rem, 11vw + 3rem, 13.5rem);
  --measure: 34rem;
  --shell-max: 96rem;
  /* Height the fixed nav occupies. Sticky stages reserve it so the top plate
     of the specimen is never occluded by the bar. */
  --nav-h: clamp(4.25rem, 2vw + 3.4rem, 5rem);

  /* Motion physics: objects have mass, nothing overshoots (doctrine §13) */
  --ease-weighted: cubic-bezier(0.22, 0.61, 0.21, 1);
  --dur-slow: 1.1s;
  --dur-mid: 620ms;
  --dur-quick: 320ms;

  color-scheme: dark;
}

/* Environment scopes. The narrative moves dark -> mineral -> dark. */

.env-dark {
  --bg: var(--substral-black);
  --ink: var(--mineral);
  --ink-body: #c9c4b6;
  --ink-structural: #8a8578;
  --accent: var(--patina);
  --rule: rgba(240, 237, 229, 0.13);
  --rule-strong: rgba(240, 237, 229, 0.26);
  --surface: var(--graphite);
  --field: rgba(240, 237, 229, 0.045);
  /* Reserved for the instrument's rejection messages. Tuned per environment:
     one value cannot clear AA on both charcoal and mineral. */
  --tone-error: #e6a98c;
}

.env-mineral {
  --bg: var(--mineral);
  --ink: var(--substral-black);
  --ink-body: #3a382f;
  --ink-structural: #5e5a4f;
  --accent: var(--patina-deep);
  --rule: rgba(17, 17, 15, 0.16);
  --rule-strong: rgba(17, 17, 15, 0.34);
  --surface: var(--mineral-sunk);
  --field: rgba(17, 17, 15, 0.04);
  --tone-error: #9c4a1e;
}

/* --- Reset --------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background: var(--substral-black);
  color: var(--mineral);
  font-family: var(--grotesk);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
canvas,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
select {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}

ul,
ol {
  list-style: none;
}

/* Visible, unmistakable focus. Never removed (doctrine §21). */

:focus-visible {
  outline: 2px solid var(--accent, var(--patina));
  outline-offset: 3px;
}

:where(a, button, input, select):focus:not(:focus-visible) {
  outline: none;
}

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100%;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--mineral);
  color: var(--substral-black);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: top var(--dur-quick) var(--ease-weighted);
}

.skip:focus {
  top: 1rem;
}

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Typographic primitives --------------------------------------------- */

.display {
  font-size: var(--t-display);
  font-weight: 600;
  font-stretch: 108%;
  line-height: 0.85;
  letter-spacing: -0.028em;
  text-transform: uppercase;
}

/* The closing principle is three lines rather than two, so it is set a step
   down from the hero to keep the same measure. */
.display--closing {
  font-size: var(--t-closing);
  line-height: 0.88;
}

.statement {
  font-size: var(--t-statement);
  font-weight: 600;
  font-stretch: 105%;
  line-height: 0.92;
  letter-spacing: -0.024em;
  text-transform: uppercase;
  text-wrap: balance;
}

/* For statements set beside the dimensional object rather than across the full
   page. Declared after .statement so it wins on source order. */
.statement--column {
  font-size: var(--t-statement-col);
}

.section-title {
  font-size: var(--t-section);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.018em;
  text-wrap: balance;
}

.lede {
  font-size: var(--t-lede);
  font-weight: 400;
  line-height: 1.34;
  letter-spacing: -0.012em;
  max-width: 24ch;
  color: var(--ink);
}

.prose {
  max-width: var(--measure);
  color: var(--ink-body);
}

.prose + .prose {
  margin-top: 1.1em;
}

/* The mono voice is evidence. It is not used for ordinary prose (§7). */

.mono {
  font-family: var(--mono);
  font-size: var(--t-mono);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-structural);
  font-variant-ligatures: none;
}

.mono--lg {
  font-size: var(--t-mono-lg);
  letter-spacing: 0.11em;
}

.mono--plain {
  text-transform: none;
  letter-spacing: 0.03em;
}

.mono--accent {
  color: var(--accent);
}

.mono--ink {
  color: var(--ink);
}

/* A measurement line: a hairline that reads as a ruling, not decoration. */

.tick {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
}

.tick::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rule);
  transform: translateY(-0.26em);
}

/* --- Shell and grid ----------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.act {
  position: relative;
  background: var(--bg);
  color: var(--ink);
  padding-block: var(--act);
}

.act__marker {
  display: flex;
  align-items: baseline;
  gap: 1.4rem;
  padding-bottom: clamp(2.5rem, 5vw, 4.5rem);
}

.act__marker .mono {
  white-space: nowrap;
}

.act__marker::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rule);
  transform: translateY(-0.3em);
}

/* --- Navigation --------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(1.1rem, 2vw, 1.9rem) var(--gutter);
  /* Opaque at all times. The bar must never let the narrative's large type
     scroll through it, and an IntersectionObserver callback can be delayed by
     rendering work — so legibility cannot depend on one firing. Over Act I it
     is the same colour as the environment behind it and reads as full bleed. */
  background: var(--bg);
  transition: border-color var(--dur-mid) var(--ease-weighted);
  border-bottom: 1px solid transparent;
}

/* Once the hero has passed, a hairline separates the bar from the page. This is
   decoration, so it is safe for it to depend on an observer. */
.nav[data-lifted='true'] {
  border-bottom-color: var(--rule);
}

.wordmark {
  display: inline-flex;
  flex-direction: column;
  gap: 0.35rem;
}

.wordmark__name {
  font-family: var(--grotesk);
  font-size: clamp(1.02rem, 1.5vw, 1.3rem);
  font-weight: 600;
  font-stretch: 112%;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--ink);
}

.wordmark__meta {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-structural);
  line-height: 1;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 1.75vw, 1.9rem);
}

.nav__link {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-structural);
  padding: 0.35rem 0;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-quick) var(--ease-weighted),
    border-color var(--dur-quick) var(--ease-weighted);
}

.nav__link:hover,
.nav__link:focus-visible {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

.nav__link[aria-current='true'] {
  color: var(--ink);
}

@media (max-width: 47.99em) {
  .nav__links {
    display: none;
  }
}

/* --- Buttons and links -------------------------------------------------- */

/* Minimal, strongly typeset, no animated fills (doctrine §22). */

.action {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  padding: 1.05rem 1.5rem;
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--rule-strong);
  cursor: pointer;
  transition: border-color var(--dur-quick) var(--ease-weighted),
    color var(--dur-quick) var(--ease-weighted);
}

.action__arrow {
  transition: transform var(--dur-mid) var(--ease-weighted);
}

.action:hover,
.action:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

.action:hover .action__arrow,
.action:focus-visible .action__arrow {
  transform: translateX(4px);
}

.action[disabled] {
  cursor: progress;
  color: var(--ink-structural);
  border-color: var(--rule);
}

.action--primary {
  border-color: var(--ink);
}

.textlink {
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 0.1em;
  transition: border-color var(--dur-quick) var(--ease-weighted),
    color var(--dur-quick) var(--ease-weighted);
}

.textlink:hover,
.textlink:focus-visible {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ==========================================================================
   ACT I — SURFACE
   ========================================================================== */

/* The object has its own grid territory. On phones it follows metadata and
   precedes the headline; tablet and desktop give text and object separate
   columns. The stage is capped rather than growing into the viewport edges. */
.surface {
  --object-stage-width: min(100%, 28rem);
  --object-stage-height: clamp(12rem, 26svh, 15rem);
  position: relative;
  min-height: 100svh;
  display: grid;
  padding-block: calc(var(--nav-h) + clamp(0.5rem, 1.6vh, 1.5rem))
    clamp(1.5rem, 4vh, 3rem);
}

.surface::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    62% 52% at 50% 42%,
    rgba(127, 168, 144, 0.07),
    transparent 68%
  );
  pointer-events: none;
}

.surface__grid {
  position: relative;
  display: grid;
  grid-template-areas: 'metadata' 'object' 'headline' 'cue';
  grid-template-rows: auto var(--object-stage-height) auto auto;
  gap: clamp(1rem, 2.5svh, 1.5rem);
  align-content: space-between;
}

.surface__object {
  grid-area: object;
  position: relative;
  width: var(--object-stage-width);
  height: var(--object-stage-height);
  justify-self: center;
  align-self: center;
  pointer-events: none;
}

.surface__object .strata { perspective-origin: 50% 52%; }
.surface__object .strata__stack {
  width: min(25rem, 66%);
  transform: rotateX(64deg) rotateZ(-38deg) scale(0.72)
    translate3d(0, 0, calc(var(--lift, 0) * 1px));
}

@media (max-width: 23.5em) {
  .surface { --object-stage-height: 24svh; }
  .surface__grid { gap: 1rem; }
}

@media (min-width: 48em) {
  .surface {
    --object-stage-width: 100%;
    --object-stage-height: min(50svh, 32rem);
  }
  .surface__grid {
    grid-template-areas: 'metadata metadata' 'headline object' 'cue cue';
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    grid-template-rows: auto minmax(var(--object-stage-height), 1fr) auto;
    column-gap: clamp(1.5rem, 3vw, 3rem);
  }
  .surface__head h1 { font-size: clamp(2.35rem, 4.65vw, 5.1rem); }
  .surface__object { justify-self: end; }
}

@media (min-width: 62em) {
  .surface {
    --object-stage-width: min(100%, 42rem);
    --object-stage-height: min(64svh, 36rem);
  }
  .surface__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
}

.surface__eyebrow {
  grid-area: metadata;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1.75rem;
}

@media (max-width: 23.5em) {
  .surface__eyebrow { row-gap: 0.5rem; }
}

/* Copy owns its grid cell; neither type nor CTA crosses the object stage. */
.surface__head {
  grid-area: headline;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.surface__head h1 {
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);
}

.surface__support {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

.surface__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem 1.75rem;
}

.surface__cue {
  grid-area: cue;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-top: 0;
}

.surface__cue-line {
  width: clamp(2.5rem, 7vw, 6rem);
  height: 1px;
  background: linear-gradient(to right, var(--rule-strong), transparent);
}

@media (min-width: 62em) {
  .surface__support {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem;
  }
}

/* ==========================================================================
   THE DIMENSIONAL OBJECT
   Baseline is a CSS 3D composition that requires no WebGL. Three.js replaces
   it when available. Either way the object is decorative: every label the
   narrative depends on lives in the document (doctrine §18, §21).
   ========================================================================== */

.stage {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: clip;
}

/* Hero and exploded containment comes from fitting, not a crop mask. */
.surface__object .stage,
.decomposition__stage .stage { overflow: visible; }

/* The CSS fallback must stay inside the shallow reading band on tablets and
   phones. Its projected substrate otherwise reaches the next layer label. */
@media (max-width: 61.999em) {
  .decomposition__stage .stage[data-webgl='off'] { overflow: hidden; }
}

.stage__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 900ms var(--ease-weighted);
}

.stage[data-webgl='on'] .stage__canvas {
  opacity: 1;
}

.stage[data-webgl='on'] .strata {
  opacity: 0;
  transition: opacity 700ms var(--ease-weighted);
}

/* CSS baseline: six machined plates, stacked in depth. */

.strata {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  perspective: 1400px;
  perspective-origin: 50% 46%;
}

.strata__stack {
  position: relative;
  width: min(34rem, 74%);
  aspect-ratio: 61 / 45;
  transform-style: preserve-3d;
  transform: rotateX(62deg) rotateZ(-38deg) scale(var(--strata-scale, 0.92))
    translate3d(0, 0, calc(var(--lift, 0) * 1px));
}

.plate {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* --i is the position in the stack, 0 at the surface and 6 at performance.
     --sep is the scroll-driven separation in px and --sep-scale reduces the
     layer depth where the frame is shallow. No transform transition: the
     damping lives in the script's interpolation, and doubling it here would
     read as lag rather than mass. */
  transform: translate3d(
    0,
    0,
    calc((2.5 - var(--i)) * var(--sep, 6px) * var(--sep-scale, 1))
  );
}

.plate__face {
  position: absolute;
  inset: 0;
  /* This is the object for anyone without WebGL and for every phone, so it
     carries enough light to read as smoked acrylic rather than a grey plane.
     --face-lift and --face-body vary per layer so the plates are seven
     different materials rather than seven copies. */
  border: 1px solid rgba(240, 237, 229, var(--face-edge, 0.26));
  transition: border-color var(--dur-mid) var(--ease-weighted),
    box-shadow var(--dur-mid) var(--ease-weighted);
  background: linear-gradient(
      148deg,
      rgba(240, 237, 229, var(--face-lift, 0.1)),
      rgba(240, 237, 229, calc(var(--face-lift, 0.1) * 0.24)) 46%,
      rgba(17, 17, 15, 0.16)
    ),
    rgb(var(--face-tone, 30 29 25) / var(--face-body, 0.5));
  box-shadow: inset 0 1px 0 rgba(240, 237, 229, calc(var(--face-lift, 0.1) * 1.4));
}

/* The layer's own drawing, composed from flat gradient rectangles so it costs
   no requests. Each layer draws something different: a page, a grid, marks, an
   index, a flow, a structure, a trace. */
.plate__face::before {
  content: '';
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  opacity: var(--art-opacity, 0.9);
}

/* 06 DESIGN — the precision surface: masthead, headline, action, media, copy. */
.plate[data-art='design'] {
  /* Precision surface: crispest edge, brightest arris, densest markings. */
  --face-lift: 0.17;
  --face-body: 0.4;
  --face-edge: 0.46;
  --edge-h: 3px;
  --edge-tint: 0.5;
  --art-opacity: 0.95;
}
.plate[data-art='design'] .plate__face::before {
  background-image: linear-gradient(rgba(240, 237, 229, 0.82), rgba(240, 237, 229, 0.82)),
    repeating-linear-gradient(90deg, rgba(240, 237, 229, 0.34) 0 22%, transparent 22% 34%),
    linear-gradient(rgba(240, 237, 229, 0.5), rgba(240, 237, 229, 0.5)),
    linear-gradient(rgba(240, 237, 229, 0.2), rgba(240, 237, 229, 0.2)),
    linear-gradient(rgba(240, 237, 229, 0.86), rgba(240, 237, 229, 0.86)),
    linear-gradient(rgba(240, 237, 229, 0.86), rgba(240, 237, 229, 0.86)),
    repeating-linear-gradient(180deg, rgba(240, 237, 229, 0.26) 0 2px, transparent 2px 9px),
    linear-gradient(rgba(127, 168, 144, 0.5), rgba(127, 168, 144, 0.5)),
    linear-gradient(152deg, rgba(240, 237, 229, 0.17), rgba(240, 237, 229, 0.02)),
    linear-gradient(rgba(240, 237, 229, 0.26), rgba(240, 237, 229, 0.26)),
    linear-gradient(rgba(240, 237, 229, 0.18), rgba(240, 237, 229, 0.18)),
    repeating-linear-gradient(180deg, rgba(240, 237, 229, 0.2) 0 2px, transparent 2px 8px),
    linear-gradient(rgba(240, 237, 229, 0.2), rgba(240, 237, 229, 0.2));
  background-size: 11% 3%, 30% 2%, 86% 1px, 20% 4.4%, 48% 7%, 34% 7%, 27% 8%,
    15% 4.6%, 37% 33%, 37% 1px, 86% 1px, 86% 14%, 86% 1px;
  background-position: 7% 7.5%, 48% 8.6%, 7% 15%, 74% 6.6%, 7% 22%, 7% 31%,
    7% 43%, 7% 56%, 57% 20%, 57% 42%, 7% 68%, 7% 74%, 7% 92%;
}

/* 05 TRUST — a seal, a credential plate, a verification ledger. */
.plate[data-art='trust'] {
  /* Warm smoked glass: the thickest of the glass layers. */
  --face-lift: 0.125;
  --face-tone: 38 35 29;
  --face-body: 0.46;
  --face-edge: 0.34;
  --edge-h: 5px;
  --edge-tint: 0.4;
  --art-opacity: 0.8;
}
.plate[data-art='trust'] .plate__face::before {
  background-image: radial-gradient(
      closest-side circle,
      transparent 0 62%,
      rgba(240, 237, 229, 0.44) 62% 70%,
      transparent 70%
    ),
    radial-gradient(
      closest-side circle,
      transparent 0 36%,
      rgba(240, 237, 229, 0.22) 36% 42%,
      transparent 42%
    ),
    linear-gradient(rgba(240, 237, 229, 0.05), rgba(240, 237, 229, 0.05)),
    linear-gradient(rgba(240, 237, 229, 0.5), rgba(240, 237, 229, 0.5)),
    repeating-linear-gradient(180deg, rgba(240, 237, 229, 0.24) 0 2px, transparent 2px 13%),
    linear-gradient(rgba(240, 237, 229, 0.3), rgba(240, 237, 229, 0.3)),
    linear-gradient(rgba(127, 168, 144, 0.5), rgba(127, 168, 144, 0.5));
  background-size: 18% 24%, 18% 24%, 30% 22%, 14% 3%, 74% 32%, 80% 1px, 6% 2.4%;
  background-position: 9% 18%, 9% 18%, 52% 17%, 55% 22%, 9% 58%, 9% 52%, 78% 26%;
}

/* 04 SEARCH — a hierarchy on the left, an index on the right. */
.plate[data-art='search'] {
  /* Etched architectural glass: the clearest body, the brightest marks. */
  --face-lift: 0.07;
  --face-body: 0.28;
  --face-edge: 0.4;
  --edge-h: 3px;
  --edge-tint: 0.46;
  --art-opacity: 0.88;
}
.plate[data-art='search'] .plate__face::before {
  background-image: linear-gradient(rgba(240, 237, 229, 0.3), rgba(240, 237, 229, 0.3)),
    linear-gradient(rgba(240, 237, 229, 0.24), rgba(240, 237, 229, 0.24)),
    linear-gradient(rgba(240, 237, 229, 0.24), rgba(240, 237, 229, 0.24)),
    linear-gradient(rgba(240, 237, 229, 0.24), rgba(240, 237, 229, 0.24)),
    linear-gradient(rgba(240, 237, 229, 0.42), rgba(240, 237, 229, 0.42)),
    linear-gradient(rgba(240, 237, 229, 0.36), rgba(240, 237, 229, 0.36)),
    linear-gradient(rgba(240, 237, 229, 0.28), rgba(240, 237, 229, 0.28)),
    linear-gradient(rgba(127, 168, 144, 0.5), rgba(127, 168, 144, 0.5)),
    linear-gradient(rgba(240, 237, 229, 0.28), rgba(240, 237, 229, 0.28)),
    repeating-linear-gradient(90deg, rgba(240, 237, 229, 0.2) 0 2px, transparent 2px 9px);
  background-size: 1px 52%, 11% 1px, 11% 1px, 11% 1px, 16% 2.4%, 22% 2.4%, 13% 2.4%,
    19% 2.4%, 16% 2.4%, 30% 30%;
  background-position: 13% 24%, 13% 28%, 13% 50%, 13% 72%, 48% 22%, 48% 34%, 52% 46%,
    48% 58%, 48% 70%, 68% 22%;
}

/* 03 CONVERSION — nodes, one converging path, one that stops. */
.plate[data-art='conversion'] {
  /* Smoked acrylic: dark, deep, polished, sparse marks. */
  --face-lift: 0.09;
  --face-body: 0.62;
  --face-edge: 0.3;
  --edge-h: 4px;
  --edge-tint: 0.42;
  --art-opacity: 0.7;
}
.plate[data-art='conversion'] .plate__face::before {
  background-image: radial-gradient(
      closest-side circle,
      transparent 0 52%,
      rgba(240, 237, 229, 0.42) 52% 66%,
      transparent 66%
    ),
    linear-gradient(26deg, transparent 49.4%, rgba(240, 237, 229, 0.26) 49.4% 50.6%, transparent 50.6%),
    linear-gradient(-26deg, transparent 49.4%, rgba(240, 237, 229, 0.26) 49.4% 50.6%, transparent 50.6%),
    linear-gradient(rgba(127, 168, 144, 0.55), rgba(127, 168, 144, 0.55)),
    repeating-linear-gradient(122deg, rgba(240, 237, 229, 0.22) 0 5px, transparent 5px 12px);
  background-size: 8% 11%, 44% 30%, 44% 30%, 9% 9%, 22% 22%;
  background-position: 9% 20%, 14% 22%, 14% 48%, 82% 45%, 50% 70%;
  background-repeat: repeat-y, no-repeat, no-repeat, no-repeat, no-repeat;
}

/* 02 ACCESSIBILITY — semantic regions and focus order, in frosted polymer. */
.plate[data-art='accessibility'] {
  /* Frosted polymer: milky and light, soft edge, diffuse markings. */
  --face-lift: 0.28;
  --face-tone: 150 146 134;
  --face-body: 0.46;
  --face-edge: 0.16;
  --edge-h: 5px;
  --edge-tint: 0.18;
  --art-opacity: 0.4;
}
.plate[data-art='accessibility'] .plate__face::before {
  background-image: linear-gradient(rgba(240, 237, 229, 0.07), rgba(240, 237, 229, 0.07)),
    linear-gradient(rgba(240, 237, 229, 0.1), rgba(240, 237, 229, 0.1)),
    linear-gradient(rgba(240, 237, 229, 0.06), rgba(240, 237, 229, 0.06)),
    linear-gradient(rgba(240, 237, 229, 0.05), rgba(240, 237, 229, 0.05)),
    repeating-linear-gradient(90deg, rgba(240, 237, 229, 0.08) 0 1px, transparent 1px 6%),
    repeating-linear-gradient(180deg, rgba(240, 237, 229, 0.06) 0 1px, transparent 1px 8%),
    repeating-linear-gradient(90deg, rgba(127, 168, 144, 0.42) 0 5px, transparent 5px 11px);
  background-size: 86% 10%, 54% 42%, 28% 42%, 86% 22%, 86% 82%, 86% 82%, 74% 1px;
  background-position: 7% 8%, 7% 22%, 65% 22%, 7% 68%, 7% 9%, 7% 9%, 7% 14%;
}

/* 01 PERFORMANCE — a request waterfall over a measured axis. */
.plate[data-art='performance'] {
  /* Graphite composite: darkest, densest, widest matte edge. */
  --face-lift: 0.045;
  --face-tone: 22 21 19;
  --face-body: 0.85;
  --face-edge: 0.26;
  --edge-h: 7px;
  --edge-tint: 0.24;
  --art-opacity: 0.62;
}
.plate[data-art='performance'] .plate__face::before {
  background-image: linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(127, 168, 144, 0.55), rgba(127, 168, 144, 0.55)),
    linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(240, 237, 229, 0.32), rgba(240, 237, 229, 0.32)),
    linear-gradient(rgba(240, 237, 229, 0.44), rgba(240, 237, 229, 0.44)),
    repeating-linear-gradient(90deg, rgba(240, 237, 229, 0.26) 0 1px, transparent 1px 4.3%);
  background-size: 14% 3%, 10% 3%, 30% 3%, 8% 3%, 22% 3%, 12% 3%, 26% 3%, 86% 1px, 86% 3%;
  background-position: 7% 16%, 12% 24%, 16% 32%, 24% 40%, 28% 48%, 38% 56%, 44% 64%,
    7% 76%, 7% 78%;
}

.plate[data-active='true'] .plate__face {
  border-color: rgba(127, 168, 144, 0.68);
  box-shadow: inset 0 1px 0 rgba(127, 168, 144, 0.34),
    0 0 0 1px rgba(127, 168, 144, 0.18);
}

/* The machined arris: the glint along the plate's thickness. */
.plate__edge {
  position: absolute;
  inset: auto 0 0 0;
  height: var(--edge-h, 3px);
  background: linear-gradient(
    to right,
    rgba(240, 237, 229, calc(var(--edge-tint, 0.42) * 0.14)),
    rgba(240, 237, 229, var(--edge-tint, 0.42)),
    rgba(240, 237, 229, calc(var(--edge-tint, 0.42) * 0.14))
  );
  transform: translateZ(calc(var(--edge-h, 3px) * -1));
}

/* ==========================================================================
   THE SUBSTRATE

   The approved procedural stone, baked for the CSS fallback at its two fixed
   viewing angles. Its depth anchor and the layers above it are unchanged.
   ========================================================================== */

.plinth {
  position: absolute;
  inset: -26%;
  transform-style: preserve-3d;
  transform: translate3d(
    0,
    0,
    calc((2.5 - 5.5) * var(--sep, 6px) * var(--sep-scale, 1) - 0.55rem)
  );
}

/* A transparent bake of the same procedural mesh used by WebGL. Counter the
   stack's rotation so the rendered stone retains its volume, while the plinth
   keeps the existing depth anchor, separation and responsive scale. The bake
   covers 6.4 scene units; 1.52 / 2.12 preserves the previous base footprint.
   No GPU work or dimensional bundle is needed for this baseline. */
.plinth__rock {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 98.979%; /* 6.4 / (PLATE_W 3.05 × substrate width ratio 2.12) */
  aspect-ratio: 160 / 77;
  background: url('../object/substrate-62.webp') center / contain no-repeat;
  transform-origin: 0 0;
  /* The planed plateau's origin inside the transparent 640 × 308 export. */
  transform: rotateZ(38deg) rotateX(-62deg) translate(-42.1875%, -20.77922%);
}

.surface__object .plinth__rock {
  background-image: url('../object/substrate-64.webp');
  transform: rotateZ(38deg) rotateX(-64deg) translate(-42.1875%, -20.77922%);
}

/* ==========================================================================
   ACT II — DECOMPOSITION
   ========================================================================== */

.decomposition {
  position: relative;
}

.decomposition__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}

/* On one column the stage is a band pinned under the nav and the layers read
   beneath it, so it has to sit above them and be opaque — otherwise the
   specimen and the prose occupy the same pixels. The band is kept shallow so
   the reading area is not halved (doctrine §17: mobile usability first). */
.decomposition__stage {
  position: sticky;
  top: 0;
  z-index: 3;
  height: calc(28svh + var(--nav-h));
  padding-top: var(--nav-h);
  padding-bottom: 0.75rem;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}

.layer {
  scroll-margin-top: calc(28svh + var(--nav-h));
}

/* The pinned bands are shallow, so the specimen is drawn smaller and with less
   depth between layers. This is the doctrine's reduced layer depth for small
   screens (§17), not an accident of scaling the desktop composition down. */
.decomposition__stage .stage,
.reconstruction__stage .stage {
  --strata-scale: 0.54;
  --sep-scale: 0.52;
}

@media (min-width: 62em) {
  .decomposition__stage .stage,
  .reconstruction__stage .stage {
    --strata-scale: 0.92;
    --sep-scale: 1;
  }
}

/* The stage readout names what is visible: the layer under examination and,
   secondary to it, the foundation. The same engineering-label language as the
   six chapters — the block explains itself, this only annotates it. */
.decomposition__readout {
  position: absolute;
  left: var(--gutter);
  bottom: 1rem;
  display: grid;
  gap: 0.35rem;
  pointer-events: none;
}

.decomposition__readout p {
  display: flex;
  gap: 1.25rem;
}

.decomposition__readout-sub {
  opacity: 0.45;
}

.layers {
  position: relative;
  z-index: 2;
}

.layer {
  padding-block: clamp(3.5rem, 9vh, 7rem);
  border-top: 1px solid var(--rule);
  transition: opacity var(--dur-mid) var(--ease-weighted);
}

.layer:first-child {
  border-top: 0;
}

.layer__index {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}

.layer__num {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  letter-spacing: 0.1em;
  color: var(--ink-structural);
  transition: color var(--dur-mid) var(--ease-weighted);
}

.layer[data-active='true'] .layer__num {
  color: var(--accent);
}

.layer__name {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink);
}

.layer__question {
  max-width: 30ch;
  margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
}

.layer__body {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: minmax(0, 1fr);
}

/* Evidence manifest: what this layer actually produces. Real measurable
   fields only — no invented values (doctrine §16). */

.manifest {
  display: grid;
  gap: 0.55rem;
  align-content: start;
  padding-top: 0.3rem;
}

.manifest dt {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.manifest dd {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.06em;
  line-height: 1.75;
  color: var(--ink-structural);
  text-transform: none;
}

@media (min-width: 62em) {
  .decomposition__layout {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 6rem);
    align-items: start;
  }

  /* Two columns: the stage no longer covers the reading column, so it returns
     to full height and stops needing to sit on top. */
  .decomposition__stage {
    z-index: 1;
    height: 100svh;
    padding-top: var(--nav-h);
    border-bottom: 0;
    border-right: 1px solid var(--rule);
  }

  .layer {
    scroll-margin-top: var(--nav-h);
  }

  .decomposition__readout {
    left: 0;
    bottom: 2rem;
  }

  .layer {
    min-height: 62svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-right: var(--gutter);
  }

  .layer__body {
    grid-template-columns: minmax(0, 1fr) minmax(0, 14rem);
    gap: 3rem;
  }
}

/* The ordering claim. Design is last, and the site says why. */

.ordering {
  border-top: 1px solid var(--rule-strong);
  padding-top: clamp(2rem, 4vw, 3rem);
  margin-top: clamp(2rem, 5vw, 4rem);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 55em) {
  .ordering {
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 5rem);
  }
}

/* A philosophy line, set as a rule-anchored pull statement, not a card. The
   statement needs space around it to land, but a full act's worth of margin on
   top of its own padding turned a held beat into a wait. */
.principle-shell {
  margin-top: clamp(2.5rem, 5vw, 6rem);
}

.principle {
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule);
  padding-block: clamp(3rem, 8vw, 6rem);
  margin-block: 0;
}

/* The measure is set on the statement itself, not the blockquote: `ch`
   resolves against the element's own font size, and on the wrapper it would
   compute from the inherited body size and crush the large type. */
.principle blockquote .statement {
  max-width: 22ch;
}

.principle__mark {
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

/* ==========================================================================
   ACT III — DIAGNOSIS
   ========================================================================== */

/* The dark-to-mineral turn is a cut section of the substrate, not a fade: the
   dark environment stops at a machined arris, you pass through a band of stone,
   and the paper begins at another one. Everything else on this site is a crisp
   physical edge, and a soft gradient wipe broke that illusion. */

/* The turn is itself a pause, so the acts either side of it do not also need
   their full breathing room against it — that stacked up as a stretch of
   nothing before the next content arrived. */
.turn + .act {
  padding-top: clamp(2.5rem, 4vw, 4.5rem);
}

.act:has(+ .turn) {
  padding-bottom: clamp(2.5rem, 4vw, 4.5rem);
}

.turn {
  height: clamp(2.5rem, 4.5vh, 3.75rem);
  background: radial-gradient(
      120% 240% at 24% 12%,
      rgba(255, 250, 238, 0.15),
      transparent 64%
    ),
    radial-gradient(60% 180% at 74% 82%, rgba(17, 17, 15, 0.3), transparent 70%),
    radial-gradient(40% 160% at 46% 32%, rgba(255, 250, 238, 0.06), transparent 72%),
    linear-gradient(172deg, #615c53, #4b473f 56%, #3a362f);
  box-shadow: inset 0 1px 0 rgba(255, 250, 238, 0.26),
    inset 0 -1px 0 rgba(17, 17, 15, 0.5);
}

.diagnosis__head {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 1fr);
  padding-bottom: clamp(3rem, 7vw, 5.5rem);
}

@media (min-width: 62em) {
  /* The statement takes the full measure so WE DIAGNOSE / BEFORE WE DESIGN.
     stays two lines; the supporting prose drops into the right column beneath
     it, which also keeps the composition asymmetric. */
  .diagnosis__head {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(3rem, 7vw, 7rem);
    row-gap: clamp(2rem, 4vw, 3.25rem);
  }

  .diagnosis__head h2 {
    grid-column: 1 / -1;
  }

  .diagnosis__head .prose {
    grid-column: 2;
  }
}

/* The method narrows as evidence becomes a recommendation. These are not three
   equal service cards: each pass exposes more of the datum at the left and
   removes unsupported surface area from the right. */

.movements {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule-strong);
}

.movement {
  --cut: 0rem;
  position: relative;
  width: calc(100% - var(--cut));
  margin-left: var(--cut);
  padding: clamp(1.8rem, 3.5vw, 2.6rem) clamp(1rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--rule);
  display: grid;
  gap: 0.9rem clamp(1.5rem, 4vw, 4rem);
  align-content: start;
  background: linear-gradient(90deg, var(--field), transparent 42%);
}

.movement:nth-child(2) {
  --cut: clamp(0.85rem, 3vw, 3rem);
}

.movement:nth-child(3) {
  --cut: clamp(1.7rem, 6vw, 6rem);
}

.movement::before {
  content: '';
  position: absolute;
  inset: -1px auto auto 0;
  width: clamp(1.5rem, 4vw, 4rem);
  height: 1px;
  background: var(--accent);
}

.movement__step {
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
}

.movement h3 {
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.1;
}

@media (min-width: 55em) {
  .movement {
    grid-template-columns: minmax(7rem, 0.35fr) minmax(14rem, 0.72fr) minmax(0, 1.25fr);
    align-items: baseline;
  }
}

/* The four conclusions. These are the diagnosis classes the assessment
   engine actually emits — not marketing categories. */

.conclusions {
  margin-top: clamp(3.5rem, 8vw, 6.5rem);
}

.conclusion {
  display: grid;
  gap: 0.75rem 2.5rem;
  grid-template-columns: minmax(0, 1fr);
  padding-block: clamp(1.6rem, 3.2vw, 2.4rem);
  border-top: 1px solid var(--rule);
}

.conclusion:last-child {
  border-bottom: 1px solid var(--rule);
}

.conclusion__class {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.conclusion__class::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  background: var(--accent);
  transform: translateY(-0.1em);
}

.conclusion p {
  color: var(--ink-body);
  max-width: 52ch;
}

@media (min-width: 55em) {
  .conclusion {
    grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
    align-items: baseline;
  }
}

.willingness {
  margin-top: clamp(3rem, 7vw, 5.5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--rule-strong);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 55em) {
  .willingness {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 5rem);
    align-items: start;
  }
}

/* ==========================================================================
   ACT IV — PROTOCOL / ASSESSMENT INSTRUMENT
   The evidence protocol is stated before the closing instrument appears.
   ========================================================================== */

.protocol {
  background: var(--bg);
}

.assessment__head {
  max-width: 46rem;
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

.instrument {
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--rule);
  padding-block: clamp(1.75rem, 4vw, 3rem);
}

.instrument__row {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
}

.instrument__field {
  display: grid;
  gap: 0.85rem;
}

.instrument__input {
  width: 100%;
  font-family: var(--grotesk);
  font-size: clamp(1.6rem, 5.2vw, 3.4rem);
  font-weight: 500;
  font-stretch: 104%;
  letter-spacing: -0.022em;
  line-height: 1.05;
  color: var(--ink);
  background: transparent;
  border-bottom: 1px solid var(--rule-strong);
  padding: 0.3rem 0 0.6rem;
  transition: border-color var(--dur-quick) var(--ease-weighted);
}

.instrument__input::placeholder {
  color: var(--ink-structural);
  opacity: 1;
}

/* Focus thickens the rule as well as recolouring it, so the state does not
   depend on colour perception. The global focus-visible outline is left
   intact rather than replaced (doctrine §21). */
.instrument__input:focus {
  border-bottom-width: 2px;
  border-bottom-color: var(--accent);
  padding-bottom: calc(0.6rem - 1px);
}

.instrument:focus-within {
  border-top-color: var(--accent);
}

.instrument__secondary {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: minmax(0, 1fr);
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  align-items: end;
}

.field {
  display: grid;
  gap: 0.6rem;
}

.field__input {
  width: 100%;
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  letter-spacing: 0.04em;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--rule);
  padding: 0.85rem 0.95rem;
  transition: border-color var(--dur-quick) var(--ease-weighted);
}

.field__input:focus {
  border-color: var(--accent);
}

.field--hidden {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

@media (min-width: 48em) {
  .instrument__row {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: clamp(1.5rem, 4vw, 3rem);
  }

  .instrument__secondary {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 3vw, 2.5rem);
  }
}

.instrument__status {
  margin-top: 1.5rem;
  min-height: 1.5rem;
  max-width: 54ch;
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  letter-spacing: 0.04em;
  line-height: 1.65;
  color: var(--ink-structural);
  text-transform: none;
}

.instrument__status[data-tone='error'] {
  color: var(--tone-error);
}

.instrument__status[data-tone='ok'] {
  color: var(--accent);
}

/* Evidence classes, stated before any result exists. */

.taxonomy {
  margin-top: clamp(3.5rem, 8vw, 6rem);
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule-strong);
}

.taxonomy__item {
  --exposure: 0rem;
  position: relative;
  width: calc(100% - var(--exposure));
  margin-left: var(--exposure);
  padding: clamp(1.4rem, 2.6vw, 2rem) clamp(1rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--rule);
  display: grid;
  gap: 0.6rem clamp(1.5rem, 4vw, 4rem);
  align-content: start;
}

.taxonomy__item:nth-child(2) {
  --exposure: clamp(0.6rem, 2vw, 2rem);
}

.taxonomy__item:nth-child(3) {
  --exposure: clamp(1.2rem, 4vw, 4rem);
}

.taxonomy__item:nth-child(4) {
  --exposure: clamp(1.8rem, 6vw, 6rem);
}

.taxonomy__item::before {
  content: '';
  position: absolute;
  inset: -1px auto auto 0;
  width: clamp(1.25rem, 3vw, 3rem);
  height: 1px;
  background: var(--accent);
}

.taxonomy__class {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--accent);
}

.taxonomy__item p {
  color: var(--ink-body);
  font-size: 1rem;
}

@media (min-width: 55em) {
  .taxonomy__item {
    grid-template-columns: minmax(10rem, 0.42fr) minmax(0, 1fr);
    align-items: baseline;
  }
}

/* The four report sections. */

.report {
  margin-top: clamp(3.5rem, 8vw, 6rem);
  display: grid;
  gap: 0;
}

.report__section {
  display: grid;
  gap: 0.85rem 2.5rem;
  grid-template-columns: minmax(0, 1fr);
  padding-block: clamp(1.6rem, 3vw, 2.3rem);
  border-top: 1px solid var(--rule);
}

.report__section:last-child {
  border-bottom: 1px solid var(--rule);
}

.report__label {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink);
}

.report__section p {
  color: var(--ink-body);
  max-width: 56ch;
}

@media (min-width: 55em) {
  .report__section {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
    align-items: baseline;
  }
}

/* What the instrument will never produce. Stated plainly (doctrine §16). */

.refusals {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.5rem);
  border-top: 1px solid var(--rule-strong);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  grid-template-columns: minmax(0, 1fr);
}

.refusals ul {
  display: grid;
  gap: 0.7rem;
}

.refusals li {
  display: grid;
  grid-template-columns: 1.25rem minmax(0, 1fr);
  gap: 0.5rem;
  color: var(--ink-body);
  font-size: 1rem;
}

.refusals li::before {
  content: '\2014';
  color: var(--ink-structural);
}

@media (min-width: 55em) {
  .refusals {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 4rem);
  }
}

/* ==========================================================================
   ACT V — WORK
   Editorial stories. No portfolio grid (doctrine §14, Act V).
   ========================================================================== */

.work__head {
  padding-bottom: clamp(3rem, 6vw, 5rem);
}

.study {
  border-top: 1px solid var(--rule-strong);
  padding-top: clamp(2.5rem, 5vw, 4rem);
}

.study + .study {
  margin-top: clamp(4rem, 9vw, 7rem);
}

.study__head {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: minmax(0, 1fr);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.study__meta {
  display: grid;
  gap: 0.5rem;
  align-content: start;
}

.study__title {
  font-size: clamp(2rem, 5vw, 4rem);
  font-weight: 600;
  font-stretch: 104%;
  line-height: 0.95;
  letter-spacing: -0.024em;
  text-transform: uppercase;
}

.study__thesis {
  max-width: 48ch;
  margin-top: 1.35rem;
  color: var(--ink-body);
  font-size: clamp(1rem, 1.45vw, 1.2rem);
}

.study__ledger {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.study__ledger > div {
  display: grid;
  gap: 0.45rem;
  align-content: start;
  padding-block: 1.25rem;
  border-bottom: 1px solid var(--rule);
}

.study__ledger > div:last-child {
  border-bottom: 0;
}

.study__ledger dt {
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--accent);
}

.study__ledger dd {
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.5;
}

@media (min-width: 48em) {
  .study__ledger {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .study__ledger > div {
    min-height: 6.8rem;
    padding: 1.25rem clamp(1rem, 2.4vw, 1.8rem);
    border-right: 1px solid var(--rule);
    border-bottom: 0;
  }

  .study__ledger > div:first-child {
    padding-left: 0;
  }

  .study__ledger > div:last-child {
    padding-right: 0;
    border-right: 0;
  }
}

@media (min-width: 62em) {
  .study__head {
    grid-template-columns: minmax(0, 1fr) minmax(0, 15rem);
    gap: clamp(2rem, 6vw, 5rem);
    align-items: end;
  }
}

/* The delivered page is held inside an evidence cut: image on one side,
   observed facts on the exposed dark edge. It is neither a browser mockup nor
   an unexplained portfolio image. */

.study__plate {
  position: relative;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.study__capture {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  overflow: hidden;
  background: var(--substral-black);
  clip-path: polygon(0 0, calc(100% - 2.5rem) 0, 100% 2.5rem, 100% 100%, 0 100%);
}

.study__plate img {
  width: 100%;
  height: auto;
  display: block;
}

.study__annotations {
  display: grid;
  align-content: end;
  padding: clamp(1.25rem, 3vw, 2.25rem);
  color: var(--mineral);
  border-top: 1px solid rgba(240, 237, 229, 0.26);
}

.study__annotations li {
  display: grid;
  gap: 0.4rem;
  padding-block: clamp(0.9rem, 2vw, 1.3rem);
  border-bottom: 1px solid rgba(240, 237, 229, 0.13);
  color: #c9c4b6;
  font-size: 0.9375rem;
  line-height: 1.45;
}

.study__annotations li:first-child {
  border-top: 1px solid rgba(240, 237, 229, 0.13);
}

.study__annotations span {
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--patina);
}

.study__caption {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin-top: 0.85rem;
}

@media (min-width: 55em) {
  .study__capture {
    grid-template-columns: minmax(0, 1fr) minmax(15rem, 0.3fr);
  }

  .study__plate img {
    height: 100%;
    object-fit: cover;
    object-position: center;
  }

  .study__annotations {
    border-top: 0;
    border-left: 1px solid rgba(240, 237, 229, 0.26);
  }
}

.study__movements {
  display: grid;
  gap: 0;
}

.study__movement {
  display: grid;
  gap: 0.85rem 2.5rem;
  grid-template-columns: minmax(0, 1fr);
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--rule);
}

.study__movement:last-child {
  border-bottom: 1px solid var(--rule);
}

.study__movement h3 {
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--ink);
}

.study__movement p {
  color: var(--ink-body);
  max-width: 58ch;
}

.study__movement p + p {
  margin-top: 0.9em;
}

@media (min-width: 55em) {
  .study__movement {
    grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
    align-items: baseline;
  }
}

.publication {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.5rem);
  border-top: 1px solid var(--rule-strong);
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 55em) {
  .publication {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 4rem);
  }
}

/* ==========================================================================
   ACT VI — RECONSTRUCTION
   ========================================================================== */

/* The same seam, lit from the other side. */
.turn--back {
  background: radial-gradient(
      120% 240% at 76% 88%,
      rgba(255, 250, 238, 0.12),
      transparent 64%
    ),
    radial-gradient(60% 180% at 26% 16%, rgba(17, 17, 15, 0.34), transparent 70%),
    radial-gradient(40% 160% at 54% 62%, rgba(255, 250, 238, 0.05), transparent 72%),
    linear-gradient(8deg, #5a554d, #46423b 54%, #34312b);
  box-shadow: inset 0 1px 0 rgba(17, 17, 15, 0.45),
    inset 0 -1px 0 rgba(255, 250, 238, 0.14);
}

.reconstruction {
  position: relative;
}

/* The commercial scope is a ruled ledger, not a tier table. Assessment,
   remediation and rebuild are three possible responses to one diagnosis. */
.engagement {
  scroll-margin-top: calc(var(--nav-h) + 1.5rem);
  padding-bottom: clamp(4rem, 9vw, 8rem);
}

.engagement__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.75rem, 4vw, 3rem);
  padding-bottom: clamp(3rem, 7vw, 5rem);
}

.engagement__tracks {
  display: grid;
  border-top: 1px solid var(--rule-strong);
}

.engagement__track {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
  padding-block: clamp(1.8rem, 4vw, 2.8rem);
  border-bottom: 1px solid var(--rule);
}

.engagement__mode,
.engagement__copy {
  display: grid;
  align-content: start;
  gap: 1rem;
}

.engagement__track h3 {
  max-width: 15ch;
  font-size: clamp(1.35rem, 2.2vw, 1.9rem);
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.05;
}

.engagement__copy > p:first-child {
  max-width: 43ch;
  color: var(--ink-body);
}

.engagement__deliverable {
  align-self: end;
  padding-top: 1rem;
  font-size: 0.75rem;
  color: var(--ink-structural);
  line-height: 1.7;
}

.engagement__index {
  font-size: 0.75rem;
}

.intervention {
  position: relative;
  height: clamp(7rem, 18vw, 9rem);
  overflow: hidden;
  border-inline: 1px solid var(--rule);
}

.intervention::before {
  content: '';
  position: absolute;
  inset: 12% 12% 12% auto;
  width: 1px;
  background: var(--rule-strong);
}

.intervention span {
  --shift: 0rem;
  position: absolute;
  left: 10%;
  right: 10%;
  top: 50%;
  height: 0.46rem;
  border: 1px solid var(--rule-strong);
  background: var(--graphite-raised);
  box-shadow: 0 0.24rem 0 rgba(0, 0, 0, 0.28);
  transform: translate3d(var(--shift), calc(var(--layer) * 0.78rem), 0);
}

.intervention span:nth-child(1) { --layer: -2.5; }
.intervention span:nth-child(2) { --layer: -1.5; }
.intervention span:nth-child(3) { --layer: -0.5; }
.intervention span:nth-child(4) { --layer: 0.5; }
.intervention span:nth-child(5) { --layer: 1.5; }
.intervention span:nth-child(6) { --layer: 2.5; }

/* Assessment exposes the stack so each layer can be inspected separately. */
.intervention--expose span:nth-child(1) { --shift: -0.75rem; }
.intervention--expose span:nth-child(2) { --shift: -0.45rem; }
.intervention--expose span:nth-child(5) { --shift: 0.45rem; }
.intervention--expose span:nth-child(6) { --shift: 0.75rem; }

.intervention--expose::after {
  content: '';
  position: absolute;
  inset: 22% auto 22% 7%;
  width: 0.45rem;
  border-block: 1px solid var(--accent);
  border-left: 1px solid var(--accent);
}

/* Remediation leaves the system intact and marks only the bounded repair. */
.intervention--repair span {
  transform: translate3d(0, calc(var(--layer) * 0.55rem), 0);
}

.intervention--repair span:nth-child(3) {
  background: linear-gradient(
    90deg,
    var(--graphite-raised) 0 43%,
    var(--patina) 43% 54%,
    var(--graphite-raised) 54%
  );
  border-color: rgba(127, 168, 144, 0.58);
}

/* Rebuild shows the same six planes resolving onto one datum. */
.intervention--rebuild span {
  background: linear-gradient(
    90deg,
    var(--graphite-raised) 0 29%,
    transparent 29% 33%,
    var(--graphite-raised) 33% 68%,
    transparent 68% 72%,
    var(--graphite-raised) 72%
  );
}

.intervention--rebuild span:nth-child(odd) { --shift: -0.35rem; }
.intervention--rebuild span:nth-child(even) { --shift: 0.35rem; }

.intervention--rebuild::after {
  content: '';
  position: absolute;
  inset: 16% 8% 16% auto;
  width: 0.35rem;
  border-block: 1px solid var(--accent);
  border-right: 1px solid var(--accent);
}

.engagement__fit {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem clamp(2rem, 5vw, 5rem);
  margin-top: clamp(3rem, 7vw, 5.5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--rule-strong);
}

@media (min-width: 55em) {
  .engagement__head {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.8fr);
    align-items: end;
  }

  .engagement__track {
    grid-template-columns: minmax(10rem, 0.55fr) minmax(14rem, 0.8fr) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
    min-height: 15rem;
  }

  .intervention {
    height: 9rem;
  }

  .engagement__fit {
    grid-template-columns: minmax(0, 10rem) minmax(0, 1fr) minmax(0, 0.75fr);
    align-items: start;
  }
}

.reconstruction__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.reconstruction__stage {
  position: sticky;
  top: 0;
  z-index: 3;
  height: calc(30svh + var(--nav-h));
  padding-top: var(--nav-h);
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
}

.converge {
  position: relative;
  z-index: 2;
  padding-top: clamp(3rem, 7vw, 5rem);
}

/* Six names that align as the object assembles. */

.converge__list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
  /* Belt and braces: the offsets below cannot widen the document, but clipping
     here means a future change to --drift cannot either. */
  overflow-x: clip;
  /* Offsets scale with the measure so narrow screens drift proportionally. */
  --drift-scale: 0.5px;
}

@media (min-width: 48em) {
  .converge__list {
    --drift-scale: 1px;
  }
}

.converge__item {
  display: flex;
  align-items: baseline;
  gap: clamp(0.85rem, 2vw, 1.75rem);
  padding-block: clamp(1.1rem, 2.4vw, 1.6rem);
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: var(--t-mono-lg);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-structural);
  /* Each row starts indented by a different amount and resolves to flush left
     as the act progresses — so the six names visibly come into alignment. The
     indent is an inset rather than a translation because a translation would
     carry the row's ends outside the column and clip them mid-word. The rule
     between name and status absorbs the change, so the status column never
     moves. The script interpolates --drift; only colour transitions here. */
  padding-left: calc(var(--drift, 0) * var(--drift-scale, 1px));
  transition: color var(--dur-mid) var(--ease-weighted);
}

.converge__item[data-aligned='true'] {
  color: var(--ink);
}

.converge__item .converge__num {
  color: var(--accent);
  flex: none;
}

.converge__item .converge__rule {
  flex: 1;
  height: 1px;
  background: var(--rule);
  transform: translateY(-0.3em);
}

.converge__state {
  flex: none;
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  color: var(--ink-structural);
}

.converge__item[data-aligned='true'] .converge__state {
  color: var(--accent);
}

.closing {
  padding-top: clamp(2.5rem, 6vw, 5rem);
}

.closing__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem 2rem;
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.assessment--closing {
  scroll-margin-top: calc(var(--nav-h) + 1rem);
  margin-top: clamp(5rem, 11vw, 10rem);
  padding-top: clamp(3rem, 7vw, 5.5rem);
  padding-bottom: clamp(1rem, 3vw, 2rem);
  border-top: 1px solid var(--rule-strong);
}

.assessment__closing-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(2.5rem, 6vw, 4.5rem);
}

.assessment__closing-head h2 {
  margin-top: 1.2rem;
}

.assessment__closing-copy {
  align-self: end;
}

.assessment__terms {
  display: grid;
  gap: 0;
  margin-top: 2rem;
  border-top: 1px solid var(--rule);
}

.assessment__terms > div {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr);
  gap: 1rem;
  padding-block: 0.8rem;
  border-bottom: 1px solid var(--rule);
}

.assessment__terms dt,
.assessment__terms dd {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.assessment__terms dt {
  color: var(--accent);
}

.assessment__terms dd {
  color: var(--ink-body);
}

@media (min-width: 62em) {
  .assessment__closing-head {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.8fr);
  }
}

@media (min-width: 62em) {
  .reconstruction__layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    column-gap: clamp(2rem, 5vw, 6rem);
    align-items: start;
  }

  .reconstruction__stage {
    z-index: 1;
    height: 100svh;
    padding-top: var(--nav-h);
    padding-bottom: clamp(3rem, 7svh, 5rem);
    padding-inline: clamp(1rem, 2vw, 2rem);
    border-bottom: 0;
    border-left: 1px solid var(--rule);
    order: 2;
  }

  /* The column is long because the convergence needs scroll to happen in. The
     content is centred in it so the reader is never looking at the empty end
     of a tall block. */
  .converge {
    min-height: 130svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: 6svh;
  }
}

/* ==========================================================================
   FOOTER
   ========================================================================== */

.foot {
  border-top: 1px solid var(--rule);
  padding-block: clamp(3rem, 6vw, 5rem) clamp(2rem, 4vw, 3rem);
  background: var(--bg);
}

.foot__top {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 1fr);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

.foot__group {
  display: grid;
  gap: 0.75rem;
  align-content: start;
}

.foot__group a {
  color: var(--ink-body);
  transition: color var(--dur-quick) var(--ease-weighted);
}

.foot__group a:hover,
.foot__group a:focus-visible {
  color: var(--accent);
}

.colophon {
  border-top: 1px solid var(--rule);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  display: grid;
  gap: 1rem clamp(1.5rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 1fr);
}

.colophon dl {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: 0.5rem 1.5rem;
}

.colophon dt {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-structural);
}

.colophon dd {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.04em;
  color: var(--ink-body);
}

@media (min-width: 55em) {
  .foot__top {
    grid-template-columns: minmax(0, 1.3fr) repeat(2, minmax(0, 1fr));
    gap: clamp(2rem, 5vw, 4rem);
  }

  .colophon {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
  }
}

/* ==========================================================================
   NARRATIVE REVEAL
   A single weighted settle per element. Opt-in via [data-reveal]; if the
   script never runs, content is visible by default (progressive enhancement).
   ========================================================================== */

html[data-js='on'] [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 900ms var(--ease-weighted),
    transform 900ms var(--ease-weighted);
}

html[data-js='on'] [data-reveal][data-revealed='true'] {
  opacity: 1;
  transform: none;
}

/* The two object acts reveal on a section line rather than floating upward:
   decomposition exposes the copy and reconstruction resolves it back onto the
   datum. The hero keeps its approved weighted settle. */
html[data-js='on'] .decomposition > .shell [data-reveal],
html[data-js='on'] .converge [data-reveal] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 900ms var(--ease-weighted);
}

html[data-js='on'] .decomposition > .shell [data-reveal][data-revealed='true'],
html[data-js='on'] .converge [data-reveal][data-revealed='true'] {
  clip-path: inset(0);
}

/* ==========================================================================
   REDUCED MOTION
   Not a degraded version: a composed, static reading of the same narrative
   (doctrine §19).
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  html[data-js='on'] [data-reveal] {
    opacity: 1;
    transform: none;
    clip-path: none;
  }

  /* No camera travel, no depth-driven scroll animation: the specimen is
     presented already decomposed, which is the state the narrative needs. The
     separation is a fixed value rather than the scroll-driven one, and the
     substrate is placed with the same constant so it still sits directly
     beneath the deepest layer. */
  .plate {
    transform: translate3d(0, 0, calc((2.5 - var(--i)) * 22px * var(--sep-scale, 1)));
  }

  .plinth {
    transform: translate3d(
      0,
      0,
      calc((2.5 - 5.5) * 22px * var(--sep-scale, 1) - 0.55rem)
    );
  }

  .converge__item {
    transform: none;
  }

  /* Released from sticky: nothing travels, so nothing needs to be pinned.

     And with nothing pinned, the two-column layout would leave the reader an
     empty gutter beside six chapters once the object had scrolled past. So the
     acts collapse to one column: the specimen is presented once, already
     decomposed, and the chapters read beneath it. That is a composed reading of
     the same narrative, not a degraded one (doctrine §19). */
  .decomposition__layout,
  .reconstruction__layout {
    grid-template-columns: minmax(0, 1fr);
  }

  .decomposition__stage,
  .reconstruction__stage {
    position: relative;
    height: clamp(20rem, 54svh, 34rem);
    padding-top: 0;
    border-right: 0;
    border-left: 0;
    border-bottom: 1px solid var(--rule);
    order: 0;
  }

  .layer {
    min-height: 0;
    padding-right: 0;
  }

  .converge {
    min-height: 0;
    padding-block: clamp(2rem, 5vw, 4rem);
  }

  .action__arrow {
    transition: none;
  }
}

/* Honour the OS preference even when the stage would otherwise animate. */
@media (prefers-reduced-motion: reduce) {
  .stage__canvas {
    display: none;
  }
}

/* ==========================================================================
   PRINT
   ========================================================================== */

@media print {
  .nav,
  .stage,
  .skip,
  .turn {
    display: none !important;
  }

  .act {
    padding-block: 1.5rem;
  }

  body {
    background: #fff;
    color: #000;
  }
}
