/* ============================================================
   Shyk Systems — single stylesheet.
   Sections: fonts · tokens · base · layout · header · footer ·
             components (Task 4) · responsive (Task 4)
   Page authors do not edit this file.
   ============================================================ */

/* --- fonts ------------------------------------------------- */
@font-face { font-family: "Source Serif 4"; src: url("/assets/fonts/source-serif-4-400.woff2") format("woff2");
             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Source Serif 4"; src: url("/assets/fonts/source-serif-4-600.woff2") format("woff2");
             font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Sans"; src: url("/assets/fonts/ibm-plex-sans-400.woff2") format("woff2");
             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Sans"; src: url("/assets/fonts/ibm-plex-sans-600.woff2") format("woff2");
             font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("/assets/fonts/ibm-plex-mono-400.woff2") format("woff2");
             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("/assets/fonts/ibm-plex-mono-500.woff2") format("woff2");
             font-weight: 500; font-style: normal; font-display: swap; }

/* --- tokens ------------------------------------------------ */
:root {
  --paper: #FCFBF8;  --surface: #FFFFFF;
  --ink: #15171A;    --ink-2: #4A5059;  --ink-3: #6E737B;  --muted: #787264;
  /* --muted was #8A8578: 3.56:1 on --paper and 3.68:1 on --surface, set at
     11px on spec-panel headings, footer column headings, .stat span,
     .record-meta, .record-result span and the contact form's .field label —
     every one of them below the 4.5:1 AA floor. #787264 measures 4.62:1 on
     --paper and 4.78:1 on --surface. --ink-3 (4.61 / 4.77) and --ink-2
     (7.86 / 8.13) already clear it; --line is border-only and never carries
     text. */
  --line: #E4E0D8;   --line-soft: #F2EFE9;
  --accent: #A23B1E; --accent-soft: #F6EDE8;

  --serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  --sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --step--1: 0.8125rem;
  --step-0:  0.9375rem;
  --step-1:  1.125rem;
  --step-2:  clamp(1.35rem, 2.2vw, 1.6rem);
  --step-3:  clamp(1.9rem, 4.2vw, 2.9rem);

  --wrap: 1120px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  color-scheme: light;
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--step-0)/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 400; letter-spacing: -0.015em; margin: 0; }
h1 { font-size: var(--step-3); line-height: 1.14; }
h2 { font-size: var(--step-2); line-height: 1.22; }
h3 { font-size: var(--step-1); line-height: 1.3; }
h4 { font-size: 1rem; line-height: 1.35; }

p { margin: 0 0 1em; }
a { color: inherit; text-decoration-color: var(--line); text-underline-offset: 3px; }
a:hover { text-decoration-color: var(--accent); }
/* Links sitting inside a paragraph need to be findable without a pointer.
   The global rule above leaves them the colour of the body text under a
   --line underline at 1.27:1, so on `privacy-policy.html` and
   `terms-and-conditions.html` the only contact route on the page is
   invisible until hover — no use to a keyboard or a touch reader
   (WCAG 1.4.1, 1.4.11). Body-copy links are exactly those inside .prose
   and .form-note; nav, footer and button links set text-decoration: none
   and are distinguishable by position and treatment, so they are left
   alone. The accent underline measures 6.38:1 on --paper, 6.60:1 on
   --surface and 5.72:1 on the .form-note --accent-soft panel. */
.prose a, .form-note a { color: var(--accent); text-decoration-color: currentColor;
                         text-decoration-thickness: 1px; }
.prose a:hover, .form-note a:hover { color: var(--ink); text-decoration-color: var(--ink); }
img { max-width: 100%; height: auto; display: block; }

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper); padding: 0.6rem 1rem; font-size: var(--step--1);
}
.skip-link:focus { left: 0; }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.eyebrow {
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 0.85rem;
}

