/* ============================================================
   AgentCTO — site styles

   Colour tokens: graphite-teal (light mode)
     Source: DesignTokens/themes/graphite-teal/tokens.css
     Copied verbatim so re-syncing is a clean diff against source.
     That file is colour-only by design; type, space, radii,
     shadow and motion are defined in the second :root below.

   Contrast rules (measured, see page-spec.md):
     --color-text          15.35:1 on bg  → headings + body copy
     --color-text-muted     6.04:1 on bg  → secondary/meta only
     --color-text-subtle     4.23:1 on bg  → FAILS AA for body text.
                                            White surface or large
                                            text only. Never on bg.
   ============================================================ */

:root {
  /* ── Teal ramp — brand + success ── */
  --color-teal-50: #e7faf8;
  --color-teal-100: #c0e2df;
  --color-teal-200: #95ccc6;
  --color-teal-300: #67b6ae;
  --color-teal-400: #34a095;
  --color-teal-500: #00877c;
  --color-teal-600: #006c62;
  --color-teal-700: #00534a;
  --color-teal-800: #003a33;
  --color-teal-900: #05231e;
  --color-teal-950: #030e0b;

  /* ── Graphite ramp — neutrals ── */
  --color-graphite-50: #f2f5fb;
  --color-graphite-100: #d5dae4;
  --color-graphite-200: #b7c0cf;
  --color-graphite-300: #9aa7ba;
  --color-graphite-400: #7f8ea4;
  --color-graphite-500: #66768d;
  --color-graphite-600: #4f5e73;
  --color-graphite-700: #3c4858;
  --color-graphite-800: #2a323d;
  --color-graphite-900: #191e24;
  --color-graphite-950: #090b0e;

  /* ── Semantic — surfaces & neutrals ── */
  --color-bg: #f2f5fb;
  --color-surface: #ffffff;
  --color-surface-muted: #d5dae4;
  --color-border: #d5dae4;
  --color-border-strong: #b7c0cf;

  /* ── Semantic — text ── */
  --color-text: #191e24;
  --color-text-muted: #4f5e73;
  --color-text-subtle: #66768d;
  --color-text-on-primary: #ffffff;
  --color-text-inverse: #f2f5fb;

  /* ── Semantic — primary / brand action ── */
  --color-primary: #006c62;
  --color-primary-hover: #00534a;
  --color-primary-active: #003a33;
  --color-primary-text: #00534a;
  --color-primary-subtle: #e7faf8;
  --color-primary-subtle-border: #c0e2df;
  --color-focus-ring: #00877c;

  /* ── Red ramp — error. Restored from source for the S5 form's
     validation states. Amber is still omitted; the page has no
     warning state. ── */
  --color-red-50: #fff2ef;
  --color-red-100: #ffccc2;
  --color-red-600: #b10015;
  --color-red-700: #890011;

  /* ── Semantic — error (red) ── */
  --color-error: #b10015;
  --color-error-text: #890011;
  --color-error-bg: #fff2ef;
  --color-error-border: #ffccc2;

  /* Input boundaries are UI components under WCAG 1.4.11 and need 3:1
     against their surface. Measured on white: --color-border is 1.40:1
     and --color-border-strong is 1.83:1, so NEITHER is legal here.
     graphite-400 is the lightest ramp step that passes, at 3.33:1.
     Do not "harmonise" this back to --color-border. */
  --color-input-border: #7f8ea4;
}

