/* ============================================================================
   firstm.work — site.css

   The design system is the Ghost theme's (../../fm2-theme/home.hbs), adopted
   as a SYSTEM rather than copied rule by rule. Two rules govern this file:

     1. THE SCALE IS THE LAW. Every font-size is one of eight tokens. The
        theme's discipline is the point: it reuses each step many times (body
        appears 14 times, the mono step 13 times, one sub-head clamp serves
        every h3). A ninth size is the bug, not the feature — and two steps
        1px apart are one step with two names, which is how --t-sub died.

     2. SECTIONS ECHO EACH OTHER. The page is built from TWO blocks, each used
        four times, recombined into different layouts. Not one bespoke device
        per section.

   ── TYPE SCALE ──────────────────────────────────────────────────────────────
     --t-display    the hero h1, and nothing else: one display moment, the thesis
     --t-h2         section headings
     --t-feature    the hammer (the theme's pullquote step)
     --t-statement  the turn: the sentence a section pivots on
     --t-h3         every stack line, every ledger heading, AND the supporting
                    line under a major heading (hero sub, form intro)
     --t-body       all running prose, and every lead-in line
     --t-small      secondary and form labels
     --t-mono       every utility label, always mono, always uppercase

   Two departures from the theme, both deliberate:
   - --t-display 72px → 56px: the new thesis headline is 79 characters against
     the old one's 56.
   - --t-body 17px → 19px (Anton, 2026-08-20: the prose read "very small").
     This page carries far more running copy than the theme's did. Raising it
     forced two consequences, both of which turned out to be latent bugs the
     smaller body had been hiding: --t-sub (21px) collided with --t-h3 (22px)
     and merged into it, and the font-relative measures collapsed into the one
     fixed --m-block (see MEASURE below).

   Body was NOT raised all the way to the old --t-sub size, which was the first
   instinct. At 21px it collides with --t-h3, and then the pile, the loop steps,
   the FAQ questions and the guarantee rows all size-match ordinary prose —
   which is the only thing making the loop read as section 5's object rather
   than as another paragraph. body:h3 is now 1.21, not 1.05.

   ── THE TWO BLOCKS ──────────────────────────────────────────────────────────
   .stack   parallel short lines under a gold rule.
              s2 the four jobs (tight, unmarked)
              s4 the three chairs (tight, unmarked, on dark)
              s5 the weekly loop (numbered — a week's loop is ordered)
              s6 the four questions (quoted)
   .ledger  rows separated by hairlines, optional label column.
              s3 the costs, summing to the .statement below them
              s4 the proof, labelled with company and chair
              s7 the guarantee
              s9 the questions

   Both blocks share --m-block, so every rule on the page stops at one edge.
   Both work on paper and on the dark surface (the rule colour is a variable).

   ── THE SIGNATURES ──────────────────────────────────────────────────────────
   - Every heading ends in a GOLD TERMINAL MARK: a period, or the colon where
     the copy already has one. It is the wordmark's period, repeated.
   - Every section CLOSES THE SAME WAY: block → turn (.statement, ink,
     --t-statement) → landing (.hammer, gold, --t-feature). No exceptions; s3
     used to end on a 56px number above a 2px ink rule and read as an outlier
     from across the page.
   - Every block is introduced by ONE lead-in line at --t-body.
   - .eyebrow appears exactly TWICE (hero top, FOOTER): the copy's ring
     composition, literal in the type. It closes in the footer rather than at
     the end of s8 because s8 is not the end of the page — the FAQ sits below
     it, which muted the ring and left the line reading as a stray tagline.

   ── MEASURE ─────────────────────────────────────────────────────────────────
     --m-block   620px, FIXED. The page's ONE text measure: every paragraph,
                 every block and every rule stops at the same edge.
   ========================================================================= */