/* --- layout ------------------------------------------------ */
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: clamp(2.5rem, 6vw, 4.25rem); }
.section--tight { padding-block: clamp(1.5rem, 3vw, 2.25rem); }
.section--band { background: var(--surface); border-block: 1px solid var(--line); }

/* Two columns, not a heading with its deck stranded underneath it. The deck
   <p> is a flex child of the head now rather than a sibling after it, and it
   is given a flex-basis: a flex item with no basis is sized from its content,
   and a paragraph's max-content width is the whole paragraph, so the deck
   always overflowed the line and wrapped to its own row. With a basis it
   shares the row — heading left, deck right, and a trailing "all ..." link
   pushed to the end by space-between. When the two bases no longer fit side
   by side, flex-wrap stacks them heading first. */
.section-head { display: flex; justify-content: space-between; align-items: baseline;
                gap: 0.9rem 2.5rem; margin-bottom: 1.6rem; flex-wrap: wrap; }
/* flex: 0 1 auto, not a grow: a head that carries only a heading (six of the
   fourteen on the site) must stay exactly as wide as its words, or the 42ch
   cap would break a forty-character heading across two lines for nothing. */
.section-head > h2 { flex: 0 1 auto; max-width: 42ch; }
/* 50ch, not the 56ch a full-width deck was allowed. The deck now sits beside
   the heading instead of under it, so its widest wrapped line has to stay
   inside the 80-character bar after the heading's column is taken out of the
   row first. 50ch measures at most 70. */
.section-head > p { flex: 1 1 20rem; max-width: 50ch; margin: 0; }
/* The underline, not the colour, is what marks these as links: the global
   `a` rule leaves them a --line underline at 1.27:1 on --paper, well under the
   3:1 non-text-contrast floor (WCAG 1.4.11). currentColor puts the underline
   on the accent the text already carries — 6.38:1 on --paper and 6.60:1 on
   --surface, for the nine "all …" links in section heads. */
.section-head a { font-size: var(--step--1); color: var(--accent);
                  text-decoration-color: currentColor; text-decoration-thickness: 1px; }

/* Section decks. A bare <p> placed directly in a section's .wrap has nothing
   constraining its measure and runs the full 1120px container — ~120 characters
   per line. Cap the measure for running text; components set their own.
   56ch, not 68ch: ch is the advance of the "0" glyph, and lowercase prose in
   IBM Plex Sans averages narrower than a digit, so a 68ch box held 91-character
   lines. 56ch measures at most 78. */
.section > .wrap > p,
.section--tight > .wrap > p,
.section--band > .wrap > p { max-width: 56ch; }

/* --- header ------------------------------------------------ */
.site-header { position: sticky; top: 0; z-index: 20; background: var(--surface);
               border-bottom: 1px solid var(--line); box-shadow: 0 1px 0 rgba(21,23,26,.03); }
.header-inner { display: flex; align-items: center; justify-content: space-between;
                gap: 1rem; padding-block: 0.8rem; }
.brand { display: inline-flex; align-items: center; gap: 0.55rem; text-decoration: none; }
.brand-mark { width: 24px; height: 24px; flex: 0 0 24px; }
.brand-name { font-family: var(--serif); font-size: 1rem; }
.nav { display: flex; align-items: center; gap: 1.1rem; }
.nav a { font-size: var(--step--1); color: var(--ink-2); text-decoration: none; }
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); box-shadow: inset 0 -1px 0 var(--accent); }
.nav-cta { border: 1px solid var(--line); border-radius: 3px; padding: 0.4rem 0.75rem; color: var(--ink) !important; }
.nav-cta:hover { border-color: var(--ink-3); }
.nav-toggle { display: none; font: 400 var(--step--1) var(--sans); background: none;
              border: 1px solid var(--line); border-radius: 3px; padding: 0.4rem 0.75rem; cursor: pointer; }