:root {
  /* ── Type scale — Perfect Fourth (1.333), carried from the retired theme.css ── */
  --text-sm:   clamp(0.75rem,  0.72rem + 0.15vw, 0.875rem);
  --text-base: clamp(1rem,     0.95rem + 0.25vw, 1.125rem);
  --text-lg:   clamp(1.125rem, 1.05rem + 0.38vw, 1.333rem);
  --text-xl:   clamp(1.333rem, 1.15rem + 0.75vw, 1.777rem);
  --text-2xl:  clamp(1.5rem,   1.25rem + 1.25vw, 2.369rem);
  /* Ceiling is 2.65rem rather than the scale's 3.157rem. At 3.157rem an h2
     rendered 50.5px, and three of the page's six headings needed 768-826px
     on one line inside a 712px column. Each missed by under 15%, so
     text-wrap: balance split them at the most even point, which stranded
     the subject and copula alone on line one ("The solution is" / "rarely
     another tool."). Capping at 42.4px lets all three sit on one line; the
     widest lands at 693px, leaving 19px of slack. The two genuinely long
     headings still wrap, which is correct. Raising this ceiling without
     re-measuring those three will bring the fragment breaks back.

     The floor and slope are lower than the scale's so that the hero h1
     outranks the h2s on a phone. At 390px the h2 was 31.3px against the
     h1's 37.9px, only 1.21x, and S4's heading ran to four lines, which made
     it heavier than the two-line hero. Now the h2 is 26.2px (1.45x) and S4
     takes three. The ceiling is reached at 1200px rather than 981px, so
     between 760px and 1200px the h2 is smaller than it was. In a column
     that is still 712px wide, that can only take wraps away.

     All of this was measured in the old single 712px column. The homepage
     now sets its h2s in columns from about 424 to 912px wide at desktop,
     so re-measure there before changing any of it. */
  --text-3xl:  clamp(1.625rem, 1.15rem + 2vw, 2.65rem);
  --text-4xl:  clamp(2.25rem,  1.7rem + 2.75vw, 4.209rem);

  /* ── Spacing — 8px grid, carried from the retired theme.css ── */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.5rem;
  --space-6:  2rem;
  --space-7:  2.5rem;
  --space-8:  3rem;
  --space-9:  4rem;
  --space-10: 5rem;

  /* ── Layout ── */
  --measure: 760px;        /* reading column, up from 600px */
  --measure-wide: 960px;   /* homepage sections that lay out in columns, down from 1200px */
  /* Floor is 5rem, up from 4rem. At 4rem a phone got 32px on each side of
     a section boundary, the same as the 32px gaps inside a section, so the
     1px rule was the only thing marking the break. At 5rem a phone gets
     24px above the rule (from .flow) and 40 below it: 65 from text to
     text, against 24 for most gaps inside a section. The widest inside
     gap, the 64 before S3's closing statement, matches it but has no
     rule. The ceiling is unchanged, so desktop still spends 112px. The
     phone figures are from the old single-column layout. */
  --section-y: clamp(5rem, 9vw, 7rem);

  /* ── Radii — restrained vs. the old 20px cards ── */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* ── Elevation — borders do most of the work in light mode ── */
  --shadow-sm: 0 1px 2px rgba(25, 30, 36, 0.04);
  --shadow-md: 0 2px 8px rgba(25, 30, 36, 0.06);

  /* ── Motion ── */
  --ease: 180ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ============================================================
   Base
   ============================================================ */

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

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

  /* The palette is light-only, so say so. Keeps form controls,
     scrollbars and the pre-paint canvas light on dark-mode systems. */
  color-scheme: light;
}

/* Stand-in for Plus Jakarta Sans until it loads. Before this the page
   drew first in the system font, which sets narrower. The homepage came
   out 99px shorter on desktop, where the h1 fit on one line instead of
   two, and 108px shorter on a phone, then jumped when Jakarta arrived.

   These faces are Arial scaled to Jakarta's widths, so lines break in
   nearly the same places. size-adjust is Jakarta's width over Arial's
   across the text of both pages, measured per weight, which is why
   there are three faces and not one. Arial has no 600, so 600 and 700
   both draw Arial Bold, at different scales. The overrides are Jakarta's
   ascent (1.038em) and descent (0.222em) divided by size-adjust, which
   scales them too.

   Android has no Arial and skips these faces. Safari applies
   size-adjust but not yet the overrides. Those only place glyphs within
   a line, since every line-height here is set explicitly. */
@font-face {
  font-family: "Jakarta Fallback";
  src: local("Arial"), local("ArialMT");
  font-weight: 400;
  size-adjust: 104.92%;
  ascent-override: 98.93%;
  descent-override: 21.16%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Jakarta Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT");
  font-weight: 600;
  size-adjust: 100.04%;
  ascent-override: 103.76%;
  descent-override: 22.19%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Jakarta Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT");
  font-weight: 700;
  size-adjust: 100.95%;
  ascent-override: 102.82%;
  descent-override: 21.99%;
  line-gap-override: 0%;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: "Plus Jakarta Sans", "Jakarta Fallback", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   Typography
   ============================================================ */

h1, h2, h3 {
  margin: 0;
  color: var(--color-text);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-4xl);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.022em;
}

h2 {
  font-size: var(--text-3xl);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.018em;
}