:root {
  /* ── Surfaces and ink ── */
  --bg: oklch(0.98 0.008 80);
  --cream: oklch(0.965 0.014 90);
  --ink: oklch(0.15 0.015 260);          /* headings, emphasis */
  --ink-2: oklch(0.32 0.015 260);        /* body text */
  --ink-soft: oklch(0.48 0.01 260);      /* utility labels */
  --ink-muted: oklch(0.62 0.008 260);    /* placeholders, helper text */
  --gold: oklch(0.72 0.13 80);
  --gold-ring: oklch(0.72 0.13 80 / 0.28);   /* focus ring: the gold at 28% */
  --rule: oklch(0.88 0.008 80);
  --danger: oklch(0.52 0.19 27);

  /* On the dark surface and in the footer. Three steps mirroring
     ink / ink-2 / ink-soft, so the dark sections use tokens rather than the
     ad hoc oklch() values the theme wrote inline. */
  --on-dark: oklch(0.97 0.005 80);
  --on-dark-2: oklch(0.80 0.008 80);
  --on-dark-soft: oklch(0.62 0.01 80);
  --dark-rule: oklch(0.28 0.01 260);

  /* ── Type ── */
  --font-primary: 'Inter Tight', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --t-display: clamp(34px, 5.6vw, 56px);
  --t-h2: clamp(28px, 4vw, 40px);
  --t-feature: clamp(24px, 3.2vw, 32px);
  --t-statement: clamp(20px, 2.8vw, 27px);
  --t-h3: clamp(20px, 2.4vw, 23px);
  --t-body: 19px;
  --t-small: 16px;
  --t-mono: 12px;

  --lh-display: 1.05;
  --lh-h2: 1.12;
  --lh-feature: 1.2;
  --lh-h3: 1.3;
  --lh-body: 1.6;

  --ls-display: -0.04em;
  --ls-h2: -0.03em;
  --ls-h3: -0.022em;
  --ls-body: -0.008em;
  --ls-mono: 0.14em;

  /* ── Measure ──
     ONE text measure. --m-prose (font-relative ch) and --m-short existed as
     separate roles, and raising body exposed both as bugs: `ch` scales with
     font-size, so prose landed at 604px against the blocks' 620px and could
     never hit it exactly at any size, while --m-short at 34ch resolved to 657px
     on the 32px hammer — WIDER than every block it was meant to sit inside.
     One fixed measure means every line of text and every rule on the page stops
     at the same edge. .hammer keeps text-wrap:balance to hold its rag. */
  --m-block: 620px;

  /* ── SPACE SCALE ──
     Five steps, assigned by ROLE, and every vertical gap on the page is one of
     them. Same law as the type scale: the page had fifteen ad hoc values
     (4/8/10/12/16/18/20/22/26/28/30/34/44/48/52) doing eight jobs, and gaps
     that differ by 2px are noise, not steps. What makes a section read as
     grouped beats rather than one undifferentiated column is the DIFFERENCE
     between these, so they sit far enough apart to be legible. */
  --s-tight: 8px;    /* inside a pile: lines that must accumulate, not breathe */
  --s-bind: 16px;    /* a lead, label or caption to the thing it introduces */
  --s-group: 24px;   /* items in a set; paragraphs in a run */
  --s-beat: 36px;    /* a sub-break within a movement */
  --s-move: clamp(40px, 6vh, 52px);   /* between movements INSIDE a section's body */
  --s-frame: clamp(56px, 8.5vh, 64px);/* the section's own frame: heading to body,
                                         and body to the landing line */
  --s-section: clamp(72px, 11vh, 90px);   /* the band itself */

  --gutter: clamp(20px, 5vw, 48px);
}

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

/* form.js toggles the [hidden] attribute; nothing may out-specify it. */
[hidden] { display: none !important; }

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

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-primary);
  font-weight: 400;
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--gold); color: var(--ink); }

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

/* Form controls inherit rather than take the UA default (13.33px), so every
   font-size on the page really is a scale token. The styled inputs override
   this below; this catches the radios and the honeypot. */
input, button, textarea, select { font-family: inherit; font-size: inherit; }

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

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

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

/* ===== Layout ===== */

.shell {
  max-width: 820px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.shell-wide {
  max-width: 920px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ===== Wordmark ===== */

.fm {
  font-family: var(--font-primary);
  font-weight: 700;
  font-size: 40px;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--ink);
}
.fm .p { color: var(--gold); }

/* ===== The mono utility voice =====
   One step, one treatment, every utility label on the page. */

.eyebrow,
.header-cta,
.btn-note,
.cred-tag,
.foot-actions .meta,
.colophon-meta,
.stack--numbered li::before {
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  font-weight: 500;
  letter-spacing: var(--ls-mono);
  text-transform: uppercase;
}

/* ===== Header ===== */

header { padding: var(--s-beat) 0 0; }
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-group);
}
.header-cta {
  color: var(--ink-soft);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 3px;
  transition: color .15s ease, border-color .15s ease;
}
.header-cta:hover { color: var(--ink); border-color: var(--gold); }