/* --- footer ------------------------------------------------ */
.site-footer { border-top: 1px solid var(--line); background: var(--surface); margin-top: 3rem; }
.footer-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr;
               gap: 2rem; padding-block: 2.5rem 2rem; }
.footer-grid h2 { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em;
                  text-transform: uppercase; color: var(--muted); margin-bottom: 0.75rem; }
.footer-grid nav { display: flex; flex-direction: column; gap: 0.45rem; }
.footer-grid a { font-size: var(--step--1); color: var(--ink-2); text-decoration: none; }
.footer-grid a:hover { color: var(--ink); text-decoration: underline; }
.footer-brand p { font-size: var(--step--1); color: var(--ink-3); max-width: 34ch; margin: 0.8rem 0 0; }
.footer-contact p { font-size: var(--step--1); color: var(--ink-3); margin: 0.45rem 0 0; }
.footer-base { display: flex; justify-content: space-between; align-items: center;
               gap: 1rem; flex-wrap: wrap; border-top: 1px solid var(--line-soft);
               padding-block: 1rem 1.5rem; font-size: var(--step--1); color: var(--ink-3); }
.footer-base p { margin: 0; }
.footer-base nav { display: flex; gap: 1.25rem; }
/* Same hole as .section-head a, in the other direction: these two legal links
   inherit .footer-base's --ink-3 text under a --line underline at 1.32:1 on
   --surface. They are the only underlined links in the footer — .footer-grid a
   sets text-decoration: none — so the underline is their whole affordance and
   has to clear 3:1. currentColor gives 4.77:1 on --surface. */
.footer-base a { text-decoration-color: currentColor; text-decoration-thickness: 1px; }
/* `.footer-base a` and the global `a:hover` have equal specificity, so the
   rule above would otherwise mask the existing hover treatment. Restore it. */
.footer-base a:hover { text-decoration-color: var(--accent); }

/* --- 1/2. hero --------------------------------------------- */
.hero { display: grid; grid-template-columns: 1.12fr 0.88fr; gap: clamp(1.5rem, 4vw, 2.75rem);
        align-items: start; padding-block: clamp(2.25rem, 5vw, 3.5rem); }
.hero-body h1 { margin-bottom: 0.9rem; }
.hero-body p.lead { font-size: var(--step-1); line-height: 1.6; color: var(--ink-2);
                    max-width: 46ch; margin-bottom: 1.5rem; }
.hero--full { grid-template-columns: 1fr; }
.hero--full .hero-body p.lead { max-width: 58ch; }

/* --- buttons ----------------------------------------------- */
.btn { display: inline-block; font-size: var(--step--1); padding: 0.62rem 1.05rem;
       background: var(--ink); color: var(--paper); border-radius: 3px;
       text-decoration: none; border: 1px solid var(--ink); }
.btn:hover { background: #000; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); margin-left: 0.45rem; }
.btn--ghost:hover { background: transparent; border-color: var(--ink-3); }

/* --- 3. spec-panel ----------------------------------------- */
.spec-panel { border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
.spec-panel > h2, .spec-panel > h3 {
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--muted); padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--line);
  background: var(--paper); margin: 0; }
.spec-row { display: flex; justify-content: space-between; gap: 1rem;
            padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--line-soft); font-size: var(--step--1); }
.spec-row:last-child { border-bottom: 0; }
.spec-row dt, .spec-row > span:first-child { color: var(--ink-3); }
.spec-row dd, .spec-row > span:last-child { margin: 0; font-family: var(--mono);
            font-variant-numeric: tabular-nums; text-align: right; }

/* --- 4. chip-strip ----------------------------------------- */
.chip-strip { display: flex; flex-wrap: wrap; gap: 0.55rem; }
/* Three sizes have been tried here. 0.6875rem (11px) made the ten technologies
   read as a legal footnote under the paragraph that calls them "the whole list
   we staff against". Pass 1 took them to var(--step--1) (13px). This is
   var(--step-0) (15px) — body size, the same step as the paragraph above them,
   which is what makes the strip the second thing in that block rather than a
   caption under the first. Measured at 1440px: the ten-item strip is one row
   using about 980px of the 1040px container. The horizontal padding is 0.75rem
   rather than a proportional 0.8rem precisely to keep that slack; at 0.85rem
   the strip is 30px from wrapping, which is not a margin to ship on. */
