/* The two inner pages, Read my story and Apply.

   Loads after style.css and build3.css, so both inner pages inherit the whole
   homepage system for free: Koe's one heading style, the champagne accent, the
   grain, the cursor lift, and the word-by-word reveals. Nothing here changes a
   homepage rule. It only adds the four things the inner pages need that the
   homepage doesn't have: a top bar, a page header, a big photo, and a form.

   The design elements that tie these pages to the homepage are deliberately
   the ones already built, not new ones:
     1. The quiet dither field, same shader as the hero, behind each page
        header and masked the same way.
     2. The grain and the cursor lift, straight from build3.js.
     3. Gold rules that draw themselves across on scroll.
     4. The gold-under-the-cursor wash from the homepage's split sections,
        reused on the award photo at a lower strength.
   No new visual language. Just the homepage, one level down. */

/* ---------- top bar ---------- */

/* Not sticky. A fixed bar over a full-height page header would sit on top of
   the headline on a phone, and these pages are short enough that scrolling
   back up costs nothing. */
.pagenav {
  position: relative;
  z-index: 3;
  padding: 34px 0 0;
}

.pagenav .wrap {
  max-width: min(1180px, 92vw);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.pagenav .mark { display: block; }
/* Up from 132. At that size the wordmark read as a favicon rather than the
   site's name, which is the one thing the top left is for.

   184px, up from 168, because the file changed. The tight logo is 6.2:1 rather
   than 5:1, so at the old width it rendered shorter even though the letters got
   bigger. 184 puts the cap height back where it was and keeps the stroke well
   clear of a subpixel. */
/* 112, thirty per cent down from 160 on Sabby's eye. Renders about 18px tall.

   Worth knowing, because it's the one number here with a floor under it: the
   tight viewBox is 600.5 wide and the wordmark's stroke is 6.5 units, so the
   rendered stroke is 6.5 x width / 600.5. At 112 that's 1.21px, and 1.2px is
   the exact width that was breaking the crossbar on the E before the file was
   swapped. It holds here because the tight file has no padding to waste, so
   112px of box is 112px of ink, and on any 2x screen it lands on 2.4 device
   pixels and resolves cleanly. Checked at 1x and 2x.

   If it ever needs to go smaller than this, the fix is a heavier-stroke
   variant of the file, not a smaller number. */
.pagenav .mark img { display: block; width: 112px; height: auto; }

.pagenav .nav-right {
  display: flex;
  align-items: center;
  gap: 26px;
}

.navlink {
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 2.4px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color .2s ease;
}
.navlink:hover { color: var(--head); }

/* The small button in the bar. Same shape as .btn, two sizes down, so the
   page always has its call to action within reach without shouting. */
.btn-sm {
  display: inline-block;
  margin: 0;
  padding: 11px 24px;
  background: transparent;
  color: var(--head);
  border: 1px solid rgba(232, 232, 232, .28);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 2px;
  text-transform: uppercase;
  border-radius: 2px;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.btn-sm:hover { background: var(--accent); color: #000; border-color: var(--accent); }

/* ---------- page header ---------- */

/* Shorter than the homepage hero on purpose. The hero's job is to stop you,
   this one's job is to get out of the way of the reading. */
.pagehead {
  position: relative;
  overflow: hidden;
  /* No top padding. The nav sits inside this header now, so the dither field
     starts at the very top of the page instead of at the header's top edge,
     which was the logo's baseline and drew a seam straight under the
     wordmark. The nav brings its own 34px of top space and the headline gets
     its distance from the nav below. */
  padding: 0 0 76px;
  text-align: center;
}

/* Direct child only. The nav has a .wrap of its own and must not get this. */
.pagehead > .wrap { margin-top: 84px; }

.pagehead .wrap { position: relative; z-index: 1; }

/* More air under the section label than the homepage gives it. Up close the
   label read as part of the headline rather than a tag above it. */
.pagehead .label { margin-bottom: 34px; }
/* 24ch, up from 20. At 20 the two-sentence headline broke "Then we're" onto
   a line of its own, which orphaned the scarcity half of the line. */
.pagehead h1 { max-width: 24ch; margin: 0 auto 24px; }

/* Two rows, not three. Sabby, 2026-09-17: the story headline ran "I spent
   twelve years / optimising everything / except myself" because 24ch of a
   52px black weight is only about 750px, and that sentence needs roughly 860
   to sit on two lines. So the story header gets its own width, the same
   min(1180px, 92vw) the nav above it already uses, and the headline is let
   out to 960px inside it. No font size changed.

   text-wrap: balance does the actual splitting. It takes the fewest lines
   that fit and then evens them out, so the break stays sensible if the
   sentence is ever rewritten. Browsers without it fall back to a normal
   greedy wrap at the same width, which is still two lines. The apply page
   keeps the 24ch above, untouched. */
.storypage .pagehead > .wrap { max-width: min(1180px, 92vw); }

/* The header and the photo were one section while the photo sat under the
   headline. With v4 the photo is back inside the prose, so the header keeps
   the plain 76px of bottom padding from .pagehead above and nothing here
   pulls the two together. */
.storypage .pagehead h1 {
  max-width: 960px;
  text-wrap: balance;
}
.pagehead .lede {
  max-width: 46ch;
  margin: 0 auto;
  color: var(--fg);
}

/* ---------- the byline ---------- */

/* Face, name, read time. Sabby, 2026-09-18, to open the story the way a
   Substack essay opens: the reader sees who is talking and how long it takes
   before deciding to start. Centred under the lede, and it doubles as the
   divider between the header and the prose. */
.byline {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 34px auto 0;
}

/* The same circle treatment as the homepage portrait, at 52px instead of 200.
   The crop numbers are the homepage's, so the head sits in the same place in
   the circle on both pages: the image runs 150% wide and is pulled left and
   up, because a face centred in a square sits too low in a circle. */
.byline-face {
  flex: 0 0 52px;
  width: 52px;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  overflow: hidden;
  position: relative;
}
.byline-face img {
  position: absolute;
  display: block;
  width: 150%;
  height: auto;
  left: -11.76%;
  top: -9.07%;
  filter: contrast(1.03);
}

.byline-text {
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--fg);
  text-align: left;
}
.byline-sep { color: var(--fg-dim); margin: 0 4px; }
.byline-time { color: var(--fg-dim); }

/* Three facts as bullets rather than one sentence. Centred as a block but
   left-aligned inside it, because centred bullet text with a ragged left edge
   is unreadable. The marker is a champagne dash, set with ::before so it
   inherits nothing from the browser's list styling. */
.pagehead .lede-list {
  list-style: none;
  display: inline-block;
  text-align: left;
  margin: 0;
  padding: 0;
}
.pagehead .lede-list li {
  position: relative;
  padding-left: 22px;
  margin: 0 0 10px;
  font-size: 17px;
  line-height: 1.45;
  color: var(--fg);
}
.pagehead .lede-list li:last-child { margin-bottom: 0; }
.pagehead .lede-list li::before {
  content: "";
  position: absolute;
  left: 2px; top: .58em;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* The clock sits a shade smaller than the line and slightly raised, because a
   colour emoji at full body size next to Poppins reads as a sticker. */
.pagehead .lede-list .emoji {
  font-size: .9em;
  margin-left: 2px;
  vertical-align: 1px;
}

/* Same dither shader as the hero, same radial mask, mounted by pages.js.
   One WebGL context per page, which is well inside the browser cap. */
.field { position: absolute; inset: 0; z-index: 0; opacity: 0; transition: opacity 1.6s ease .2s; }
.field.on { opacity: 1; }
.field canvas { display: block; width: 100%; height: 100%; }
.pagehead .field {
  -webkit-mask-image: radial-gradient(ellipse 74% 70% at 50% 46%,
    transparent 0%, transparent 46%, rgba(0,0,0,.45) 76%, #000 100%);
  mask-image: radial-gradient(ellipse 74% 70% at 50% 46%,
    transparent 0%, transparent 46%, rgba(0,0,0,.45) 76%, #000 100%);
}

/* A single gold hairline under the page header, drawn left to right on load.
   This is the one motif that appears on both inner pages and nowhere else, so
   they read as a pair. */
/* The starting states below hang off .pjs, which pages.js adds to <html>
   as its first act. If pages.js never runs (an old browser, a module error)
   nothing is ever hidden, so a broken script can't swallow the photo or the
   rule. Same principle as the .js class in build3.css. */
.rule-gold {
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%, var(--accent) 14%, var(--accent) 86%, transparent 100%);
  opacity: .5;
  transform-origin: 50% 50%;
  transition: transform 1.4s cubic-bezier(.16, 1, .3, 1) .3s;
}
.pjs .rule-gold { transform: scaleX(0); }
.pjs .rule-gold.is-in { transform: scaleX(1); }

/* ---------- the story ---------- */

.story { padding: 88px 0 40px; }
.story + .story { border-top: 0; }

/* The story page runs 20% wider than the reading column it started at, Sabby's
   call. Set as --col on the body rather than as a max-width on each block, so
   the page header, the story, the photo, the closing line and the footer all
   move together and stay aligned down the left edge. 680 x 1.2 = 816.

   The apply page is untouched: it keeps the site default, and its form column
   caps itself tighter still at 620. */
.storypage { --col: 816px; }

/* Section subheads inside the story. Deliberately NOT the h2 monster: at 52px
   every subhead would be a new hero and the read would stop four times. */
.story h3 {
  font-size: 24px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.5px;
  color: var(--head);
  margin: 54px 0 22px;
}

/* The one pulled-out line per section. Gold, bigger, no quote marks, because
   it's Sabby's own sentence rather than a testimonial. */
.story .pull {
  font-size: 26px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.4px;
  color: var(--accent);
  margin: 40px 0;
  padding-left: 22px;
  border-left: 1px solid rgba(var(--accent-rgb), .38);
}

/* The realisations, in bold, with one word in the accent. Sabby, 2026-09-18:
   v4 runs with no section headings, so these are what breaks the page up and
   what somebody scrolling actually reads. 600, not the browser's synthetic
   700, because only 300/400/600/800/900 of Poppins are loaded and a
   synthesised weight looks smeared next to a real one. The brighter heading
   colour does as much of the work as the weight does. */
.story strong {
  font-weight: 600;
  color: var(--head);
}

/* The award photo now lives inside the story's .wrap, which already supplies
   the column width and the gutters, so the figure itself takes neither. More
   specific than .storypage .figure on purpose, so it wins wherever it sits. */
.storypage .story .figure {
  max-width: none;
  padding: 0;
  margin: 52px 0;
}

/* Full column width again. The 30% shrink was for the photo sitting under the
   headline, where it was a portrait of the man; in the body it's evidence, and
   the plaque has to be readable. The caption follows it back out to 64ch. */
.storypage .story .figure .shot { width: 100%; }
/* Centre-aligned under the photo, Sabby's call 2026-09-18, so the caption
   reads as part of the picture rather than as another line of the story. */
.storypage .story .figure figcaption { max-width: 64ch; text-align: center; }

/* The closing quote. Nothing uses this today: the Rolex line came off the
   page on 2026-09-18 and the story ends on its own last paragraph. Kept
   because the treatment is right if a closing line ever comes back, and it
   costs nothing.

   Centred and in quote marks, because it's a saying rather than a sentence of
   the story. No attribution: the whole page is already signed.

   Bigger than a .beat on purpose, 32 against 28, so the last line of the page
   is the largest thing in the prose and the beats read as steps towards it.
   32 rather than 33 because the second sentence is 45 characters and has to
   sit on one line in the reading column.
   No rule above it any more, Sabby 2026-09-18: it's the end of the story, not
   a separate block, and the page's second gold rule sits below it instead. */

/* The story ends on the quote instead of on a paragraph, so it needs more
   room underneath it than the 40px .story carries. */
.storypage .story { padding-bottom: 104px; }

.story .quote {
  font-size: 32px;
  font-weight: 800;
  line-height: 1.32;
  letter-spacing: -0.7px;
  color: var(--head);
  text-align: center;
  text-wrap: balance;
  max-width: 100%;
  margin: 62px auto 0;
  padding: 0;
  border: 0;
}

/* One sentence per line, two lines. Left to wrap on its own, balance split it
   mid-sentence, which read as an accident. */
.story .quote span { display: block; }
.story .quote span .accent { display: inline; }

/* One line above "By application only", not two. style.css draws a grey
   border on every `section + section` and build3.css replaces it with an
   animated pseudo-element; both are turned off for this page's closing
   section, because the gold rule in the markup is doing that job here. */
.storypage .close { border-top: 0; }
.js .storypage .close::before { display: none; }

/* ---------- the turns ---------- */

/* The one treatment for every pivot on this page. A short orange hairline,
   then the line centred, a notch bigger than the body, at the body's own 400
   weight. Most carry one orange word.

   It started as the quiet option for three lines that Sabby didn't want
   bolded, and on 2026-09-18 he moved every turn onto it and took the bold
   version out. So nothing on this page is bold now: the hairline does the
   separating that weight used to do, and the page reads calmer for it.

   Air and centring alone was too quiet, it read as a stray centred
   paragraph, which is why the hairline is there. Short is the whole point:
   the two full-width rules on this page are section breaks, and a 48px
   centred one is clearly a different object, the printed-essay break rather
   than the end of a chapter.

   44ch, wide enough that the longest of these sits on two lines. Deleting the
   class from a <p> puts that line straight back into the prose. */
.story .breath {
  font-size: 22px;
  line-height: 1.5;
  color: var(--head);
  text-align: center;
  text-wrap: balance;
  max-width: 44ch;
  margin: 60px auto;
}

.story .breath::before {
  content: '';
  display: block;
  width: 48px;
  height: 1px;
  margin: 0 auto 30px;
  background: var(--accent);
  opacity: .55;
}

/* The three questions people actually asked, as quotes rather than as a
   sentence. Accent dot, same as the homepage's "what we hear" list, because
   this page doesn't load build3-etched.css and can't borrow .reasons. */
.story .asks {
  list-style: none;
  margin: 30px 0 30px 4px;
  padding: 0;
}
.story .asks li {
  position: relative;
  padding-left: 22px;
  margin: 0 0 12px;
  font-size: 18px;
  line-height: 1.5;
  color: var(--fg);
}
.story .asks li:last-child { margin-bottom: 0; }
.story .asks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.story .kicker {
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 6px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--fg-dim);
  margin: 0 0 22px;
}

/* ---------- the award photo ---------- */

/* Same width as the copy, not a breakout. var(--col) plus the same gutters
   the text uses means the photo's left edge lands on the paragraph's left
   edge exactly, at every screen size, and it keeps doing that if --col
   changes again.

   sabby-award.jpg is already a true greyscale file, so there is no
   grayscale() filter here. The colour version sits beside it in assets if it
   is ever wanted. */
.figure {
  margin: 56px auto;
  width: 100%;
  max-width: var(--col);
  padding: 0 var(--gut);
}

/* 30% smaller and centred, Sabby's call 2026-09-17, now that the photo opens
   the page instead of sitting mid-story. The shrink happens on .shot, not on
   .figure, so the figure keeps the copy's column and gutters and the photo
   sits centred inside it. The caption centres with it, below. */
.figure .shot {
  width: 70%;
  margin-inline: auto;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: 2px;
  /* Same gold-under-the-cursor trick as the homepage split sections, set up
     here and driven by pages.js. */
  --mx: 50%; --my: 50%; --glow: 0;
}

.figure img {
  display: block;
  width: 100%;
  height: auto;
  /* A touch of contrast, because a greyscale jpeg off a stage screen runs
     flat against a pure black page. */
  filter: contrast(1.06) brightness(1.02);
}

/* The gold wash. Lower opacity ceiling than the homepage version (0.5 against
   1.0), because this is a photograph of a person and a full gold flood over a
   face looks like a mistake rather than a treatment. */
.figure .shot::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  opacity: var(--glow);
  transition: opacity .45s ease;
  background: radial-gradient(circle 280px at var(--mx) var(--my),
              var(--accent) 0%, var(--accent-mid) 44%, #ffffff 80%);
}
@media (hover: none) { .figure .shot::after { display: none; } }

/* Scale-in on scroll. 0.985 to 1, small enough to feel and not see, the same
   move the homepage portrait makes. */
.pjs .figure .shot { opacity: 0; transform: scale(.985); transition: opacity .9s ease, transform 1.2s cubic-bezier(.16, 1, .3, 1); }
.pjs .figure.is-in .shot { opacity: 1; transform: none; }

.figure figcaption {
  /* Centred on the photo, not on the column, so the block reads as one thing.
     64ch was the limit while the photo ran the full width; at 70% the photo is
     usually the narrower of the two, so the caption follows it in. */
  margin: 20px auto 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--fg-dim);
  max-width: min(64ch, 70%);
}

/* ---------- the form ---------- */

/* ---- form rhythm ----
   Three numbers run the whole form.

     --gap          every question to the next question. One value, no
                    exceptions, anywhere on the page.
     --gap-before   the end of one section to the next section's header.
     --gap-after    that header's rule down to its first question.

   --gap-before is three times --gap-after on purpose. A header sitting
   equidistant between two groups belongs to neither, which is why 01, 02 and
   03 read as floating labels rather than as the tops of sections. Pushing the
   space above them and closing the space below attaches each header to the
   questions underneath it, and the three sections separate without needing a
   box or a background to say so. */
.applypage { --gap: 30px; --gap-before: 132px; --gap-after: 30px; }

.applypage .form-wrap { max-width: 620px; }

/* The button sat too close to the footer rule. This is the only section on
   the page, so its bottom padding is the gap. */
.applypage .story { padding-bottom: 118px; }

.form { margin: 0; }

/* Groups rather than a single run of fields, so a ten-question form reads as
   three short ones. The count in the corner is the honest version of a
   progress bar: it tells you how much is left before you start. */
.fieldset {
  border: 0;
  margin: 0 0 var(--gap-before);
  padding: 0;
}
/* The last group runs into the button, not another header, so it takes an
   ordinary break rather than a section one. */
.fieldset:last-of-type { margin-bottom: 52px; }

.fieldset > legend {
  display: block;
  width: 100%;
  padding: 0 0 15px;
  margin: 0 0 var(--gap-after);
  /* A touch stronger than --rule, which at 14% was too faint to register as
     a section divider once there was real space around it. */
  border-bottom: 1px solid rgba(232, 232, 232, .22);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 6px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--fg-dim);
}

/* The number takes the accent, the word stays dim. Same treatment the
   homepage already gives the nine measurement tiles, where 01 to 09 sit in
   the accent above each label, so the numbering reads as one system across
   the site rather than a new idea on this page.

   The nbsp that used to separate the two is gone: the gap is a margin now, so
   it can be tuned without editing three lines of markup. */
.fieldset > legend em {
  font-style: normal;
  font-weight: 600;
  color: var(--accent);
  margin-right: 16px;
}

.field-row { margin: 0 0 var(--gap); }
.field-row:last-child { margin-bottom: 0; }

/* Two short fields side by side. Collapses to one column under 560px. */
.field-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  margin: 0 0 var(--gap);
}
.field-pair:last-child { margin-bottom: 0; }
.field-pair .field-row { margin: 0; }