h3 {
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* Measures are in em, not ch. A ch is the width of the "0" in whichever
   font is drawing, so a ch measure changed size when Plus Jakarta Sans
   replaced the fallback: 0.732em per ch in Jakarta at 400, 0.606em in the
   macOS system font. Chrome also did not always re-resolve it after the
   swap. In one of three headless renders the statements kept the
   fallback's 617px with Jakarta's wider text inside, and S2's ran to
   three lines, moving everything below it down 39px. An em is the same
   in any font.

   Each value is the old ch measure at Jakarta's widths, so nothing moves
   once the font has loaded: 47.58em is 65ch, .lead's 39.53em is 54ch, and
   .statement's 24.34em is 34ch at 600, where Jakarta's 0 is 0.716em. */
p {
  margin: 0;
  max-width: 47.58em;
}

/* Lead paragraph — hero subhead and section intros */
.lead {
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--color-text);
  max-width: 39.53em;
}

/* Quieter supporting line. Secondary by intent, so muted is correct. */
.note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Horizontal rule. The UA default is a 2px inset groove with margins of
   its own; both are reset. Spacing comes from the layout around it, so
   it carries none of its own. On index.html it closes the hero, the one
   plain section followed by another plain one; the bands mark their own
   edges. */
hr {
  margin: 0;
  border: 0;
  border-top: 1px solid var(--color-border);
}

/* Elevated single statement — the line under the S3 steps */
.statement {
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--color-text);
  max-width: 24.34em;
  border-left: 3px solid var(--color-primary);
  padding-left: var(--space-5);
}

.eyebrow {
  display: inline-block;
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary-text);
}

a { color: var(--color-primary); }

/* Screen-reader-only. Used by the skip link. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The skip link has to show itself when it takes focus. Hidden and
   focused at once, a keyboard user tabs onto nothing they can see, which
   fails WCAG 2.4.7. This undoes .sr-only's clipping and lays it over the
   top-left of the header. :focus rather than :focus-visible, so no
   heuristic can leave it focused and invisible. */
.skip-link:focus {
  position: fixed;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 10;
  width: auto;
  height: auto;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  overflow: visible;
  clip-path: none;
  background: var(--color-surface);
  color: var(--color-primary-text);
  font-weight: 600;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

a:focus-visible,
.btn:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

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

.wrap {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

/* The homepage's container, and the header and footer on both pages.
   Its sections set things side by side (the hero beside its card, the
   offer beside its form), so they take 960px. The design's 1200px read
   as too wide on a 1440px screen. Paragraphs inside keep
   their own em measure, and centred heads cap at --measure (see
   .section-head). The privacy page shares the header and footer so the
   logo does not move when you click through, and keeps its policy text
   in .wrap. */
.wide {
  max-width: var(--measure-wide);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

/* Half, not the full token, because vertical padding does not collapse
   between siblings the way margins do. Two adjacent sections each carrying
   a full --section-y summed to 224px of dead space at every boundary on
   the page. Half on each side means a boundary spends one --section-y
   total, which is what the token was always meant to express. Read it as
   "each section contributes half the gap", not as "sections are padded". */
section { padding-block: calc(var(--section-y) / 2); }

/* Bands are the exception: they own their internal padding rather than
   contributing half a gap. The colour change already marks the boundary,
   so the space is doing a different job inside them, and half a token
   would crowd the content against the edge of the fill.

   A plain section set between two bands takes the full token too
   (.section-full). Neither band gives a half-gap to the boundary, so on
   half a token its content would sit 56px from each fill's edge while
   the bands' own content sits 112px in. */
.section-dark,
.section-tint,
.section-full { padding-block: var(--section-y); }

/* The first section already has separation above it: the nav's own
   padding plus its bottom rule. Even half a --section-y on top of that
   reads as a hole rather than rhythm, so it opens on a shorter measure.
   The homepage hero adds its own padding to this (see .hero). */
main > section:first-child { padding-top: var(--space-8); }

/* Section rhythm for a single column of text: the privacy policy.

   Margins rather than a gap, because a gap is one value for every pair
   and .prose sets its topic headings further out than the text between
   them. The grid stays for the single column, and the explicit single
   column is load-bearing. `justify-items: start` would size the column
   to content, which breaks any child relying on a percentage width.
   Inline-level children (buttons) must therefore sit in their own
   wrapper, since grid items get blockified. Grid items' margins do not
   collapse, so a child's margin-top is exactly its distance from the
   child above.

   :not(:first-child) rather than * + *, for its specificity. At (0,2,0)
   the default beats .marked-list, which resets margin to 0 with a single
   class further down the file. */
.flow { display: grid; grid-template-columns: minmax(0, 1fr); }
.flow > :not(:first-child) { margin-top: var(--space-5); }

/* An h1 is 67px on desktop, and 24px under it is tighter than that size
   can carry. */
.flow > h1 + .lead { margin-top: var(--space-6); }

/* Horizontal group — buttons, inline actions */
.row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.875rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font: inherit;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--ease), border-color var(--ease), color var(--ease);
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-text-on-primary);
}
.btn-primary:hover  { background: var(--color-primary-hover); }
.btn-primary:active { background: var(--color-primary-active); }