/* ===== Eyebrow — the slogan. Twice on the page, and that is the point. ===== */

.eyebrow {
  font-weight: 600;
  color: var(--gold);
  margin-bottom: var(--s-beat);
  /* Balanced so a narrow screen breaks the slogan between its sentences
     rather than orphaning "YOU." on its own line. */
  text-wrap: balance;
}

/* ===== Hero ===== */

/* Padded like every other band. The header above it already supplies the extra
   top air the two bespoke clamps here used to fake. */
.hero {
  border-top: none;
  padding: var(--s-section) 0;
}
.hero h1 {
  font-size: var(--t-display);
  font-weight: 700;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  color: var(--ink);
  text-wrap: balance;
  margin-bottom: var(--s-beat);
}
.hero .sub {
  font-size: var(--t-h3);
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  max-width: var(--m-block);
  text-wrap: pretty;
  margin-bottom: var(--s-frame);
}

/* ===== Buttons ===== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-bind);
  font-family: var(--font-primary);
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: -0.01em;
  background: var(--ink);
  color: #fff;
  padding: 16px 24px 17px;
  border: 1px solid var(--ink);
  border-radius: 0;
  cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
.btn:hover { background: #000; }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .55; cursor: default; }
.btn .arrow { display: inline-block; transition: transform .2s ease; }
.btn:hover .arrow { transform: translateX(3px); }

.btn-note {
  line-height: 1.5;
  color: var(--ink-soft);
  /* Binds to its button, in the hero and in the form alike. */
  margin-top: var(--s-bind);
}
/* Each phrase is unbreakable, so a narrow screen can only break these lines
   between sentences. text-wrap:balance is not enough on its own: it optimises
   line length, not meaning, and split "48 HOURS" and "FIRST / PROCESS" across
   lines. Applies to the slogan in both its places. */
.btn-note span,
.eyebrow span { white-space: nowrap; }

/* ===== Sections and surfaces ===== */

section {
  padding: var(--s-section) 0;
  border-top: 1px solid var(--rule);
}
section.surface-cream { background: var(--cream); }
section.surface-dark {
  background: var(--ink);
  border-top: none;
  color: var(--on-dark-2);
}
/* Dark surface to paper: the contrast is the boundary, no rule needed. */
section.surface-dark + section { border-top: none; }

.section-head { margin-bottom: var(--s-frame); }
/* A block that ends its section carries no trailing margin, or it stacks on
   top of the band's own padding. Same principle as .ledger's last row. */
section .shell > *:last-child { margin-bottom: 0; }
.section-head h2 {
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-h2);
  color: var(--ink);
  text-wrap: balance;
}
section.surface-dark .section-head h2 { color: var(--on-dark); }

/* ===== Prose =====
   Body is one size. Every paragraph and every block lead-in, in every section. */

.prose p,
.lead-line,
.faq-a,
.cred-desc,
.coda .line,
.submitted p {
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--ink-2);
  max-width: var(--m-block);
  text-wrap: pretty;
}
.prose p { margin-bottom: var(--s-beat); }
.prose p:last-child { margin-bottom: 0; }
.prose p strong { color: var(--ink); font-weight: 600; }
.prose a,
.submitted a {
  border-bottom: 1px solid var(--gold);
  color: var(--ink);
  transition: color .15s ease;
}
.prose a:hover, .submitted a:hover { color: var(--gold); }
section.surface-dark .prose p { color: var(--on-dark-2); }
section.surface-dark .prose p strong { color: var(--on-dark); }

/* Every block is introduced by ONE lead-in line, bound tightly to it.
   .block-lead additionally opens a new movement. */
.lead-line { margin-bottom: var(--s-bind); }
.block-lead { margin-top: var(--s-move); }

/* The turn: the sentence a section pivots on. It carries its own frame gap,
   because a turn always follows the section's body. This used to live in two
   identically-ruled classes, .posted-close and .ledger-sum, and a statement
   given neither (the About page's) had no gap at all. Where a turn follows a
   .section-head instead, the two --s-frame margins collapse to one, so putting
   it here is safe everywhere. */