/* Direct children only. The radio rows are <label class="choice"> elements
   living inside .field-row too, and a plain `.field-row label` out-specifies
   `.choice`, which stripped their display:flex and turned every dot into a
   sliver. The child combinator keeps the two label jobs apart. */
.field-row > label,
.field-row > .q {
  display: block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .3px;
  line-height: 1.4;
  color: var(--fg);
  margin: 0 0 10px;
}

.field-row > label .opt,
.field-row .opt {
  font-weight: 400;
  letter-spacing: 2px;
  font-size: 10px;
  text-transform: uppercase;
  color: var(--fg-dim);
  margin-left: 8px;
}

/* Underline fields, not boxes. Ten boxed inputs on a black page look like a
   tax return; ten rules look like a form someone designed. */
.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form input[type="number"],
.form select,
.form textarea {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(232, 232, 232, .22);
  border-radius: 0;
  padding: 10px 2px 12px;
  color: var(--head);
  font-family: var(--f);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.4;
  transition: border-color .22s ease;
}

.form textarea { resize: vertical; min-height: 96px; line-height: 1.5; }

.form input::placeholder,
.form textarea::placeholder { color: rgba(232, 232, 232, .3); }

.form input:focus,
.form select:focus,
.form textarea:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

/* The native select arrow is a light-mode grey lozenge in most browsers, so
   it gets replaced with a drawn chevron in the champagne. */