/* A second action set beside a button: the hero's "How I work". Teal-700
   at 600 holds its own next to the solid button without competing with
   it. The UA underline stays, since underlined teal is what a link looks
   like on this page. */
.text-link {
  color: var(--color-primary-text);
  font-weight: 600;
}

/* ============================================================
   Nav — logo + single CTA, no links
   ============================================================ */

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-5);
  border-bottom: 1px solid var(--color-border);
}

/* Used in both the header and the footer. The logo is a single SVG that
   already contains the wordmark, so there is no text node and none of the
   old type properties apply. inline-flex plus a block img kills the
   inline-baseline gap under the image. */
.nav-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

/* 44px, not 32. The artwork box includes the "A" apex above the cap line
   and the "g" descender below it, so the wordmark reads at roughly half
   the box height. At 32px it sat visibly lighter than the nav button. */
.nav-logo img {
  display: block;
  height: 44px;
  width: auto;
}

@media (max-width: 640px) {
  /* Pre-existing, surfaced by the logo swap: the nav CTA needs 213px on one
     line and the content column is 312px, so the label wrapped to two lines
     even with the old 32px mark. No logo size fixes that. Let the button
     take its own row instead of squeezing it. */
  .nav { flex-wrap: wrap; }
  .nav .btn { white-space: nowrap; }
}

/* ============================================================
   Section banner — S2

   Abstract line art. It carries no information the copy does not
   already state, so alt is empty and it stays out of the
   accessibility tree. Describing it would make a screen reader
   narrate a drawing to reach a point the next heading makes in
   seven words.

   The width/height attributes in the markup are the intrinsic
   pixels. They only reserve the aspect ratio, which matters because
   the image is lazy-loaded and would otherwise shove the section
   down when it arrives.

   This carried `mix-blend-mode: multiply` while the asset was a PNG.
   That was a workaround for an opaque white ground showing as a
   rectangle against the page, and process-banner.svg has a
   transparent one, so the workaround is gone rather than inherited.
   Putting it back would darken the artwork against the page for no
   gain. The animation lives inside the SVG; there is nothing to
   drive from here.
   ============================================================ */

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

/* 80% of the column rather than full width, for the S2 process banner:
   at the full width of the old 712px column it outweighed the h2 beneath
   it. In the homepage's 912px column that is 730px, inside the 760px head
   under it; the cap at --measure keeps it there if the column widens.
   Centred, so the spare width
   splits either side instead of sitting as a gap beside the chevron.
   Auto margins rather than justify-self, so it centres in a grid track
   and in normal flow alike. Sized here rather than in the SVG so the
   drawing's own proportions, stroke weights and timings are untouched.
   banner-gravity.js copies the img's classes onto its inline
   replacement, so this survives the upgrade. */
.banner-narrow { width: 80%; max-width: var(--measure); margin-inline: auto; }

/* A banner that opens a section does not pay the section's top half-gap.

   Every section contributes half a --section-y above and below, so a
   boundary normally spends 112px (see the section rule near the top of
   Layout). That rhythm is right when a heading opens the section: the
   type has weight at its top edge and the space reads as separation.
   A banner does not. It is light line art with its own internal margin,
   so the same 112px reads as a hole with a drawing floating in it.

   Negative margin, not a reduced padding-block on the section, because
   the section's bottom half-gap is still correct and should not move.
   Expressed against the token so it tracks any change to --section-y
   rather than drifting into a stale pixel value.

   On the homepage the section above is the hero, which closes on its
   <hr> with no half-gap under it (see .section-hero), so the banner's
   box starts at the rule. What shows between the rule and the drawing
   is the SVG's own transparent margin: process-banner.svg draws from y25
   in a 380-unit viewBox, about 15px at its full 730px. That gap is the
   asset's, not the layout's, and changing it means cropping the viewBox
   rather than adding a pixel fudge here.

   It assumes the section above closes on an <hr>. The rule is what
   separates the two sections; this only removes the dead air under it.
   With no rule above it, a banner reads as the underline of whatever
   comes before. That was the old S3, whose method banner sat 56px under
   a pull-quote. It now sits inside its band's head, out of this rule's
   reach. */
section > .banner:first-child { margin-top: calc(var(--section-y) / -2); }