.statement,
.lede {
  margin-top: var(--s-frame);
  font-size: var(--t-statement);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: var(--ls-h2);
  color: var(--ink);
  max-width: var(--m-block);
  text-wrap: balance;
}
.lede { font-weight: 500; text-wrap: pretty; margin-bottom: 0; }

/* A statement that CONTINUES a run of prose is a callout inside that run, not
   the section's turn, so it takes paragraph spacing on both sides and reads as
   an emphasised paragraph. A statement following a block (.stack, .ledger, a
   .section-head) is the turn and keeps the frame gap above. Expressed by
   position rather than a modifier class: the distinction is structural, and a
   rule that reads itself off the markup cannot be forgotten at a new call
   site. */
.prose + .statement {
  margin-top: var(--s-beat);
  margin-bottom: var(--s-beat);
}

/* The hammer: every section lands on one gold line. */
.hammer {
  font-size: var(--t-feature);
  font-weight: 500;
  line-height: var(--lh-feature);
  letter-spacing: var(--ls-h2);
  color: var(--gold);
  max-width: var(--m-block);
  text-wrap: balance;
  margin-top: var(--s-frame);
}
/* A hammer following the turn is the second half of one closing pair, so it
   keeps the tighter movement gap; the frame already sits above the turn. A
   hammer following body content IS the whole conclusion and takes the frame. */
.statement + .hammer { margin-top: var(--s-move); }

/* ============================================================================
   BLOCK 1 — .stack
   Parallel short lines under a gold rule. Four uses, one skeleton: the four
   jobs (s2), the three chairs (s4), the weekly loop (s5), the four questions
   (s6). What varies is the gap and whether the gutter carries a marker.
   ========================================================================= */

.stack {
  list-style: none;
  border-left: 2px solid var(--gold);
  padding-left: var(--s-group);
  max-width: var(--m-block);
  display: flex;
  flex-direction: column;
  gap: var(--s-group);
}
.stack li {
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  color: var(--ink);
  text-wrap: pretty;
}
section.surface-dark .stack li { color: var(--on-dark); }

/* Tight: the pile-up IS the argument, so the four jobs accumulate rather than
   breathe. Canon forbids bullets here — organised is exactly what the job is
   not — so the gold rule brackets them instead. */
.stack--tight { gap: var(--s-tight); }

/* The pile's last beat. Inside the rule, flush against the stack: the bold
   does the work, no gap needed. */
/* The flex gap already sits above this item, so subtract it: the visible gap
   is --s-bind, not --s-bind plus the stack's own gap. */
.stack-close {
  font-weight: 700 !important;
  margin-top: calc(var(--s-bind) - var(--s-tight));
}

/* Numbered: only where the content is genuinely ordered. A week's loop is. */
.stack--numbered { counter-reset: step; }
.stack--numbered li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: var(--s-bind);
}
.stack--numbered li::before {
  content: counter(step, decimal-leading-zero);
  font-weight: 600;
  color: var(--gold);
  padding-top: 6px;
}

/* ============================================================================
   BLOCK 2 — .ledger
   Rows separated by hairlines, closed top and bottom. Four uses: the costs
   (s3), the proof (s4), the guarantee (s7), the questions (s9). The optional
   label column carries the row's name.
   ========================================================================= */

.ledger {
  list-style: none;
  max-width: var(--m-block);
  --ledger-rule: var(--rule);
}
section.surface-dark .ledger { --ledger-rule: var(--dark-rule); }

/* Every text token with a light-ground colour needs its dark counterpart, or a
   block that works on the homepage renders dark-on-dark the first time it is
   used on the dark surface. The homepage never exposed this because its dark
   section uses .cred-desc, which carries its own colour; the About page's
   "The work" ledger did. */
section.surface-dark .ledger > *,
section.surface-dark .lead-line,
section.surface-dark .faq-a { color: var(--on-dark-2); }
section.surface-dark .statement,
section.surface-dark .lede,
section.surface-dark .ledger-label,
section.surface-dark .ledger strong,
section.surface-dark .ledger em { color: var(--on-dark); }

/* Row typography lives HERE, not in the prose group: a `.ledger li` selector
   up there would out-specify the .ledger--lead modifier below and silently
   hold every guarantee row at body size. */
.ledger > * {
  padding: var(--s-group) 0;
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--ink-2);
  text-wrap: pretty;
}