/* The placeholder sits dim so it can't be mistaken for an answer already
   given. pages.js adds .chosen the moment a real option is picked, and the
   text comes up to full white like every other filled field. */
.form select { color: var(--fg-dim); }
.form select.chosen { color: var(--head); }

.form select {
  cursor: pointer;
  padding-right: 28px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23F07A47' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 2px center;
}
.form select option { background: #0a0a0a; color: var(--head); }

/* Radio rows, drawn rather than native, because a native radio on a black
   page renders as a white blob in Chrome and a blue one in Safari. */
.choices {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* The radio block carries its own 14px of row padding, so left alone it
     added 28px to the gaps either side of the price question. These three
     numbers cancel that: the first option's text now starts the same distance
     below its question as an input's text does, the block ends the same
     distance above the next question, and -16px pulls the rows left so the
     option text lines up with every other answer on the page. */
  margin: -4px 0 -2px -16px;
}

.choice {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  transition: background .2s ease, border-color .2s ease;
}
.choice:hover { background: rgba(232, 232, 232, .035); }

.choice input {
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
}

.choice .dot {
  flex: 0 0 auto;
  width: 15px; height: 15px;
  margin-top: 3px;
  border: 1px solid rgba(232, 232, 232, .38);
  border-radius: 50%;
  position: relative;
  transition: border-color .2s ease;
}
.choice .dot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
  transform: scale(0);
  transition: transform .22s cubic-bezier(.16, 1, .3, 1);
}

