/* ==========================================================================
   TWELFTH FRET — twelfthfret.app
   Built from the Figma board "05 · final design" (1440 × 6616).

   Contents
   01  Tokens
   02  Reset and base
   03  Utilities
   04  Type primitives
   05  Component — app screen
   06  Component — signup form
   07  Component — store badges
   08  Section — hero
   09  Section — plate 01, the instrument
   10  Section — the whole flow
   11  Section — plate 02, omissions
   12  Section — the node
   13  Section — plate 04, specification
   14  Section — plate 05, the maker
   15  Section — CTA and colophon
   16  Document pages
   17  Loading veil
   18  Motion
   19  Print
   ========================================================================== */


/* ==========================================================================
   01  TOKENS
   ========================================================================== */

:root {
  /* Palette --------------------------------------------------------------- */
  --ink:      #0A1410;   /* deepest, site only              */
  --forest:   #12251E;   /* darkest brand green             */
  --tolex:    #1E3A30;   /* amp covering green              */
  --moss:     #2F5B49;   /* mid green                       */
  --cream:    #F5EFE0;   /* paper                           */
  --tweed:    #E0D0AE;   /* warm secondary                  */
  --sand:     #C4AC7E;   /* muted tertiary                  */
  --signal:   #5CA872;   /* in tune                         */
  --amber:    #D89A3C;   /* almost                          */
  --rust:     #B0512E;   /* flat / sharp                    */
  --tweed-dk: #CDBA98;   /* plate numeral on tweed          */
  --slot:     #17302A;   /* inactive string slot            */
  --moss-lift:#5C8A78;   /* moss lifted for dark-bg contrast*/

  /* Typefaces ------------------------------------------------------------- */
  --font-display: "Fraunces", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-body:    "Karla", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono:    "Geist Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --font-alt:     "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Layout ---------------------------------------------------------------- */
  /* max() keeps content clear of a notch in landscape, since the document
     declares viewport-fit=cover */
  --gutter: max(clamp(20px, 5.56vw, 80px), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --measure: 1280px;
  --cw: min(calc(100% - (2 * var(--gutter))), var(--measure));
  --cw-vw: min(calc(100vw - (2 * var(--gutter))), var(--measure));
  /* left inset of the content column, usable outside .container */
  --pad-x: max(var(--gutter), calc((100vw - var(--measure)) / 2));

  /* Rhythm ---------------------------------------------------------------- */
  --space-section: clamp(72px, 9vw, 130px);
  --radius-sm: 3px;
  --radius-md: 6px;

  /* Motion ----------------------------------------------------------------
     --ease has a long, soft tail: most of the distance is covered early and
     the last few pixels take their time, which is what reads as "settling"
     rather than "arriving". --ease-ui is quicker off the mark, for hover. */
  --ease:      cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.25, 1, 0.35, 1);  /* veil and page settle     */
  --ease-ui:   cubic-bezier(0.32, 0.72, 0, 1);
  --dur-move: 2000ms;   /* the lift; the fade inside it completes at 62%,
                           so type is readable ~760ms before it settles     */
  --dur-ui:   240ms;    /* hover, focus, field states                       */
  --delay-in: 60ms;     /* a beat before anything starts, so it reads as
                           choreographed rather than reactive              */
}


/* ==========================================================================
   02  RESET AND BASE
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Reserved always, so nothing can shift sideways if the scrollbar ever
     appears or disappears mid-sequence. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;   /* fallback for Safari < 16 */
  overflow-x: clip;
}

h1, h2, h3, h4, p, dl, dd, figure, blockquote { margin: 0; }
ol, ul { margin: 0; padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
hr { border: 0; margin: 0; }

a { color: inherit; }

button, input { font: inherit; color: inherit; margin: 0; }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--signal); color: var(--forest); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }


/* ==========================================================================
   03  UTILITIES
   ========================================================================== */

.container { width: var(--cw); margin-inline: auto; }

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