/* Rules BETWEEN rows only, never around the outside. A ledger's job is to
   divide rows from each other; a rule whose outer side is empty space is not
   separating anything, it just reads as a stray line — the top rule sat under a
   heading with nothing above it, and the bottom rule in the guarantee came
   between the last promise and its own gold landing line. The 52px movement
   gaps already bound the block. */
.ledger > * + * { border-top: 1px solid var(--ledger-rule); }
/* and with no outer rules, the outer padding is dead space that would push the
   movement gaps past --s-move. */
.ledger > *:first-child { padding-top: 0; }
.ledger > *:last-child { padding-bottom: 0; }

/* Rows that carry their own weight rather than describing a figure. Same
   specificity as the base rule, so source order decides. */
.ledger--lead > * {
  font-size: var(--t-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  color: var(--ink);
  padding: var(--s-group) 0;
}

/* A label column: the row's name beside the row's substance. Spans the full
   section column rather than --m-block, because 200px of it goes to the label
   and the substance still needs a readable measure. */
.ledger--labelled {
  max-width: none;
}
.ledger--labelled > * {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--s-beat);
  align-items: start;
}

/* ===== 2. The job you actually posted ===== */

/* The posting, quoted inline rather than boxed: it is the setup, and a second
   framed object beside the stack was the clumsiness. Mono marks it as lifted
   from a document; the gold rule is reserved for the payload below. */
.quoted {
  font-family: var(--font-mono);
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: var(--lh-h3);
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 0;
}


/* ===== 3. What the gamble costs ===== */

.ledger { margin-top: 0; }
/* The label cell: the row's figure or name. Regularised across all four rows,
   including the one the copy leaves unbolded, so the column reads as a column
   rather than as three bold leads and a stray. */
.ledger-label {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.015em;
}
.ledger em { font-style: normal; color: var(--ink); }

/* The sum is a .statement — the section's turn — not a bespoke object. It had
   been a 56px display number above a 2px ink rule, and both were outliers: no
   other section lands at display scale, and that rule weight and colour appear
   nowhere else on the page. The ledger already closes on its own hairline, and
   that closing rule IS the sum line an invoice needs. */

/* ===== 4. I've sat in both chairs (dark) ===== */

/* Centered, not start-aligned: the stack is shorter than the portrait, and
   start alignment left a void hanging under it. */
.chairs-open {
  display: grid;
  grid-template-columns: 210px 1fr;
  gap: var(--s-move);
  align-items: center;
  margin-bottom: var(--s-move);
}
/* Square, and deliberately so. At 5:6 with a tight centred crop against a
   plain wall this read as a passport photo; the ratio was the cause, not the
   corners. Rounding was tested and barely helped — and it would have been the
   only rounded object on a site whose two border-radius declarations are
   explicit zeroes. Square costs nothing in layout: the grid column is 210px
   either way, so the text beside it does not move. */
.portrait {
  width: 210px;
  height: 210px;
  overflow: hidden;
  background: var(--dark-rule);
}
.portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 20%;
  display: block;
}
/* On the homepage the portrait block opens its section, so the section-head
   supplies its gap. On the About page it concludes one, so it takes the same
   frame gap every other conclusion takes. */
.ledger + .chairs-open { margin-top: var(--s-frame); }

.chairs-lead {
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  color: var(--on-dark);
  margin-bottom: var(--s-bind);
}

.cred-name {
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  color: var(--gold);
  margin-bottom: var(--s-bind);
}
.cred-desc { color: var(--on-dark-2); max-width: none; }
/* Proof sentence first on every card; the detail exists to make it checkable. */
.cred-desc .proof { color: var(--on-dark); font-weight: 500; }
/* .case is the one sentence a card is really selling. Declared standalone, not
   scoped to .cred-desc, because the About page runs the same sentence inside a
   plain ledger row and the scoped rule silently did nothing there. */