/* Unanswered options sit dim. The one that gets picked comes up to full
   white, so the answer is readable at a glance on a page of three choices
   and you can see what you chose without hunting for the gold dot. */
.choice .txt {
  font-size: 16px;
  line-height: 1.45;
  color: var(--fg-dim);
  transition: color .22s ease;
}
.choice:hover .txt { color: var(--fg); }
.choice input:checked ~ .txt { color: var(--head); }

.choice input:checked ~ .dot { border-color: var(--accent); }
.choice input:checked ~ .dot::after { transform: scale(1); }
.choice:has(input:checked) { background: rgba(var(--accent-rgb), .06); border-color: rgba(var(--accent-rgb), .26); }
.choice input:focus-visible ~ .dot { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .2); }

/* A reassurance under an answer, not an instruction above it. Sits in the
   same dim grey as the section labels so it reads as the page talking rather
   than as part of the question. */
.form .hint {
  display: block;
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-dim);
}

/* Validation. Only ever shown after a submit attempt, never while typing,
   which is the difference between a form that helps and a form that nags. */
.form .err {
  display: none;
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.4;
  color: #E08A7A;
}
.form .field-row.bad .err { display: block; }
.form .field-row.bad input,
.form .field-row.bad select,
.form .field-row.bad textarea { border-bottom-color: #E08A7A; }

/* Centred, because the headline and the bullets above it are centred and a
   left-aligned button at the end of a centred page looks like it slipped. */
.form-actions { margin: 8px 0 0; text-align: center; }
.form .btn { margin-top: 0; }
.form .btn[disabled] { opacity: .5; pointer-events: none; }

/* No max-width. The 52ch cap wrapped this at about 400px inside a 620px
   column, which left a ragged hole on the right under a full-width form and
   was the thing that looked broken. It runs the width of the column now. */
.form-note {
  margin: 24px auto 0;
  max-width: 44ch;
  font-size: 13px;
  line-height: 1.6;
  color: var(--fg-dim);
}

/* ---------- the thank you state ---------- */

/* Same page, swapped in place rather than a second URL. Nothing to deploy, no
   redirect to get wrong, and the back button still works the way people
   expect. */
.form-done { display: none; padding: 20px 0 0; }
.form-done.on { display: block; }
.form.off { display: none; }

.form-done .tick {
  width: 46px; height: 46px;
  margin: 0 0 28px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.form-done .tick svg { display: block; }
.form-done h2 { font-size: 34px; letter-spacing: -0.8px; margin-bottom: 20px; }
.form-done p { max-width: 48ch; }

/* The spam trap. Off screen rather than display:none, because some bots skip
   anything that's hidden outright and fill anything that isn't. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Chrome and Safari draw the number spinner as a pale grey lozenge that sits
   badly on an underline field. */
.form input[type="number"]::-webkit-outer-spin-button,
.form input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.form input[type="number"] { -moz-appearance: textfield; }

/* ---------- the accent hairline above the footer ----------
   Copied from build3-etched.css rather than rewritten, values and all, so the
   lander and the two inner pages draw one line instead of three near-misses.
   It's the same motif already sitting under each page header here as
   .rule-gold.

   style.css puts a plain border on the footer and a border can't be animated,
   so it's made transparent and a scalable line drawn in its place, which is
   the trick build3.css already uses on `section + section`. build3.js watches
   `footer` and adds .is-in, so the script side needed nothing.

   The starting state hangs off .js. If the script never runs, the plain
   border is simply still there and the footer keeps a top edge. */
.js footer { position: relative; border-top-color: transparent; }
.js footer::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%, var(--accent) 14%, var(--accent) 86%, transparent 100%);
  opacity: .5;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1.15s cubic-bezier(.16, 1, .3, 1);
}
.js footer.is-in::before { transform: scaleX(1); }