.chip { font-family: var(--mono); font-size: var(--step-0); color: var(--ink-2);
        border: 1px solid var(--line); background: var(--surface);
        padding: 0.45rem 0.75rem; border-radius: 3px; }
/* The supporting column is 438px, a little over a third of the band the rule
   above is sized for. A 15px chip there is not a bigger chip, it is a strip
   that wraps to four rows. In the aside the strip is a reference list rather
   than a headline, so it keeps pass 1's 13px — the same reasoning that
   re-lays-out .stat-row and .bordered-grid for that column. */
.split-aside .chip-strip { gap: 0.5rem; }
.split-aside .chip { font-size: var(--step--1); padding: 0.34rem 0.7rem; }

/* --- 5. bordered-grid -------------------------------------- */
.bordered-grid { display: grid; grid-template-columns: repeat(3, 1fr);
                 border: 1px solid var(--line); background: var(--surface); }
.bordered-grid--2 { grid-template-columns: repeat(2, 1fr); }
.cell { padding: 1.1rem 1.15rem; border-right: 1px solid var(--line); text-decoration: none; display: block; }
.cell:last-child { border-right: 0; }
/* A lone cell is auto-placed into column 1 and fills a third of an obviously
   bordered box. The bible's sequence token for such a section is a bare
   `bordered-grid`, so span it here rather than add a `--1` modifier that would
   force a markup change on pages that are already correct. */
.bordered-grid > .cell:only-child { grid-column: 1 / -1; }
.cell:hover { background: var(--paper); }
.cell-idx { font-family: var(--mono); font-size: 0.6875rem; color: var(--accent); margin-bottom: 0.6rem; }
.cell h3 { margin-bottom: 0.55rem; }
.cell p { font-size: var(--step--1); color: var(--ink-2); margin: 0; max-width: 56ch; }

/* --- 6. record-row ----------------------------------------- */
.record-list { border-top: 1px solid var(--line); }
.record { display: grid; grid-template-columns: 8.5rem 1fr 10rem; gap: 1.2rem;
          padding: 1.05rem 0; border-bottom: 1px solid var(--line-soft);
          align-items: center; text-decoration: none; }
.record:hover { background: var(--surface); }
.record-meta { font-family: var(--mono); font-size: 0.6875rem; color: var(--muted); line-height: 1.55; }
.record-body h3 { margin-bottom: 0.55rem; }
.record-body p { font-size: var(--step--1); color: var(--ink-2); margin: 0; max-width: 56ch; }
.record-result { text-align: right; font-size: var(--step--1); }
.record-result strong { display: block; font-family: var(--serif); font-size: var(--step-1);
                        font-weight: 400; letter-spacing: -0.02em; }
.record-result span { font-family: var(--mono); font-size: 0.6875rem; color: var(--muted); }

/* --- 7. pull-quote ----------------------------------------- */
.pull-quote { display: grid; grid-template-columns: 1fr 11rem; gap: 1.6rem; align-items: center;
              border: 1px solid var(--line); background: var(--surface); padding: 1.35rem 1.5rem; }
/* 64ch, not the 56ch used for body copy: this is Source Serif 4 at --step-1,
   where ch is 9.34px against the sans's 7.8px, so the same ch count would set a
   much shorter line. 64ch is 609px and holds 72 characters of the shipped quote
   against 91 uncapped. It stays above the ~40-character floor below which a
   pull quote reads as fragments, and it is inert under about 900px, where the
   two-column grid already narrows the quote past the cap. */