/* ============================================================
   Section bands

   .section-dark remaps the semantic text tokens rather than
   restyling each child, so components dropped inside it adapt
   on their own. Measured against graphite-900:
     graphite-50   15.35:1   body + headings
     graphite-200   9.15:1   muted
     teal-200       9.37:1   eyebrow
   --color-primary is remapped for accents, which means .btn-primary
   is NOT usable directly in here (teal-300 fill would leave white
   text at ~2.3:1). The band's only button sits inside .form-card,
   which restores the light tokens. A button placed directly in the
   band needs an inverse style first: white fill with a teal-700
   label measured 8.99:1.
   ============================================================ */

.section-dark {
  background: var(--color-graphite-900);

  /* Setting `color` here is load-bearing, not redundant with the token
     remap below. Inheritance passes the COMPUTED colour down, not the
     var() reference: body resolves `color: var(--color-text)` once,
     against the light value. Elements with no colour rule of their own
     (plain <p>, <li>) would inherit that dark value and vanish against
     this background. Only elements that re-read the token themselves
     (h1-h3, .lead, .statement) would survive. */
  color: var(--color-text);

  --color-text: var(--color-graphite-50);
  --color-text-muted: var(--color-graphite-200);
  --color-border: var(--color-graphite-700);
  --color-surface: var(--color-graphite-800);
  --color-primary: var(--color-teal-300);
  --color-primary-text: var(--color-teal-200);
}

.section-tint { background: var(--color-primary-subtle); }

/* ============================================================
   Hero — S1

   The pitch on the left and, on the right, a card saying who is
   making it. The bio used to sit near the end of the page; here it
   answers "who is this?" before the first scroll.

   1.6fr to 1fr, so the copy keeps a reading width, 532px of the
   912px column, and the card stays narrow enough to read as an
   aside rather than a second column of copy.
   ============================================================ */

/* The hero closes on its <hr> with no half-gap under it, so S2's banner
   pull-up brings the drawing up to the rule. The space above the rule
   is .hero's own padding. */
.section-hero { padding-bottom: 0; }

/* The top padding adds to the first section's 48px (main >
   section:first-child), so the hero starts 80px under the nav.
   The gap is 48px so the chain (see .chain) holds one line beside the
   card. At 64px it wrapped from 1647px up: --text-sm grows until about
   1650px, and the copy column stopped at 522px. */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: center;
  padding-block: var(--space-6) var(--space-9);
}

.hero-copy { display: grid; gap: var(--space-6); }

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-5);
}