/* ---------- footer colophon ----------
   The homepage gained this at 11:46 today and these two pages predated it.
   Values copied from build3-etched.css rather than re-invented, so the three
   footers are identical. */
footer .fineprint { margin-top: 42px; }
footer .colophon {
  margin-top: 7px;
  font-size: 12px;
  letter-spacing: .06em;
  color: rgba(232, 232, 232, .38);
  margin-bottom: 0;
}

/* ---------- responsive ---------- */

@media (max-width: 767px) {
  .pagenav { padding-top: 24px; }
  .pagenav .mark img { width: 94px; }
  .pagenav .nav-right { gap: 16px; }
  .pagehead { padding: 0 0 56px; }
  /* 78, up from 48, in two goes: 68 first, then 78 on Sabby's eye. Desktop gives this gap 84px and the
     phone was taking nearly half of it away, which left the label sitting under
     the wordmark rather than starting a page of its own. Both inner pages take
     it, because a different gap on each would read as an accident. */
  .pagehead > .wrap { margin-top: 78px; }
  /* The v4 headline is seventeen words. At the site's 39px phone heading it
     took seven lines and pushed the first paragraph off the screen, so the
     story page alone comes down to 32. The homepage and the apply page keep
     39. */
  .storypage .pagehead h1 { font-size: 32px; letter-spacing: -0.7px; }
  .pagehead .lede-list li { font-size: 16px; }
  .pagehead .label { margin-bottom: 26px; }
  .applypage { --gap-before: 92px; }
  .applypage .story { padding-bottom: 84px; }
  .story { padding: 64px 0 32px; }
  .story h3 { font-size: 21px; margin-top: 44px; }
  .story .pull { font-size: 21px; margin: 32px 0; padding-left: 16px; }
  .story .quote { font-size: 24px; margin-top: 44px; }
  .story .asks li { font-size: 17px; }
  .story .breath { font-size: 20px; margin: 44px auto; max-width: none; }
  .story .breath::before { margin-bottom: 24px; }
  .byline { margin-top: 26px; gap: 12px; }
  .byline-face { flex-basis: 46px; width: 46px; }
  .byline-text { font-size: 14px; }
  .storypage .story { padding-bottom: 76px; }
  .storypage .story .figure { margin: 36px 0; }
  /* No full-bleed override any more. The photo is the width of the copy now,
     so it lines up with the paragraphs on a phone the same way it does on a
     desktop, and the gutters stay consistent down the whole page. */
  .figure { margin: 40px auto; }
  /* The 30% shrink is a desktop move. On a phone the column is already
     narrow, so the photo takes all of it. */
  .figure .shot { width: 100%; }
  .figure figcaption { font-size: 14px; max-width: none; margin: 16px 0 0; }
  .field-pair { grid-template-columns: 1fr; gap: var(--gap); }
  .form-done h2 { font-size: 28px; }
}

@media (max-width: 480px) {
  .pagenav .navlink { display: none; }   /* the button survives, the link goes */
}

@media (prefers-reduced-motion: reduce) {
  .rule-gold { transform: scaleX(1) !important; transition: none !important; }
  .js footer::before { transform: scaleX(1) !important; transition: none !important; }
  .pjs .figure .shot { opacity: 1 !important; transform: none !important; transition: none !important; }
}