.case { font-weight: 600; color: var(--ink); }
section.surface-dark .case { color: #fff; }
.cred-tag { color: var(--on-dark-soft); line-height: 1.5; }

/* ===== 5. How the process gets built ===== */

/* Two of the three words carry a gold rule: those are the ones that move. */
/* 2px, matching the stack's gold rule: the page has exactly two rule weights,
   1px hairlines and 2px gold. */
.jobs .moves { border-bottom: 2px solid var(--gold); padding-bottom: 2px; }
.jobs-legend { margin-top: var(--s-group); margin-bottom: 0; }

.after-loop { margin-top: var(--s-move); }

/* ===== 7. The guarantee ===== */

.guarantee-lead { margin-bottom: 0; }

/* ===== 8. Send the post — the form ===== */

#teardown { scroll-margin-top: 24px; }

.form-intro {
  font-size: var(--t-h3);
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  max-width: var(--m-block);
  text-wrap: pretty;
  /* --s-beat under its heading, exactly as .hero .sub sits under the h1. The
     section-head's own --s-move then separates the whole unit from the form. */
  margin-top: var(--s-beat);
}

.form { max-width: var(--m-block); }
.field { margin-bottom: var(--s-beat); }
/* Body size, not --t-small. A label must never be smaller than the text it
   labels: at 16px above a 19px input it dipped below its own field and made the
   80px frame gap above it look like a mistake. The label reads as a label by
   WEIGHT. Size now descends cleanly: 40 head, 23 intro, 19 label, 19 input,
   16 helper. */
.field label,
.fieldset-label {
  display: block;
  font-family: var(--font-primary);
  font-size: var(--t-body);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin-bottom: var(--s-bind);
}
.field input[type="text"],
.field input[type="email"] {
  display: block;
  width: 100%;
  font-family: var(--font-primary);
  font-size: var(--t-body);
  letter-spacing: var(--ls-body);
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 0;
  padding: 14px 16px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input::placeholder { color: var(--ink-muted); }
.field input:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--gold-ring);
}
/* form.js owns validation, so it owns this border too. :user-invalid was here
   and had to go: it fires on the browser's own constraints, which no longer
   match ours — a required field blurred while still empty went red with no
   message beside it, because the script deliberately stays quiet until there
   is something to correct. A red box that explains nothing is worse than no
   red box. Message and border now always appear together. */
.field input[aria-invalid="true"] { border-color: var(--danger); }
.helper {
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--ink-muted);
  margin-top: var(--s-bind);
}
/* Takes the helper's slot and metrics under the input, in the danger colour.
   Both can show at once: the helper explains, the error corrects. */
.field-error {
  font-size: var(--t-small);
  line-height: 1.5;
  font-weight: 500;
  color: var(--danger);
  margin-top: var(--s-bind);
}

.stage-set { border: 0; margin-bottom: var(--s-beat); }
.stage-options { display: flex; flex-wrap: wrap; gap: var(--s-bind); }
.stage-options label {
  position: relative;
  display: inline-flex;
  align-items: center;
  font-size: var(--t-body);
  letter-spacing: var(--ls-body);
  color: var(--ink-2);
  background: #fff;
  border: 1px solid var(--rule);
  padding: 12px 18px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.stage-options label:hover { border-color: var(--ink-muted); color: var(--ink); }
.stage-options input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.stage-options input:focus-visible { outline: none; }
.stage-options label:has(input:checked) {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}
.stage-options label:has(input:focus-visible) {
  box-shadow: 0 0 0 3px var(--gold-ring);
}

#turnstile-slot:not(:empty) { margin-bottom: var(--s-beat); }
.form .btn { margin-top: 0; }

.form-error {
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--danger);
  border-left: 2px solid var(--danger);
  padding-left: var(--s-group);
  margin-bottom: var(--s-group);
}

/* No movement gap: the coda opens with the button's own .btn-note, which binds
   to the button at 16px exactly as it does in the hero. Letting .coda push it
   to --space-block stranded the friction line halfway down the section. */
.coda {
  margin-top: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-group);
}
/* Classed, not `.coda p`: the coda also holds .btn-note and .eyebrow, and a
   type selector here would out-specify both. */
.coda .line { line-height: 1.55; }
/* The coda holds two different VOICES: the button's 12px mono note, then 19px
   prose. Spacing them identically made the register change read as an accident,
   so the prose opens with a full beat. (Minus the flex gap already above it.) */
.coda .btn-note + .line { margin-top: calc(var(--s-beat) - var(--s-group)); }


.noscript-note {
  font-size: var(--t-small);
  line-height: var(--lh-body);
  color: var(--ink-2);
  border-left: 2px solid var(--gold);
  padding-left: var(--s-group);
  margin-top: var(--s-group);
}