.cred {
  display: grid;
  justify-items: center;
  gap: var(--space-5);
  padding: var(--space-8) var(--space-6);
  text-align: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* 50% matches the asset's own circular mask, so a square photo dropped
   in later still renders as a circle. */
.cred img {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  object-fit: cover;
}

.cred-name {
  font-size: var(--text-lg);
  font-weight: 700;
}

/* Left-aligned inside the centred card. Centred, a paragraph this long
   starts every line somewhere new. Muted is 6.6:1 on the white card.
   pretty, or "today." ends the bio alone from 901px to 939px. */
.cred-summary {
  color: var(--color-text-muted);
  text-align: left;
  text-wrap: pretty;
}

/* Stacked: the copy, then the card. */
@media (max-width: 900px) {
  .hero { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
}

/* The first section's 48px is all the space a phone needs above the h1. */
@media (max-width: 560px) {
  .hero { padding-block: 0 var(--space-8); }
}

/* ============================================================
   Section head — S2, S3

   A centred h2 with its intro or its banner. Capped at --measure,
   so over the wide grids below it the heading and intro still keep
   a reading width.
   ============================================================ */

.section-head {
  display: grid;
  justify-items: center;
  gap: var(--space-5);
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
}

/* S2's banner sits above its head rather than inside it. */
.banner + .section-head { margin-top: var(--space-6); }

/* ============================================================
   Problems — S2

   Eight small cards, four across. Each is a label plus one line
   naming what it costs, so the grid argues instead of just listing.
   The tick on each card's top edge is the one the S3 steps and the
   S6 columns carry. The cost line is muted, 6.6:1 on the white card.
   ============================================================ */

/* 16px between the cards and inside their sides, rather than 24px. Four
   across in the 960px frame, 24px left each card 160px of text: six of
   the eight titles wrapped and one cost line ran to three. At 16px it is
   182px, four titles wrap and every cost line takes two. */
.problems {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-4);
  list-style: none;
  margin: var(--space-8) 0 0;
  padding: 0;
}

.problems > li {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

/* On the top border, inset to line up with the text below it. */
.problems > li::before {
  content: "";
  position: absolute;
  top: -1px;
  left: var(--space-4);
  width: var(--space-7);
  height: 2px;
  background: var(--color-primary);
}

.problems b { font-weight: 600; }

/* balance, as the S6 blurbs use, so no cost line ends on one word.
   pretty left "improved." and "approvals." alone at every width above
   900px. A browser without balance keeps the plain wrap. */
.problems span {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-wrap: balance;
}

/* The S2 close. Each card names one cost and this sums them, so it is
   set at h2 size and centred under the grid, rather than as a
   .statement, whose rule and indent belong beside a single column. */
.big-statement {
  max-width: 22em;
  margin: var(--space-9) auto 0;
  font-size: var(--text-3xl);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.018em;
  text-align: center;
  text-wrap: balance;
}

@media (max-width: 900px) {
  .problems { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .problems { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   Marked list — S5 deliverables, the privacy policy

   Marker colour comes from --color-primary, so the same class
   works on both the light background and inside .section-dark.
   ============================================================ */

.marked-list {
  display: grid;
  gap: var(--space-4) var(--space-6);
  list-style: none;
  margin: 0;
  padding: 0;
}

.marked-list > li {
  position: relative;
  padding-left: var(--space-5);
}

.marked-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 12px;
  height: 2px;
  background: var(--color-primary);
}

/* ============================================================
   Chain — S1 hero

   Three terms read as one left-to-right progression (what you
   find, what it means, what you get) rather than three parallel
   claims. The first two are muted and the last takes full weight
   plus a teal underline, so the row resolves on "opportunity"
   and hands off to the CTA below it, which uses the same word.

   The arrows are ::after pseudo-elements, not characters in the
   markup. Decorative by construction: they stay out of the
   accessibility tree, so a screen reader gets three clean list
   items instead of "identify friction black right pointing
   triangle expose inefficiencies".

   Sized one step below body. It is connective tissue between the
   lead and the CTA, and at --text-base the row competes with the
   lead for the same attention.
   ============================================================ */

.chain {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  letter-spacing: 0.01em;
}

/* Muted is 6.04:1 on --color-bg, which clears AA at this size.

   nowrap keeps a term and its arrow together as one unit. Without it the
   anonymous text item inside the li is free to break mid-phrase, and the
   row degrades into "expose / inefficiencies →" before it degrades into
   two clean lines. The widest term is 126px against 342px of content on a
   390px phone, so no single item can overflow. */
.chain > li {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Shaft and head come from one clip-path on one pseudo-element, so the
   connector needs no extra box and no stacking tricks. The 2px shaft is
   the same weight as the .marked-list marker, which is the only other
   teal rule on the page. currentColor would tint it with the muted text
   beside it; the arrow reads as structure, so it takes the accent. */
.chain > li:not(:last-child)::after {
  content: "";
  flex: 0 0 auto;
  width: 22px;
  height: 8px;
  background: var(--color-primary);
  clip-path: polygon(
    0 3px, 15px 3px, 15px 0, 22px 4px, 15px 8px, 15px 5px, 0 5px
  );
}

/* The payoff term. Full contrast and 600 against the muted 400 beside it,
   which is enough of a step to land the row without any decoration.

   It carried a teal rule underneath until it was pointed out that this
   page styles links as `a { color: var(--color-primary) }` with the UA
   underline, so teal plus a rule is exactly the link signature. Teal text
   was not the fix either, for the same reason. Weight and contrast are
   the only emphasis left that a reader cannot mistake for a target.

   The tint chip is the emphasis that replaced it. It stays clear of the
   page's button language, which is a solid --color-primary fill with white
   text at 0.875rem padding; this is a pale fill at 2px, so it reads as a
   tag rather than a target. Vertical padding is deliberately small so the
   chip hugs the text and does not start to look pressable.

   Scoped under .chain to outrank `.chain > li`'s muted colour on
   specificity rather than with !important. */
.chain > .chain-end {
  color: var(--color-text);
  font-weight: 600;
  padding: 2px var(--space-2);
  background: var(--color-primary-subtle);
  border: 1px solid var(--color-primary-subtle-border);
  border-radius: var(--radius-sm);
}

/* No breakpoint. The row stays horizontal at every width and simply wraps
   when it runs out of room: one line down to ~470px, two below that.
   Beside the hero's card it holds one line at every width, with 5px to
   spare at 901px, the tightest point (the hero's 48px gap makes the
   room). Forcing one line was tried and removed: in a column too narrow
   for it the chain can only overflow, and with a 20px browser default
   font it ran 44px into the card.

   An earlier revision forced a vertical stack under 640px with the arrows
   rotated a quarter turn. It was removed for spending three lines on what
   wraps into two, and for reading as a bulleted list with decorations
   rather than as a progression. The horizontal reading survives a wrap;
   it does not survive being stacked.

   A single line on a 390px phone is not reachable and was not attempted:
   the three terms measure 339px of text against 342px of content width
   before any arrows or gaps, so two lines is the floor at a legible size. */

/* ============================================================
   Steps — S3

   Measure, Improve, Verify side by side, each opening on a 1px
   rule with a teal tick and a two-digit numeral. The numerals are
   generated, so the markup stays a plain ordered list.

   Each name is the page's plain h3 (--text-xl, 600, full
   contrast), not teal. On this page teal text is the link
   signature (see .chain-end), so size and weight do the
   emphasising. The numeral is the exception: small and spaced, it
   reads as a label, and teal-700 is 8.32:1 on the tint band.
   ============================================================ */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-7);
  list-style: none;
  margin: var(--space-8) 0 0;
  padding: 0;
  counter-reset: step;
}

.steps > li {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-3);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  counter-increment: step;
}

.steps > li::before {
  content: "0" counter(step);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--color-primary-text);
}

/* The tick sits on the divider, a full --space-5 above the type, so it
   cannot be read as an underline. 2px matches the .marked-list marker
   and the .chain arrow shaft, the page's other teal rules. A full-width
   teal rule was tried and turned the three dividers into the loudest
   thing in the section. */
.steps > li::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--space-7);
  height: 2px;
  background: var(--color-primary);
}