.skip-link {
  position: absolute;
  top: 0; left: 50%;
  transform: translate(-50%, -140%);
  z-index: 100;
  padding: 12px 20px;
  background: var(--cream);
  color: var(--forest);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip-link:focus { transform: translate(-50%, 0); }


/* ==========================================================================
   04  TYPE PRIMITIVES
   ========================================================================== */

.mono-eyebrow {
  font-family: var(--font-mono);
  font-size: clamp(9px, 0.7vw, 10px);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.mono-fine {
  font-family: var(--font-mono);
  font-size: clamp(8.5px, 0.63vw, 9px);
  line-height: 1.35;
  letter-spacing: 0.175em;
  text-transform: uppercase;
}

.plate__eyebrow { color: var(--moss); }


/* ==========================================================================
   05  COMPONENT — APP SCREEN
   The component is driven by one variable, --sw (screen width). Everything
   inside is expressed in the 320 × 660 design grid via --u, so the screen
   is pixel-faithful at any size. --sw must always resolve to a length.
   ========================================================================== */

.screen {
  --sw: 296px;
  --u: calc(var(--sw) / 320);
  --accent: var(--cream);

  position: relative;
  flex: none;
  width: var(--sw);
  aspect-ratio: 320 / 660;
  background: var(--forest);
  border: calc(1.62 * var(--u)) solid rgba(245, 239, 224, 0.16);
  border-radius: calc(44 * var(--u));
  overflow: hidden;
}

.screen[data-state="rest"] { --accent: var(--cream);  }
.screen[data-state="flat"] { --accent: var(--rust);   }
.screen[data-state="near"] { --accent: var(--amber);  }
.screen[data-state="tune"] { --accent: var(--signal); }

.screen__notch {
  position: absolute;
  top: calc(12 * var(--u));
  left: 50%;
  transform: translateX(-50%);
  width: calc(52 * var(--u));
  height: calc(4 * var(--u));
  border-radius: calc(2 * var(--u));
  background: rgba(245, 239, 224, 0.22);
}

.screen__mode {
  position: absolute;
  top: calc(48 * var(--u));
  inset-inline: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: calc(7 * var(--u));
  line-height: calc(10 * var(--u));
  letter-spacing: calc(1.4 * var(--u));
  color: var(--signal);
}

.screen__disc {
  position: absolute;
  top: calc(134 * var(--u));
  left: 50%;
  transform: translateX(-50%);
  width: calc(124 * var(--u));
  height: calc(124 * var(--u));
  color: var(--accent);
}

.screen__note {
  position: absolute;
  top: calc(286 * var(--u));
  inset-inline: 0;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: calc(92 * var(--u));
  line-height: calc(100 * var(--u));
  letter-spacing: calc(-1.6 * var(--u));
  color: var(--cream);
}

/* Cent meter --------------------------------------------------------------
   33 ticks at 7.375u spacing across a 236u span, drawn as two repeating
   gradients so the markup stays clean and everything scales with --sw.    */

.screen__meter {
  position: absolute;
  top: calc(419 * var(--u));
  left: 50%;
  transform: translateX(-50%);
  width: calc(236 * var(--u));
  height: calc(25 * var(--u));
}

.screen__ticks {
  position: absolute;
  top: calc(5 * var(--u));
  left: calc(-0.5 * var(--u));
  width: calc(237 * var(--u));
  height: calc(10 * var(--u));
  background-image:
    repeating-linear-gradient(to right,
      rgba(245, 239, 224, 0.38) 0 calc(1 * var(--u)),
      transparent calc(1 * var(--u)) calc(29.5 * var(--u))),
    repeating-linear-gradient(to right,
      rgba(245, 239, 224, 0.15) 0 calc(1 * var(--u)),
      transparent calc(1 * var(--u)) calc(7.375 * var(--u)));
  background-size: 100% calc(10 * var(--u)), 100% calc(5 * var(--u));
  background-position: 0 0;
  background-repeat: no-repeat;
}

.screen__centre {
  position: absolute;
  top: calc(5 * var(--u));
  left: 50%;
  transform: translateX(-50%);
  width: calc(2 * var(--u));
  height: calc(15 * var(--u));
  background: rgba(245, 239, 224, 0.8);
}

.screen__needle {
  --cents: 0;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(calc(-50% + ((var(--cents) / 50) * 118 * var(--u))));
  width: calc(2.4 * var(--u));
  height: calc(25 * var(--u));
  border-radius: calc(1.2 * var(--u));
  background: var(--accent);
}

.screen__state {
  position: absolute;
  top: calc(466 * var(--u));
  inset-inline: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: calc(16 * var(--u));
  line-height: calc(20 * var(--u));
  letter-spacing: calc(2.4 * var(--u));
  color: var(--accent);
}
.screen[data-state="rest"] .screen__state { color: var(--moss-lift); }

.screen__freq {
  position: absolute;
  top: calc(496 * var(--u));
  inset-inline: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: calc(9 * var(--u));
  line-height: calc(12 * var(--u));
  letter-spacing: calc(0.5 * var(--u));
  font-variant-numeric: tabular-nums;
  color: var(--moss-lift);
}

.screen__strings {
  position: absolute;
  top: calc(552 * var(--u));
  inset-inline: 0;
  display: flex;
  justify-content: center;
  gap: calc(8 * var(--u));
}

.screen__strings li {
  display: grid;
  place-items: center;
  width: calc(34 * var(--u));
  height: calc(34 * var(--u));
  border-radius: 50%;
  background: var(--slot);
  font-family: var(--font-mono);
  font-size: calc(10 * var(--u));
  line-height: 1;
  color: var(--tweed);
}
.screen__strings li.is-active { background: var(--moss); color: var(--cream); }


/* ==========================================================================
   06  COMPONENT — SIGNUP FORM
   ========================================================================== */

.signup { display: grid; gap: 16px; }

.signup__input {
  width: 100%;
  min-width: 0;
  height: 60px;
  padding: 0 22px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--cream);
  color: var(--forest);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.4;
  transition: border-color var(--dur-ui) var(--ease-ui), box-shadow var(--dur-ui) var(--ease-ui);
}
.signup__input::placeholder { color: var(--moss); opacity: 1; }
.signup__input:focus-visible {
  outline: none;
  border-color: var(--signal);
  box-shadow: 0 0 0 3px rgba(92, 168, 114, 0.4);
}
.signup__input[aria-invalid="true"] {
  border-color: var(--rust);
  box-shadow: 0 0 0 3px rgba(176, 81, 46, 0.32);
}

.signup__button {
  height: 60px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--signal);
  color: var(--forest);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color var(--dur-ui) var(--ease-ui), transform 140ms var(--ease-ui);
}
.signup__button:hover { background: #6DBB83; }
.signup__button:active { transform: translateY(1px); }
.signup__button[disabled] { opacity: 0.6; cursor: default; }

.signup__message {
  margin: -4px 0 0;
  min-height: 1em;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.signup__message:empty { display: none; }
.signup__message[data-tone="error"]   { color: #D9744E; }
.signup__message[data-tone="success"] { color: var(--signal); }


/* ==========================================================================
   07  COMPONENT — STORE BADGES
   Placeholder marks in the brand palette. Swap for the official Apple and
   Google artwork before launch — see README.
   ========================================================================== */

.stores { display: flex; flex-wrap: wrap; gap: 11px; }

.store-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 31px;
  padding: 0 12px 0 9px;
  border-radius: 4px;
}
.store-badge--play  { background: #000; color: #FFF; }
.store-badge--apple { background: #FFF; color: #000; }

.store-badge__glyph { width: 17px; height: 17px; flex: none; }
.store-badge--play .store-badge__glyph { width: 15px; height: 15px; }

.store-badge__text { display: grid; line-height: 1; }
.store-badge__text small {
  font-family: var(--font-alt);
  font-size: 6.5px;
  letter-spacing: 0.01em;
}
.store-badge__text strong {
  margin-top: 2px;
  font-family: var(--font-alt);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: -0.015em;
}


/* ==========================================================================
   08  SECTION — HERO
   Desktop: a 62.5% / 37.5% colour split measured across the container,
   with the wordmark deliberately crossing the seam.
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  background: var(--tolex);
  padding-block: clamp(36px, 4.2vw, 60px) clamp(48px, 4.4vw, 63px);
}

/* The seam is measured across the viewport, exactly as on the artboard:
   880 / 1440 = 61.111%. Percentages resolve against the hero, so this is
   scrollbar-safe, unlike vw. */
.hero__split {
  position: absolute;
  z-index: -1;
  inset-block: 0;
  right: 0;
  left: 61.111%;
  background: var(--forest);
}

/* Both rows are full-bleed and split on the seam itself, so the right-hand
   column IS the forest panel. On the artboard the signup block sits 940–1380
   inside an 880–1440 panel: dead centre, 60px each side. */
.hero__cols {
  display: grid;
  grid-template-columns: 61.111% 38.889%;
  align-items: start;
}

/* Left of the seam — aligned to the page gutter, capped at the artboard's 760 */
.hero__est,
.hero__lede {
  padding-left: var(--pad-x);
  padding-right: clamp(16px, 2.78vw, 40px);
}
.hero__lede > * { max-width: 760px; }

/* Right of the seam — the signup block is centred in the panel, 440 wide */
.hero__signup {
  width: min(78.571%, 440px);
  margin-inline: auto;
}

/* The catalogue line is pinned to the seam and stays put, rather than
   travelling with the centred block underneath it. 880 + 60 = 940 at 1440. */
.hero__cat { padding-left: 60px; }

.hero__est    { color: var(--sand);  }
.hero__cat    { color: var(--cream); }
.hero__signup { padding-top: clamp(0px, 4.86vw, 70px); }

/* Full-bleed band. 540 / 1440 = 37.5% in, 560 / 1440 = 38.889% wide, so the
   wordmark crosses the seam in the same place at every viewport width. */
.hero__brand {
  margin-block: clamp(24px, 5.28vw, 76px) clamp(28px, 6.18vw, 89px);
}
.hero__wordmark {
  /* Both percentages resolve against the full-bleed band, so the mark holds
     the same size and crossing point at every width. Must be margin, not
     padding: padding would shrink the box the width is measured against.
     Artboard is 37.5% / 38.889%; dialled back ~11% here, keeping the seam
     at the same point along the mark (60.7% of its width). */
  margin-left: 40.17%;
  width: 34.5%;
  max-width: none;
  height: auto;
  color: var(--cream);
}

.hero__fret {
  margin-bottom: clamp(20px, 2.64vw, 38px);
  font-family: var(--font-alt);
  font-weight: 600;
  font-size: clamp(17px, 1.8vw, 26px);
  line-height: 1.25;
  letter-spacing: 0.54em;
  color: var(--tweed);
}

.hero__rule {
  height: 2px;
  margin-bottom: clamp(22px, 2.64vw, 38px);
  background: var(--moss);
}

.hero__headline {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(34px, 5.42vw, 78px);
  line-height: 1.077;
  letter-spacing: -0.026em;
  color: var(--cream);
}

.hero__promise { margin-top: 24px; color: var(--sand); }
.hero .stores  { margin-top: clamp(40px, 6.53vw, 94px); }

@media (min-width: 900px) {
  .hero .stores { justify-content: flex-end; }
}

/* Hero — responsive collapse ---------------------------------------------- */

@media (max-width: 899px) {
  .hero { padding-bottom: 0; }
  .hero__split { display: none; }

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

  .hero__est,
  .hero__lede { padding-inline: var(--pad-x); }

  .hero__cat {
    margin: 6px 0 0;
    padding-inline: var(--pad-x);
  }

  .hero__brand { padding-inline: var(--pad-x); }
  /* 320px cap meets the desktop rule almost exactly at the 900 breakpoint
     (0.345 × 900 = 310), so there is no jump across it. */
  .hero__wordmark { margin-left: 0; width: min(74%, 320px); }

  .hero__signup {
    width: auto;
    margin: clamp(40px, 8vw, 64px) 0 0;
    padding: clamp(30px, 6vw, 44px) var(--pad-x) clamp(40px, 8vw, 56px);
    background: var(--forest);
  }

  .hero .stores { margin-top: 32px; }
}

@media (max-width: 599px) {
  .hero__fret { letter-spacing: 0.4em; }
}


/* ==========================================================================
   09  SECTION — PLATE 01, THE INSTRUMENT

   Artboard, frame coordinates (section spans y900–1948):
     eyebrow        y970          device  x572–868, y1149–1759.5 (296 × 610.5)
     A  text x80    y1262–1328    line x300–540  y1340   dot right end
     C  text x1150  y1402–1449    line x900–1140 y1460   dot left end
     B  text x80    y1557–1604    line x300–540  y1615   dot right end
     D  text x1150  y1622–1669    line x900–1140 y1680   dot left end
     closing        y1830, 600 wide, centred

   Each rule points at a specific part of the readout, so its position is a
   percentage of the DEVICE height, not a consequence of how tall the text is.
   The text then hangs above its rule, 12px clear.
     A 31.29% -> the disc      C 50.94% -> the note letter
     B 76.33% -> the frequency D 86.98% -> the string row
   ========================================================================== */

.plate { position: relative; overflow: hidden; overflow: clip; }
.plate__inner { position: relative; z-index: 1; }

/* The artboard bleeds these off the canvas. Here they sit inside the content
   column instead, aligned to the same edge as everything else in the section.
   The -0.045em nudge cancels Fraunces' left side bearing so the glyph's stem
   lines up optically with the eyebrow above it, not just its box. */
.plate__numeral {
  position: absolute;
  z-index: 0;
  left: calc(50% - (var(--cw) / 2));
  margin-left: -0.045em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(130px, 20.8vw, 300px);
  line-height: 1;
  letter-spacing: -0.02em;
  pointer-events: none;
  user-select: none;
}

/* Plate 02 is the one drawn on the right */
.plate--omissions .plate__numeral {
  left: auto;
  right: calc(50% - (var(--cw) / 2));
  margin-left: 0;
  margin-right: -0.045em;
}

.plate--instrument {
  background: var(--cream);
  color: var(--forest);
  padding-block: clamp(48px, 4.86vw, 70px) clamp(56px, 6.25vw, 90px);
}
.plate--instrument .plate__numeral {
  top: clamp(20px, 4.79vw, 69px);
  color: var(--tweed);
}

.instrument {
  --dev: clamp(230px, 20.56vw, 296px);   /* device width */
  --lead: 32px;                          /* rule stops this far short of it */
  display: grid;
  gap: clamp(32px, 4vw, 48px);
  margin-top: clamp(56px, 11.46vw, 165px);
}

.instrument__device { grid-column: 1 / -1; display: flex; justify-content: center; }
.instrument .screen { --sw: var(--dev); }

.callout__key {
  margin-bottom: 2px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
  color: var(--forest);
}
.callout__body {
  font-size: 13px;
  line-height: 1.4615;
  color: var(--moss);
}
.callout__line { display: none; }

.instrument__closing {
  max-width: 600px;
  margin: clamp(40px, 4.9vw, 70px) auto 0;
  text-align: center;
  font-weight: 500;
  font-size: clamp(15px, 1.11vw, 16px);
  line-height: 1.75;
  color: var(--forest);
  text-wrap: balance;
}

/* Stacked, no rules, until there is room to place them around the device */
@media (max-width: 1023px) {
  .callout__body { max-width: 30ch; }

  /* Centring only earns its place when the line sits under a centred device
     with copy either side of it. Once the callouts stack into left-aligned
     columns there is nothing left for it to be centred against, so it ranges
     left with everything else. */
  .instrument__closing {
    max-width: 62ch;
    margin-inline: 0;
    text-align: left;
  }
}
@media (min-width: 560px) and (max-width: 1023px) {
  .instrument { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .instrument {
    display: block;
    position: relative;   /* height == the device, so % anchors to the device */
  }

  .callout {
    position: absolute;
    left: 0;
    width: 100%;
    display: grid;
    padding-bottom: 12px;               /* the rule sits 12px under the text */
    bottom: calc(100% - var(--y));      /* --y measured from the device top   */
  }
  .callout__key,
  .callout__body { width: 210px; }

  .callout--a { --y: 31.29%; justify-content: start; }
  .callout--c { --y: 50.94%; justify-content: end;   }
  .callout--b { --y: 76.33%; justify-content: start; }
  .callout--d { --y: 86.98%; justify-content: end;   }

  .callout__line {
    display: block;
    position: absolute;
    bottom: 0;
    width: 240px;
    height: 1px;
    background: var(--sand);
  }
  .callout--a .callout__line,
  .callout--b .callout__line { right: calc(50% + (var(--dev) / 2) + var(--lead)); }
  .callout--c .callout__line,
  .callout--d .callout__line { left:  calc(50% + (var(--dev) / 2) + var(--lead)); }

  /* 6px dot, centred on the rule end that faces the device */
  .callout__line::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 6px;
    height: 6px;
    margin-top: -3px;
    border-radius: 50%;
    background: var(--forest);
  }
  .callout--a .callout__line::after,
  .callout--b .callout__line::after { right: -3px; }
  .callout--c .callout__line::after,
  .callout--d .callout__line::after { left: -3px; }
}


/* ==========================================================================
   10  SECTION — THE WHOLE FLOW

   Artboard, frame coordinates (section spans y1948–3121, 1173 tall):
     eyebrow    x80   y2018–2033      70 below the section top
     headline   x80   y2079–2187      46 below the eyebrow, 2 lines at 54
     screens    x80, 408, 736, 1064 · y2257 · 296 × 610.5 · 32 apart
                                       70 below the headline
     number     y2888   20.5 below the device
     label      y2912   12 below the number
     sub        y2934
     footnote   y3019   65.5 below the sub, 90 above the section bottom
   ========================================================================== */

.flow {
  background: var(--forest);
  padding-block: clamp(48px, 4.86vw, 70px) clamp(56px, 6.25vw, 90px);
}

.flow__eyebrow {
  font-weight: 500;
  font-size: 11px;
  line-height: 1.364;
  letter-spacing: 0.218em;
  text-transform: uppercase;
  color: var(--signal);
}

.flow__title {
  margin-top: clamp(26px, 3.19vw, 46px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(26px, 3.06vw, 44px);
  line-height: 1.2273;
  letter-spacing: -0.0227em;
  color: var(--cream);
}

.flow__list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 32px;
  margin-top: clamp(44px, 4.86vw, 70px);
}

/* --sw mirrors the real grid column so the screens can never overflow.
   4 × 296 + 3 × 32 = 1280, the full content column at 1440. */
.flow__item .screen {
  --sw: min(296px, calc((var(--cw-vw) - 96px) / 4));
  margin-bottom: clamp(16px, 1.42vw, 20.5px);
}

.flow__num { color: var(--sand); }

.flow__label {
  margin-top: 12px;
  font-weight: 500;
  font-size: 15px;
  line-height: 1.4667;
  letter-spacing: 0.013em;
  color: var(--cream);
}

.flow__sub {
  font-size: 13px;
  line-height: 1.5;
  color: var(--signal);
}

.flow__footnote {
  margin-top: clamp(40px, 4.55vw, 65.5px);
  color: var(--sand);
}

/* Tablet — two up */
@media (max-width: 1079px) {
  .flow__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 52px 32px; }
  .flow__item .screen { --sw: min(296px, calc((var(--cw-vw) - 32px) / 2)); }
}

/* Mobile — a snapping rail that still reads as an ordered list */
@media (max-width: 699px) {
  .flow__list {
    display: flex;
    gap: 20px;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-bottom: 10px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-left: var(--gutter);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }
  .flow__list::-webkit-scrollbar { display: none; }
  .flow__list:focus-visible { outline-offset: -2px; }

  .flow__item {
    flex: 0 0 auto;
    width: min(258px, 70vw);
    scroll-snap-align: start;
  }
  .flow__item .screen { --sw: min(258px, 70vw); }
}


/* ==========================================================================
   11  SECTION — PLATE 02, OMISSIONS
   ========================================================================== */

.plate--omissions {
  background: var(--moss);
  color: var(--cream);
  padding-block: var(--space-section);
}
.plate--omissions .plate__eyebrow { color: var(--tweed); }
.plate--omissions .plate__numeral {
  top: clamp(8px, 2.2vw, 31px);
  color: var(--tolex);
}

.omissions__title {
  margin-top: clamp(20px, 2.8vw, 40px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(27px, 4.31vw, 62px);
  line-height: 1.13;
  letter-spacing: -0.026em;
  color: var(--cream);
}

.omissions__list { margin-top: clamp(48px, 6.8vw, 98px); }

.omissions__row {
  display: grid;
  grid-template-columns: 80px minmax(0, 460px) minmax(0, 1fr);
  align-items: baseline;
  gap: 4px 0;
  padding-block: clamp(20px, 2vw, 28px);
  border-top: 1px solid rgba(224, 208, 174, 0.32);
}
.omissions__row:first-child { border-top: 0; padding-top: 0; }

.omissions__num { color: var(--sand); letter-spacing: 0.127em; }
.omissions__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(20px, 1.81vw, 26px);
  line-height: 1.23;
  letter-spacing: -0.015em;
  color: var(--cream);
}
.omissions__desc { font-size: 15px; line-height: 1.47; color: var(--tweed); }

@media (max-width: 899px) {
  .omissions__row { grid-template-columns: 44px minmax(0, 1fr); row-gap: 6px; }
  .omissions__num  { grid-row: 1; grid-column: 1; }
  .omissions__name { grid-row: 1; grid-column: 2; }
  .omissions__desc { grid-row: 2; grid-column: 2; }
}


/* ==========================================================================
   12  SECTION — THE NODE

   Artboard, frame coordinates (section spans y3885–4705, 820 tall):
     ink base -> photograph (cover) -> flat ink veil at 62%
     eyebrow           x80    y3955  (15 tall)
     fret rules        x140, 350, 560, 770, 980, 1190 · y4185 · 2 x 220
                       cream at 28%, except the twelfth at 90%
     fret numbers      y4425 (20 below the rules) · moss, twelfth in signal
     headline          x80    y4491–4615
     body              x860   y4557  (500 wide, sits to the container edge)
   ========================================================================== */

.node {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  overflow: clip;
  background: var(--ink);
  padding-block: clamp(48px, 4.86vw, 70px) clamp(56px, 6.25vw, 90px);
}

.node__media {
  position: absolute;
  z-index: -2;
  inset: 0;
  background-color: var(--ink);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;

  /* Plain JPEG first as the floor, then let the browser pick the best it
     supports. WebP is roughly half the weight at the same quality. */
  background-image: url("../images/node-fretboard.jpg");
  background-image: -webkit-image-set(
    url("../images/node-fretboard@1x.webp") 1x,
    url("../images/node-fretboard.webp") 2x);
  background-image: image-set(
    url("../images/node-fretboard@1x.webp") type("image/webp") 1x,
    url("../images/node-fretboard.webp")    type("image/webp") 2x,
    url("../images/node-fretboard@1x.jpg")  type("image/jpeg") 1x,
    url("../images/node-fretboard.jpg")     type("image/jpeg") 2x);
}

/* Flat, not a gradient — the artboard uses a single 62% ink wash */
.node__veil {
  position: absolute;
  z-index: -1;
  inset: 0;
  background: rgba(10, 20, 16, 0.62);
}

.node__eyebrow {
  font-weight: 500;
  font-size: 11px;
  line-height: 1.364;
  letter-spacing: 0.218em;
  text-transform: uppercase;
  color: var(--tweed);
}

/* Fret diagram — rules at 4.6875% + n × 16.406% of the content column,
   which is 140 + n × 210 on the artboard. */
.node__frets {
  position: relative;
  height: clamp(110px, 15.28vw, 220px);
  margin-top: clamp(72px, 14.93vw, 215px);
}

.node__fret {
  --i: 0;
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(4.6875% + (var(--i) * 16.406%));
  width: 2px;
}
.node__fret:nth-child(2) { --i: 1; }
.node__fret:nth-child(3) { --i: 2; }
.node__fret:nth-child(4) { --i: 3; }
.node__fret:nth-child(5) { --i: 4; }
.node__fret:nth-child(6) { --i: 5; }

.node__fret i {
  display: block;
  width: 2px;
  height: 100%;
  background: rgba(245, 239, 224, 0.28);
}
.node__fret em {
  position: absolute;
  top: calc(100% + 20px);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 10px;
  line-height: 1.4;
  letter-spacing: 0.1em;
  color: var(--moss);
}

/* The twelfth is the whole point: the rule reads, the number is signal green */
.node__fret.is-twelfth i  { background: rgba(245, 239, 224, 0.9); }
.node__fret.is-twelfth em { color: var(--signal); }

.node__text {
  display: grid;
  /* 500 is the artboard width, but as a share of a 900px container it would
     leave the headline only 255px. Cap it at 42% so the headline always wins. */
  grid-template-columns: minmax(0, 1fr) minmax(0, min(500px, 42%));
  column-gap: clamp(40px, 5vw, 72px);
  align-items: end;
  margin-top: clamp(52px, 5.97vw, 86px);
}

.node__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(27px, 3.61vw, 52px);
  line-height: 1.192;
  letter-spacing: -0.023em;
  color: var(--cream);
}

.node__body {
  font-size: clamp(15px, 1.11vw, 16px);
  line-height: 1.6875;
  color: var(--tweed);
}

@media (max-width: 899px) {
  .node__text { grid-template-columns: minmax(0, 1fr); row-gap: 22px; }
}


/* ==========================================================================
   13  SECTION — PLATE 04, SPECIFICATION

   Artboard, frame coordinates (section spans y4705–5385, 680 tall):
     numeral "03"   x-30  y4755
     eyebrow        x80   y4775  (70 below the section top)
     headline       x80   y4835–4893
     row values     y4973, 5045, 5117, 5189, 5261   — a 72 pitch
     rules          y5027, 5099, 5171, 5243         — between rows only
     columns        label x80 (240) · value x320 (380) · desc x700 (660)

   The three cells in a row are CENTRED on one another, not baseline-aligned:
   value 4973+34/2, desc 4979+22/2 and label 4983+14/2 all resolve to 4990.
   ========================================================================== */

.plate--spec {
  background: var(--tweed);
  color: var(--forest);
  padding-block: 70px 70px;
}
.plate--spec .plate__numeral {
  top: clamp(16px, 3.47vw, 50px);
  color: var(--tweed-dk);
}

.spec__title {
  margin-top: clamp(22px, 3.19vw, 46px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(28px, 3.47vw, 50px);
  line-height: 1.16;
  letter-spacing: -0.024em;
  color: var(--forest);
}

.spec__list { margin-top: clamp(44px, 5.56vw, 80px); }

.spec__row {
  display: grid;
  grid-template-columns: 240px minmax(0, 380px) minmax(0, 1fr);
  align-items: center;
  padding-block: 17px 20px;            /* 34 + 17 + 20 + 1px rule = 72 pitch */
  border-top: 1px solid rgba(18, 37, 30, 0.22);
}
.spec__row:first-child { border-top: 0; padding-top: 0; }

.spec__label {
  font-family: var(--font-mono);
  font-size: 11px;          /* artboard is 10; lifted a step for legibility */
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--moss);
}
.spec__value {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: clamp(20px, 1.81vw, 26px);
  line-height: 1.3077;
  font-variant-numeric: tabular-nums;
  color: var(--forest);
}
.spec__desc {
  margin: 0;
  font-size: 15px;
  line-height: 1.4667;
  color: var(--moss);
}

@media (max-width: 1023px) {
  .plate--spec { padding-block: clamp(48px, 6.8vw, 70px); }
  .spec__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: baseline;
    row-gap: 8px;
    column-gap: 24px;
    padding-block: 20px 22px;
  }
  .spec__label { grid-column: 1 / -1; }
  .spec__value { grid-column: 1; }
  .spec__desc  { grid-column: 2; }
}

@media (max-width: 599px) {
  .spec__row { grid-template-columns: minmax(0, 1fr); }
  .spec__value, .spec__desc { grid-column: 1; }
}


/* ==========================================================================
   14  SECTION — PLATE 05, THE MAKER

   Artboard, frame coordinates (section spans y5385–5845, 460 tall):
     image     x0    y5385  480 × 460  (a third of the frame, full bleed left)
     eyebrow   x580  y5504–5518        119 below the section top
     headline  x580  y5544–5636        26 below the eyebrow · 780 wide
     body      x580  y5672–5726        36 below the headline · 495 wide
                                        119 above the section bottom
   ========================================================================== */

.maker {
  display: grid;
  grid-template-columns: minmax(0, 480fr) minmax(0, 960fr);
  align-items: stretch;
  background: var(--cream);
  color: var(--forest);
}

.maker__media {
  min-height: clamp(220px, 32vw, 460px);
  background-color: var(--forest);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-image: url("../images/maker-peg.jpg");
  background-image: -webkit-image-set(
    url("../images/maker-peg@1x.webp") 1x,
    url("../images/maker-peg.webp") 2x);
  background-image: image-set(
    url("../images/maker-peg@1x.webp") type("image/webp") 1x,
    url("../images/maker-peg.webp")    type("image/webp") 2x,
    url("../images/maker-peg@1x.jpg")  type("image/jpeg") 1x,
    url("../images/maker-peg.jpg")     type("image/jpeg") 2x);
}

.maker__text {
  padding-block: clamp(48px, 8.26vw, 119px);
  padding-left: clamp(28px, 6.94vw, 100px);
  padding-right: var(--gutter);
}

.maker__title {
  max-width: 780px;
  margin-top: clamp(18px, 1.81vw, 26px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(22px, 2.36vw, 34px);
  line-height: 1.3529;
  letter-spacing: -0.0206em;
  color: var(--forest);
  text-wrap: pretty;
}

.maker__body {
  max-width: 495px;
  margin-top: clamp(24px, 2.5vw, 36px);
  font-size: clamp(15px, 1.11vw, 16px);
  line-height: 1.6875;
  color: var(--moss);
}

@media (max-width: 899px) {
  .maker { grid-template-columns: minmax(0, 1fr); }
  .maker__media { min-height: 0; aspect-ratio: 16 / 10; }
  .maker__text { padding-inline: var(--gutter); }
}


/* ==========================================================================
   15  SECTION — CTA AND COLOPHON

   Artboard, frame coordinates (section spans y5845–6605, 760 tall):
     image        x760  680 × 760, full bleed right, flat 20% ink wash
     eyebrow      x90   y5995–6010     150 below the section top
     headline     x90   y6035–6163     620 wide, 2 lines at 64
     body         x90   y6185–6211     480 wide
     field        x90   y6255  300 × 58 r6, cream at 10%
     button       x404  y6255  180 × 58 r6, signal
     promise      x90   y6341–6353
     rule         x90   y6485  580 × 1, cream at 14%
     "12th"       x90   y6509  52.3 × 21.5
     email        x670  y6522–6534, right-aligned to the rule end

   NOTE: the artboard sets this whole panel at x90, where every other section
   on the page sits at x80. Reproduced here as --cta-inset. Almost certainly a
   slip rather than intent — set it to 0 to line the footer up with the rest.
   ========================================================================== */

.cta {
  --cta-inset: 10px;
  /* The photograph occupies the right 47.222%. Everything in the panel is
     capped to the space left of it, so the artboard widths (620 / 580 / 494)
     apply at 1440 and above and shrink cleanly below that. */
  --cta-safe: calc(52.778vw - var(--pad-x) - 40px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  overflow: clip;
  background: var(--ink);
  padding-block: clamp(72px, 10.42vw, 150px) clamp(48px, 4.93vw, 71px);
}

.cta__media {
  position: absolute;
  z-index: -1;
  top: 0; right: 0; bottom: 0;
  width: 47.222%;
  background-color: var(--forest);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-image: url("../images/cta-player.jpg");
  background-image: -webkit-image-set(
    url("../images/cta-player@1x.webp") 1x,
    url("../images/cta-player.webp") 2x);
  background-image: image-set(
    url("../images/cta-player@1x.webp") type("image/webp") 1x,
    url("../images/cta-player.webp")    type("image/webp") 2x,
    url("../images/cta-player@1x.jpg")  type("image/jpeg") 1x,
    url("../images/cta-player.jpg")     type("image/jpeg") 2x);
}

/* A single flat wash with a hard edge against the panel, not a gradient */
.cta__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(10, 20, 16, 0.2);
}

.cta__inner { padding-left: var(--cta-inset); }
.cta__panel { max-width: min(620px, var(--cta-safe)); }

.cta__eyebrow {
  font-weight: 500;
  font-size: 11px;
  line-height: 1.364;
  letter-spacing: 0.218em;
  text-transform: uppercase;
  color: var(--signal);
}

.cta__title {
  max-width: 620px;
  margin-top: clamp(16px, 1.74vw, 25px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(32px, 3.89vw, 56px);
  line-height: 1.1429;
  letter-spacing: -0.0268em;
  color: var(--cream);
}

.cta__body {
  max-width: 480px;
  margin-top: clamp(18px, 1.53vw, 22px);
  font-size: clamp(15px, 1.11vw, 16px);
  line-height: 1.625;
  color: var(--tweed);
}

/* Field and button are 58 tall; the field is a 10% cream wash, not solid */
.signup--cta {
  grid-template-columns: minmax(0, 300px) auto;
  gap: 14px;
  max-width: min(494px, var(--cta-safe));  /* 300 + 14 + 180 */
  margin-top: clamp(28px, 3.06vw, 44px);
}
.signup--cta .signup__input,
.signup--cta .signup__button { height: 58px; border-radius: var(--radius-md); }

.signup--cta .signup__input {
  background: rgba(245, 239, 224, 0.1);
  color: var(--cream);
  padding-inline: 22px;
}
/* A placeholder is not content — it is the absence of content, and it vanishes
   the moment you type. At sand it carried the same weight as the real text
   around it. Dimmed cream reads as an empty field instead, and stays clear of
   sand (static text) and signal (links) so the block has three distinct
   voices rather than one. 4.6:1, so still legible as a hint. */
.signup--cta .signup__input::placeholder { color: rgba(245, 239, 224, 0.45); }
.signup--cta .signup__input:focus-visible {
  border-color: var(--signal);
  box-shadow: 0 0 0 3px rgba(92, 168, 114, 0.4);
}

.signup--cta .signup__button { min-width: 180px; }
.signup--cta .signup__message { grid-column: 1 / -1; }

/* Sits below the field, as drawn. Colour raised from the artboard's moss
   (~2:1 on the panel, effectively unreadable) to sand at 7.4:1. */
.cta__promise {
  margin-top: clamp(20px, 1.94vw, 28px);
  color: var(--sand);
}

/* Colophon — 580 wide, matching the rule; the email ends on the rule's end */
.colophon {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  max-width: min(580px, var(--cta-safe));
  margin-top: clamp(64px, 9.17vw, 132px);
  padding-top: 23px;
  border-top: 1px solid rgba(245, 239, 224, 0.14);
}

.colophon__mark {
  width: 52.3px;
  height: auto;
  margin-bottom: 3.5px;     /* seats the mark on the artboard line, both flush */
  color: var(--moss);
}

/* Colour and hover come from .colophon__links a. This rule only does the two
   things specific to an address: keep it lowercase (.mono-fine uppercases
   everything, which is right for FREE FOREVER and wrong for an email), and
   lift the hit area to 28px tall without shifting the line — WCAG 2.5.8. */
.colophon__email {
  position: relative;
  text-transform: none;
}
.colophon__email::after {
  content: "";
  position: absolute;
  inset: -8px -6px;
}

@media (max-width: 899px) {
  /* The photograph leads, full bleed and flush to the section top — the
     desktop top padding would otherwise leave a band of dead ink above it. */
  .cta {
    --cta-inset: 0px;
    --cta-safe: 100%;
    padding-block: 0 clamp(44px, 11vw, 64px);
  }

  .cta__media {
    position: relative;
    inset: auto;
    width: auto;
    margin: 0 calc(var(--gutter) * -1);
    aspect-ratio: 4 / 3;
  }

  .cta__inner { padding-top: clamp(44px, 11vw, 64px); }

  .colophon { margin-top: clamp(44px, 11vw, 64px); }
}

@media (max-width: 519px) {
  .signup--cta { grid-template-columns: minmax(0, 1fr); }
  .signup--cta .signup__button { min-width: 0; }
}


/* ==========================================================================
   16  DOCUMENT PAGES  (privacy, and anything else long-form later)
   ========================================================================== */

/* Neither form carries a consent line. The colophon's Privacy link is the
   site's privacy information, and it is present on every page. */

/* Signal green, same as every other link on the site. Green now means one
   thing — this is interactive — which is what separates these two from the
   sand promise line above and the dimmed placeholder in the field. 5.6:1. */
.colophon__links { display: flex; gap: 22px; }
.colophon__links a {
  color: var(--signal);
  text-decoration: none;
  text-underline-offset: 3px;
  transition: color var(--dur-ui) var(--ease-ui);
}
.colophon__links a:hover,
.colophon__links a:focus-visible { color: var(--cream); text-decoration: underline; }

/* -------------------------------------------------------------------------- */

.doc { background: var(--forest); }

/* Same container as the home page, so the mark lands on the gutter where
   "EST. 2026" sits and the footer rule aligns with the colophon. Only the
   reading column is narrowed. */
.doc__wrap {
  width: var(--cw);
  margin-inline: auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.doc__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-block: clamp(32px, 4vw, 56px);
}
/* The exit link is whichever anchor comes last in the header — matching on
   href broke the moment the links became "/" rather than "index.html". */
.doc__head > a:last-child {
  color: var(--signal);
  text-decoration: none;
  text-underline-offset: 3px;
  transition: color var(--dur-ui) var(--ease-ui);
}
.doc__head > a:last-child:hover,
.doc__head > a:last-child:focus-visible {
  color: var(--cream);
  text-decoration: underline;
}

.doc__home {
  display: inline-block;
  color: var(--signal);
  transition: color var(--dur-ui) var(--ease-ui);
}
.doc__home:hover, .doc__home:focus-visible { color: var(--cream); }
.doc__mark { width: 48px; height: auto; }


/* The COLUMN is centred; the text inside it is not. Centring the type itself
   would cost real readability — the eye has no fixed left edge to return to on
   each line — and would be the only centred long-form copy on the site.
   Centring the measure gives the balance without that cost.

   70ch sits at the upper end of the comfortable 45–75 character range. Past
   about 75 the eye starts losing its place on the return sweep, so this is
   roughly as wide as it can go and still read easily. */
/* The top padding sits on top of the header's own padding-bottom, so the
   header clears the eyebrow by roughly 56 + 40 = 96px at full width. It
   scales down with the header so the two never drift apart. */
.doc__body {
  flex: 1;
  width: 100%;
  max-width: 70ch;
  margin-inline: auto;
  padding-top: clamp(20px, 2.8vw, 40px);
  padding-bottom: clamp(64px, 8vw, 110px);
}

/* Short notice pages — the two signup confirmations and the 404. The body
   centres in the space between header and footer rather than starting under
   the header: two lines pinned to the top of a tall viewport read as an
   error, not as a designed page. Narrower measure too, because the copy is
   a statement rather than something to be read through. */
.doc__body--note {
  display: flex;
  flex-direction: column;
  justify-content: center;
  max-width: 56ch;
  padding-block: clamp(48px, 8vw, 96px);
}

/* One quiet link under the message. Not a button — nothing here is urgent. */
.doc__return {
  margin-top: clamp(32px, 3.6vw, 48px);
  font-size: clamp(16px, 1.18vw, 17px);
}

.doc__eyebrow { color: var(--signal); }

/* balance evens out the line lengths across a short heading so it never ends
   on one stranded word. Browsers cap it at a few lines, which is all a title
   ever is. */
.doc__title {
  text-wrap: balance;
  margin-top: clamp(18px, 2.2vw, 32px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(30px, 3.61vw, 52px);
  line-height: 1.19;
  letter-spacing: -0.023em;
  color: var(--cream);
}

/* pretty rather than balance for running text: it leaves the earlier lines
   full and only adjusts the last few, purely to avoid an orphan. Browsers
   without it wrap exactly as before, so there is nothing to fall back from. */
.doc__lede {
  text-wrap: pretty;
  margin-top: clamp(24px, 2.6vw, 38px);
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.7;
  color: var(--tweed);
}

.doc__body h2 {
  margin-top: clamp(40px, 4.2vw, 60px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(20px, 1.81vw, 26px);
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--cream);
}

.doc__body p {
  text-wrap: pretty;
  margin-top: 16px;
  font-size: clamp(16px, 1.18vw, 17px);
  line-height: 1.75;
  color: var(--tweed);
}

/* Signal green, underlined — the prose-link style used site-wide. */
.doc__body a {
  color: var(--signal);
  text-underline-offset: 3px;
  transition: color var(--dur-ui) var(--ease-ui);
}
.doc__body a:hover, .doc__body a:focus-visible { color: var(--cream); }

.doc__stamp {
  margin-top: clamp(48px, 5vw, 72px);
  padding-top: 22px;
  border-top: 1px solid rgba(245, 239, 224, 0.14);
  color: var(--moss-lift);
}

.doc__foot {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding-block: clamp(24px, 3vw, 40px);
  border-top: 1px solid rgba(245, 239, 224, 0.14);
}
.doc__foot a {
  color: var(--signal);
  text-decoration: none;
  text-underline-offset: 3px;
  transition: color var(--dur-ui) var(--ease-ui);
}
.doc__foot a:hover, .doc__foot a:focus-visible { color: var(--cream); text-decoration: underline; }


/* ==========================================================================
   17  LOADING VEIL

   No door, no wipe, no cut. The veil dissolves while lifting very slightly
   toward the viewer, and the page settles down into place beneath it from a
   fractional scale-up. Two things cross-dissolving through each other reads as
   depth, which is the language Apple uses almost exclusively — you rarely see
   anything slide across the frame.

   While it holds, the mark does what the app does: the needle sweeps in flat,
   overshoots sharp and settles, while the disc runs rust to amber to signal.
   ========================================================================== */

.loader { display: none; }

.js .loader {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--forest);
  /* 1350ms — must match DISSOLVE in main.js. If CSS were longer the veil
     would be torn from the DOM mid-fade; if shorter, the page would sit
     waiting behind nothing. */
  transition:
    opacity   1350ms var(--ease-soft),
    transform 1350ms var(--ease-soft);
}

/* Deliberately no scroll lock while the veil holds. overflow:hidden here
   prevents the browser restoring scroll position on reload — a reader who
   refreshed half way down the page was dumped back at the top. The veil is
   fixed and covers the viewport anyway. */

.loader__stage {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 30px;
}

.loader__disc {
  width: clamp(64px, 9vw, 104px);
  height: auto;
  color: var(--rust);
  animation:
    loader-in   1000ms var(--ease-soft) 150ms both,
    loader-tune 1400ms var(--ease-soft) 170ms both;
}

.loader__meter {
  position: relative;
  display: block;
  width: clamp(120px, 16vw, 180px);
  height: 10px;
  background:
    repeating-linear-gradient(to right,
      rgba(245, 239, 224, 0.22) 0 1px,
      transparent 1px 11px);
  background-size: 100% 6px;
  background-position: 0 2px;
  background-repeat: no-repeat;
  animation: loader-in 1000ms var(--ease-soft) 260ms both;
}

.loader__needle {
  position: absolute;
  top: -3px;
  left: 50%;
  width: 2px;
  height: 16px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--cream);
  animation: loader-needle 1400ms var(--ease-soft) 210ms both;
}

@keyframes loader-in {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes loader-tune {
  0%   { color: var(--rust);   }
  48%  { color: var(--amber);  }
  100% { color: var(--signal); }
}

/* Flat, sharp, then settling — a string being brought to pitch */
@keyframes loader-needle {
  0%   { transform: translateX(-54px); }
  50%  { transform: translateX(16px);  }
  74%  { transform: translateX(-6px);  }
  89%  { transform: translateX(2px);   }
  100% { transform: translateX(0);     }
}

/* Away — dissolving as it lifts toward the viewer, the disc going first and
   a touch further, so it feels passed through rather than faded out. */
.loader.is-done {
  opacity: 0;
  transform: scale(1.06);
  pointer-events: none;
}
.loader.is-done .loader__stage {
  opacity: 0;
  transform: scale(1.12);
  transition:
    opacity   950ms  var(--ease-soft),
    transform 1200ms var(--ease-soft);
}

/* The page is NOT animated. It sits at full opacity the whole time and the
   veil simply becomes transparent over it — a true cross-dissolve.

   It used to fade up from 0 while scaling down from 1.035, and that was the
   glitch: for the first half-second both layers were part-transparent at once,
   so the screen went muddy and then snapped clean. Scaling a 6600px-tall
   wrapper also forces the browser to rasterise an enormous layer mid-flight.
   Removing it costs nothing — all the depth is in the veil's own lift, which
   is one cheap viewport-sized layer. */

@media (prefers-reduced-motion: reduce) {
  .loader__disc,
  .loader__meter,
  .loader__needle { animation: none !important; }
  .loader__disc { color: var(--signal); }
  .js .loader { transition: opacity 220ms linear !important; }
  .loader.is-done { transform: none; }
  .loader.is-done .loader__stage { transform: none; transition: opacity 160ms linear; }
}


/* ==========================================================================
   18  MOTION
   Restrained by design: one fade-and-lift on entry, nothing else.
   ========================================================================== */

/* Keyframes, not transitions, and deliberately so.

   A transition only runs if the browser has already painted the start state.
   Get the ordering wrong by a single frame and the element jumps straight to
   its final position with no animation at all — which is exactly what was
   happening here, and no change of duration could have fixed it. An animation
   has no such requirement: it plays from its own first keyframe whenever the
   class lands. There is no race to lose. */
.reveal { opacity: 0; }

.reveal.is-visible {
  animation: reveal-in var(--dur-move) var(--ease) var(--delay-in) both;
}

/* Shorter travel over a longer duration, with a whisper of scale. 40px in
   1.9s reads as drifting; 34px with the element also easing up from 0.985
   reads as weight. Distance is what makes a slow move feel slow. */
@keyframes reveal-in {
  from { opacity: 0; transform: translate3d(0, 34px, 0) scale(0.985); }
  62%  { opacity: 1; }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

@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;
    scroll-behavior: auto !important;
  }

  /* Reduce motion, not feedback. The lift goes entirely — movement is what
     triggers vestibular responses — but a short cross-fade stays, which is
     considered safe and stops the page feeling inert. */
  .reveal.is-visible {
    animation: reveal-fade 260ms linear both !important;
  }
  @keyframes reveal-fade { from { opacity: 0; } to { opacity: 1; } }
}


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

@media print {
  body { background: #fff; color: #000; }
  .hero__split, .node__media, .node__veil, .cta__media, .stores { display: none !important; }
  .hero, .flow, .plate--omissions, .node, .cta { background: #fff !important; color: #000 !important; }
  .hero__headline, .flow__title, .omissions__title, .node__title, .cta__title,
  .omissions__name, .flow__label, .node__body, .cta__body, .omissions__desc {
    color: #000 !important;
  }
  .hero__wordmark, .colophon__mark { color: #000 !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
  .flow__list { display: grid !important; grid-template-columns: repeat(4, 1fr) !important; overflow: visible !important; }
}