/* Post submit (site doc s10). The heading is a .section-head like every other
   section's, because after the swap it IS this section's heading. */
.submitted .section-head { margin-bottom: var(--s-frame); }
/* A block that ends its section carries no trailing margin, or it stacks on
   top of the band's own padding. Same principle as .ledger's last row. */
section .shell > *:last-child { margin-bottom: 0; }
.submitted p { margin-bottom: var(--s-beat); }
.submitted p:last-child { margin-bottom: 0; }

/* ===== 9. Fair questions ===== */

.faq-q {
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  color: var(--ink);
  margin-bottom: var(--s-bind);
  text-wrap: balance;
}

/* ===== Footer ===== */

footer {
  background: var(--ink);
  color: var(--on-dark-2);
  padding: var(--s-section) 0 var(--s-move);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-move);
  align-items: start;
  padding-bottom: var(--s-move);
  border-bottom: 1px solid var(--dark-rule);
}
.foot-brand .fm { font-size: 48px; color: #fff; line-height: 0.9; }
/* The ring closes here, in the treatment it opened in. .eyebrow's own
   margin-bottom is cleared: --s-beat below comes from .foot-social. */
.foot-slogan { margin: var(--s-group) 0 0; }
.foot-social { display: flex; gap: var(--s-group); margin-top: var(--s-beat); }
.foot-social a { color: var(--on-dark-soft); display: inline-flex; transition: color .15s ease; }
.foot-social a:hover { color: var(--gold); }
.foot-social svg { width: 22px; height: 22px; display: block; }

/* Same law as .ledger: rules between rows, never around the outside. This list
   had three rules for two links, one of them floating above the first with
   nothing over it. */
.foot-actions {
  display: flex;
  flex-direction: column;
}
.foot-actions a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-group);
  padding: var(--s-bind) 0;
  color: var(--on-dark-2);
  font-size: var(--t-small);
  line-height: 1.5;
  transition: color .15s ease;
}
.foot-actions a + a { border-top: 1px solid var(--dark-rule); }
.foot-actions a:first-child { padding-top: 0; }
.foot-actions a:last-child { padding-bottom: 0; }
.foot-actions a:hover { color: var(--gold); }
.foot-actions .meta { color: var(--on-dark-soft); flex-shrink: 0; }

.colophon {
  margin-top: var(--s-beat);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-group);
  flex-wrap: wrap;
}
.colophon-meta { color: var(--on-dark-soft); }

/* ===== Responsive =====
   The scale is already fluid: every step above body is a clamp, so the type
   resizes itself. What changes here is layout and rhythm, not sizes. */

/* The type and space scales are both fluid, so a phone needs almost no spacing
   overrides: tighten the two largest steps AT THE TOKEN and every gap on the
   page follows. What is left here is layout — grids collapsing — not spacing.
   Restating individual gaps down here is how the ad hoc values crept back in
   last time. */
@media (max-width: 720px) {
  :root {
    --t-body: 17px;
    --s-beat: 28px;
    /* The top three steps are pinned FLAT on mobile, and they have to move
       together. Pinning only --s-frame broke it twice over: the desktop clamp
       had resolved to ~57 on a phone, landing 7px from the 64px band padding so
       frame and section read as one gap; and leaving --s-move on its clamp let
       it reach 52 on a TALL phone (932px), i.e. larger than the pinned 48px
       frame — the movement gap outgrowing the frame it sits inside.
       40/48/64 holds the desktop proportions (1.20 / 1.33 vs 1.23 / 1.41). */
    --s-move: 40px;
    --s-frame: 48px;
    --s-section: 64px;
  }

  .header-cta { display: none; }

  .stack { padding-left: var(--s-group); }
  /* A phone is too narrow to hold the longest job line, so the pile relaxes one
     step: it has to stay legible as four things when one wraps to two lines. */
  .stack--tight { gap: var(--s-bind); }
  .stack--numbered li { grid-template-columns: 28px 1fr; }

  .ledger--labelled > * { grid-template-columns: 1fr; gap: var(--s-bind); }

  .chairs-open { grid-template-columns: 1fr; }
  .portrait { width: 148px; height: 148px; }

  .stage-options label { width: 100%; }

  .footer-grid { grid-template-columns: 1fr; padding-bottom: 0; border-bottom: none; }

  .btn { padding: 14px 20px 15px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  html { scroll-behavior: auto; }
}