/* The closing statement beside the paragraph that expands on it. */
.work-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-9);
  align-items: start;
  margin-top: var(--space-9);
}

@media (max-width: 900px) {
  .steps { grid-template-columns: minmax(0, 1fr); }
  .work-foot { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
}

/* ============================================================
   Columns — Activate, Build, Scale, S6

   Three columns, stacked on phones. Each opens on a 1px rule with
   the S3 steps' teal tick, so the section speaks the page's
   existing list language instead of adding a card style.

   Bordered white cards were tried first, in the old 712px column.
   The three blurbs differ
   in length, and the cards showed it: at desktop Activate ran six
   lines to the others' four, and the shared bottom edge left the
   shorter two looking half-empty. Open columns have no bottom edge
   to give it away.

   The names are the page's plain h3, as in the S3 steps, and the
   tick is the section's only colour.
   ============================================================ */

/* The eyebrow and its heading, 12px apart: a label and the thing it
   labels. */
.phases-head { display: grid; gap: var(--space-3); }

.phases-head + .columns { margin-top: var(--space-8); }

/* --space-6 between columns. The row gap only applies once the columns
   stack on a phone, where it matches the --space-7 between the S3
   steps. */
.columns {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-7) var(--space-6);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* balance, so no blurb ends on a lone word. Unbalanced in the old 216px
   columns, two of the three did, "confidence." and "model.", last lines
   of 104 and 60px; balanced, the last lines ran 139 to 206px. Balance
   keeps the line count, so no column grows. */
.columns > li {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-3);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  text-wrap: balance;
}

/* The tick from .steps > li::after: 2px, on the rule, a full --space-5
   above the name. */
.columns > li::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--space-7);
  height: 2px;
  background: var(--color-primary);
}