.pull-quote blockquote { margin: 0; font-family: var(--serif); font-size: var(--step-1);
                         line-height: 1.5; letter-spacing: -0.01em; max-width: 64ch; }
.pull-quote-who { border-left: 1px solid var(--line); padding-left: 1.15rem;
                  font-size: 0.6875rem; line-height: 1.6; color: var(--ink-3); }
.pull-quote-who strong { display: block; color: var(--ink); }

/* --- 8. prose ---------------------------------------------- */
/* 56ch, for the same reason as the section decks above: 68ch measured 95
   characters on the widest wrapped line of a long-form column at 1440px.
   Long-form lowercase prose averages a narrower advance than deck copy, which
   carries digits and capitals, so prose does not get to sit wider.
   55ch, not 56ch: at 56ch the widest line on the site was 81 characters —
   `services/dedicated-teams.html`, "…before the team takes a full sprint's
   load. Those days sit inside the three-month" — one over the 80-character
   bar. One ch off the cap takes it to 79 and moves nothing else. */
.prose { max-width: 55ch; }
.prose h2 { margin: 2.2rem 0 0.7rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }
.prose h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose h3 { margin: 1.5rem 0 0.5rem; }
.prose p, .prose li { color: var(--ink-2); }
.prose ul, .prose ol { padding-left: 1.15rem; margin: 0 0 1em; }
.prose li { margin-bottom: 0.4rem; }
.prose strong { color: var(--ink); font-weight: 600; }

/* --- 9. stat-row ------------------------------------------- */
.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem;
            border-top: 1px solid var(--line); padding-top: 1.25rem; }
.stat strong { display: block; font-family: var(--serif); font-size: var(--step-2);
               font-weight: 400; letter-spacing: -0.02em; }
.stat span { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.08em;
             text-transform: uppercase; color: var(--muted); }