@media (max-width: 640px) {
  .columns { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   Offer — S5

   The offer and the form that takes it up, side by side, so the
   ask sits next to the reason for it. The copy gets the wider
   column, 1.1fr to 1fr, since it carries the argument.
   ============================================================ */

.offer {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--space-9);
  align-items: start;
}

/* 24px between everything by default, the page's one run of reading. */
.offer-copy { display: grid; gap: var(--space-5); }

/* Tight: the eyebrow and its heading, the deliverables and their label.
   A grid gap is one value for every pair, so a negative margin takes 12
   back from the 24. */
.offer-copy > .eyebrow + h2,
.offer-copy > h3 + .marked-list { margin-top: calc(var(--space-3) - var(--space-5)); }

/* Loose: the deliverables are a change of kind, 48px under the copy. */
.offer-copy > h3 { margin-top: var(--space-5); }

/* The closing note stands a little apart from the last deliverable. */
.offer-copy > .marked-list + .note { margin-top: var(--space-3); }

/* pretty, so nothing here ends on one word. Without it "look." ended
   the lead from 932px to 1118px, "keep." the closing note from 955px to
   1006px, "time." the form's note at most widths above 900px, and four
   deliverables ("week", "lost", "work", "opportunities") every width
   from about 930px up. Covers the form's note too, which sits inside
   .offer. */
.offer .lead,
.offer .note,
.offer .marked-list li { text-wrap: pretty; }

/* The card stays in view while the longer copy beside it scrolls past.
   align-items: start on .offer is what allows it; a card stretched to
   the row's height would have nowhere to move. */
.offer .form-card {
  position: sticky;
  top: var(--space-6);
}

@media (max-width: 900px) {
  .offer { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .offer .form-card { position: static; }
}

/* ============================================================
   Availability form — S5

   A white card sitting inside .section-dark, so it must restore the
   light token set. .section-dark remaps --color-text, --color-surface
   and --color-border for its own background; inheriting those into a
   white card would put light text on white. Restoring them here means
   fields, labels and .btn-primary all work unmodified inside the card.
   Same inheritance rule as .section-dark: `color` is set explicitly so
   the remap reaches elements that never declare a colour of their own.
   ============================================================ */

.form-card {
  background: #ffffff;
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-md);
  color: var(--color-text);

  --color-text: #191e24;
  --color-text-muted: #4f5e73;
  --color-surface: #ffffff;
  --color-border: #d5dae4;
  --color-primary: #006c62;
  --color-primary-hover: #00534a;
  --color-primary-text: #00534a;
}

/* Explicit single column, for the same reason as .flow — an implicit
   auto track content-sizes and breaks the full-width fields. */
.form-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }

/* The card's heading and the line under it, the form's first item. */
.form-card h3 { margin-bottom: var(--space-2); }

/* The submit button spans the card, the width of the fields above it. */
.form-card .btn { width: 100%; justify-content: center; }

.field { display: grid; gap: var(--space-2); }

.field > label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text);
}

.field .hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.field input,
.field textarea {
  font: inherit;
  font-size: var(--text-base);
  color: var(--color-text);
  background: #ffffff;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  width: 100%;
  transition: border-color var(--ease), box-shadow var(--ease);
}

.field textarea { min-height: 7rem; resize: vertical; }

.field input:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--color-focus-ring);
  box-shadow: 0 0 0 3px rgba(0, 135, 124, 0.25);
}

/* Validation. Never colour-only: the message text carries the meaning,
   and aria-invalid drives the border so assistive tech agrees with it. */
.field [aria-invalid="true"] { border-color: var(--color-error); }

.field-error {
  font-size: var(--text-sm);
  color: var(--color-error-text);
}

.form-status {
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-base);
}
.form-status[data-state="error"] {
  background: var(--color-error-bg);
  border: 1px solid var(--color-error-border);
  color: var(--color-error-text);
}
.form-status[data-state="success"] {
  background: var(--color-primary-subtle);
  border: 1px solid var(--color-primary-subtle-border);
  color: var(--color-primary-text);
}

@media (max-width: 640px) {
  .form-card { padding: var(--space-5); }
}

/* ============================================================
   About — S4

   The heading on the left, the two paragraphs that argue it on the
   right. The bio that used to follow them is the hero's card now.
   ============================================================ */

.about-wide {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-9);
  align-items: start;
}

.about-wide > div { display: grid; gap: var(--space-5); }

@media (max-width: 900px) {
  .about-wide { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
}

/* ============================================================
   Closing — S7

   The last line and a way to act on it, so the page does not end
   on a heading with nothing to do next.
   ============================================================ */

.closing {
  display: grid;
  justify-items: center;
  gap: var(--space-6);
  text-align: center;
}

/* ============================================================
   Prose — privacy.html

   A policy is one column of short topics, so the topics share a
   single .flow instead of each opening a section. A section per
   topic would spend a full section boundary, 112px on desktop,
   on topics that run to a sentence or two.

   The topic headings stay h2 for the outline but take the h3
   style. The h1 already names the document, and at the full h2
   size a one-word topic like Cookies outweighs the sentence under
   it. The 48px above each marks a change of kind; .flow's 24px
   default below keeps the heading with its own text.
   ============================================================ */

.prose > h2 {
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* :not(:first-child) for specificity only. Plain .prose > h2 is (0,1,1)
   and would lose to .flow's (0,2,0) default. */
.prose > h2:not(:first-child) { margin-top: var(--space-8); }

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

.footer {
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-8);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  font-size: var(--text-sm);
}

.footer-legal { margin-top: var(--space-5); }