/* --- 10. cta-band ------------------------------------------ */
.cta-band { border: 1px solid var(--line); background: var(--surface);
            padding: 1.75rem; display: flex; justify-content: space-between;
            align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.cta-band h2 { max-width: 28ch; }
.cta-band p { font-size: var(--step--1); color: var(--ink-3); margin: 0.5rem 0 0; max-width: 40ch; }

/* --- 11. split --------------------------------------------- */
/* The eleventh component, added after the vocabulary was held closed at ten
   for the whole build. Every section below a hero was one 56ch column inside
   a 1120px container, so about 600px of each screen below the fold carried
   nothing at all. The fix is not a wider measure — the 56ch caps are what
   stopped this site setting 125-character lines — it is putting the
   supporting material that sat stacked underneath the prose alongside it
   instead. The ratio is the hero's, so the page keeps one asymmetry rather
   than acquiring a second.
   .split-body and .split-aside are the two column elements. Either may carry
   another class (`prose split-body` is the usual left column); the aside is a
   container that HOLDS a component rather than being one, which is what lets
   the four rules below re-lay-out the components that assume a full-width
   row. */
.split { display: grid; grid-template-columns: 1.12fr 0.88fr;
         gap: clamp(1.5rem, 4vw, 2.75rem); align-items: start; }
/* A grid item's automatic minimum size is its min-content width, so a long
   unbroken token — a mono figure, an email address — in either column would
   push that track past its fr share and overflow the page at 375px. */
.split-body, .split-aside { min-width: 0; }
/* The left track is 1.12fr of about 996px at 1440px, which is wider than the
   56ch the rest of the site sets. Cap the running text so the measure is
   exactly what it was before this component existed and the extra width goes
   into the gutter, not into line length. .prose carries its own 56ch and
   needs nothing here. */
.split-body > p, .split-body > ul, .split-body > ol, .split-body > dl { max-width: 56ch; }

/* The supporting track is about 438px at 1440px — the same width as the
   hero's spec panel, which is why .spec-panel and .chip-strip need no help.
   The three components that assume a full-width row do. */
.split-aside .stat-row { grid-template-columns: repeat(2, 1fr); row-gap: 1.35rem; }
.split-aside .bordered-grid,
.split-aside .bordered-grid--2 { grid-template-columns: 1fr; }
.split-aside .cell { border-right: 0; border-bottom: 1px solid var(--line); }
.split-aside .cell:last-child { border-bottom: 0; }
.split-aside .pull-quote { grid-template-columns: 1fr; }
.split-aside .pull-quote-who { border-left: 0; border-top: 1px solid var(--line);
                               padding: 1rem 0 0; }
/* A plain list is the sixth thing the column is allowed to hold; the browser
   default is 40px of padding and a 1em margin, neither of which belongs
   against a bordered panel's top edge. */
.split-aside > ul, .split-aside > ol { margin: 0; padding-left: 1.15rem; }
.split-aside > ul > li, .split-aside > ol > li { font-size: var(--step--1);
                               color: var(--ink-2); margin-bottom: 0.4rem; }
/* Pass 2 stacks two and three components in this column — a spec panel, then
   a chip strip, then a stat row. None of the ten components carries an outer
   margin (they were all designed to be the only thing in a full-width row),
   so stacked they would sit flush against one another. The gap comes from the
   container instead of from margins added to nine components. align-content
   keeps the rows at their content height rather than stretching them to fill
   a column whose height is set by the prose beside it. */
.split-aside { display: grid; gap: clamp(1.25rem, 2.5vw, 1.75rem);
               align-content: start; }
/* Running text is allowed in this column only as a caption to the component
   under it — the four case studies' "five of the ten technologies" sentence
   sits above its chip strip. --step--1 and --ink-2 are the same treatment the
   plain list above gets; the margin is zero because the grid gap now owns the
   spacing. */
.split-aside > p { margin: 0; font-size: var(--step--1); color: var(--ink-2); }
.split-aside svg { display: block; }
/* The heading of a section that has been folded into the supporting column.
   It was tried as a mono 11px --muted label, matching .spec-panel > h2 and
   .footer-grid h2. That was wrong: on about.html the label sat directly above
   the two <h3>s inside the bordered grid it heads, so a reader saw 11px grey
   above 18px serif and read the hierarchy backwards. An <h2> that owns <h3>s
   has to look like it does, so this carries nothing but a bottom margin and
   renders as the h2 it is — 25.6px serif against its children's 18px. */
.aside-head { margin: 0 0 0.9rem; }

/* --- 11a. contents rail (how-we-work.html) ------------------ */
/* CSS only, and deliberately not a scrollspy. Marking which section the reader
   is currently in needs a scroll listener or an IntersectionObserver, and the
   whole site's JavaScript is one 23-line file that toggles the mobile nav. A
   contents list that links to nine headings is honest; a rail with a
   hard-coded "active" item that never moves is not, so no active state is
   faked here.
   max-height and overflow because the rail holds nine entries, two diagrams
   and a stat row — about 870px, which is taller than the space under the
   header on a 900px viewport. Without them the bottom of the rail would be
   unreachable at any scroll position. */
.split-rail { position: sticky; top: 5rem;
              max-height: calc(100vh - 6.5rem); overflow-y: auto;
              overscroll-behavior: contain; }
.rail-nav ol { list-style: none; margin: 0; padding: 0.3rem 0; counter-reset: rail; }
.rail-nav li { counter-increment: rail; }
/* text-decoration: none, like .nav a and .footer-grid a and unlike .prose a:
   these are a list of links inside a <nav>, where position and treatment carry
   the affordance, not nine accent underlines stacked down a panel. */
.rail-nav a { display: flex; gap: 0.7rem; padding: 0.25rem 0.9rem;
              font-size: var(--step--1); color: var(--ink-2); text-decoration: none; }
.rail-nav a::before { content: counter(rail, decimal-leading-zero);
                      font-family: var(--mono); color: var(--muted); }
.rail-nav a:hover { background: var(--paper); color: var(--ink); }
/* .site-header is sticky and 63px tall, so an anchor jump would otherwise
   land the heading underneath it. */
.prose h2[id] { scroll-margin-top: 5.5rem; }

/* --- contact form ------------------------------------------ */
/* 34rem: nothing else constrains this grid, so at 1440px it ran the full
   1040px column, set the mandated .form-note as one 110-character line, and
   rendered 995px-wide inputs. Capped, the note measures 77 and the inputs 499.
   Inert below about 600px, where the container is already narrower. */
.form-grid { display: grid; gap: 0.9rem; border: 1px solid var(--line);
             background: var(--surface); padding: 1.35rem; max-width: 34rem; }
.field { display: grid; gap: 0.35rem; }
.field label { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.08em;
               text-transform: uppercase; color: var(--muted); }
.field input, .field textarea, .field select {
  font: 400 var(--step-0) var(--sans); color: var(--ink); background: var(--paper);
  border: 1px solid var(--line); border-radius: 3px; padding: 0.55rem 0.7rem; }
.field textarea { min-height: 7rem; resize: vertical; }
.form-note { font-size: var(--step--1); color: var(--ink-2); background: var(--accent-soft);
             border: 1px solid var(--line); border-radius: 3px; padding: 0.75rem 0.9rem;
             margin: 0; display: none; }
.form-note.is-visible { display: block; }

/* --- media -------------------------------------------------- */
.media { border: 1px solid var(--line); border-radius: 4px; overflow: hidden; background: var(--surface); }

/* --- responsive --------------------------------------------- */
@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; }
  /* One column, prose first: .split-body is always the first child in source
     order, so the reading order on a phone is the argument and then the
     evidence, never the other way round. */
  .split { grid-template-columns: 1fr; }
  /* A sticky rail on a phone would pin a contents list over the article the
     reader is trying to read. One column, in source order, same as every
     other .split on the site. */
  .split-rail { position: static; max-height: none; overflow: visible; }
  /* The one exception to prose-first, and it is an exception because a
     contents list is navigation rather than supporting material. Collapsed,
     the aside lands after a 6,076px article, where a list of links to nine
     headings the reader has already scrolled past is dead weight. Moving it
     above the article instead would mean either a second copy in the DOM or
     an `order` property, and it would put nine links between the reader and
     the first sentence on the device with the least room for them. The nine
     headings are still in the flow and still reachable by heading navigation,
     so nothing is lost but the shortcut. The stat row in the same rail is
     supporting material and stays. */
  .rail-nav { display: none; }
  .bordered-grid, .bordered-grid--2 { grid-template-columns: 1fr; }
  .cell { border-right: 0; border-bottom: 1px solid var(--line); }
  .cell:last-child { border-bottom: 0; }
  .record { grid-template-columns: 1fr; gap: 0.5rem; }
  .record-result { text-align: left; }
  .pull-quote { grid-template-columns: 1fr; }
  .pull-quote-who { border-left: 0; border-top: 1px solid var(--line); padding: 1rem 0 0; }
  .stat-row { grid-template-columns: repeat(2, 1fr); row-gap: 1.5rem; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 680px) {
  .nav-toggle { display: block; }
  .nav { display: none; position: absolute; left: 0; right: 0; top: 100%;
         flex-direction: column; align-items: stretch; gap: 0;
         background: var(--surface); border-bottom: 1px solid var(--line); padding: 0.5rem var(--gutter) 1rem; }
  .nav.is-open { display: flex; }
  .nav a { padding: 0.65rem 0; border-bottom: 1px solid var(--line-soft); }
  .nav-cta { margin-top: 0.75rem; text-align: center; border-bottom: 1px solid var(--line) !important; }
  .header-inner { position: relative; }
  .footer-grid { grid-template-columns: 1fr; }
}
