/* ============================================================
   Home page design layer. Loaded only by index.html.
   Idea: the page is a test sheet being worked on. Wide openers,
   ruled data instead of boxes, plates for the instruments, and
   colour used as fields rather than decoration.
   Four things are drawn: the cast under the hero, the five stages
   in "What we do", the methods that prove a finding in "How we
   test", and the page under the free audit. Everything that moves
   answers the reader's scroll rather than a clock: a reading order
   sweeping a page, a focus outline walking its controls, a stage
   plotted in as it is reached, a line collecting every method that
   was used.
   All of it sits behind html.js[data-motion="on"], so no JavaScript
   or the pause control leaves every drawing complete and still.
   ============================================================ */

body.home {
  --ink: #0b1a31;
  --paper: #ffffff;
  --shade: #eef3fb;
  --tab: #dbe5f5;
  --line: #c3d3e8;
  --blue: #2875f5;
  --blue-ink: #174ea6;
  --amber: #ffc24b;
  --muted: #3e4c63;
  --crit: #b42318;
  --serious: #92400e;
  --moderate: #174ea6;
  --minor: #3e4c63;
  --cleared: #0f766e;
  /* The same four as filled surfaces. They are inside the lit report, so they
     hold their value in both themes. */
  --crit-fill: #b42318;
  --serious-fill: #92400e;
  --moderate-fill: #174ea6;
  /* Roles that part company in the dark theme: the band ground, the structural
     rules, small marks, and the lit state of the process rail. */
  --band: var(--ink);
  --rule: var(--ink);
  --mark: var(--blue-ink);
  --rail-on: var(--blue-ink);
  --rail-on-ink: #ffffff;
  --hover-wash: rgba(11, 26, 49, 0.08);
  --focus: var(--blue-ink);
  /* Drawing palette: the flat set used by every scene on this page. */
  --ch-blue: #174ea6;
  --ch-blue-d: #15429e;
  --ch-slate: #33465f;
  --ch-navy: #22334d;
  --ch-shoe: #101b2e;
  --skin-1: #f2cba8;
  --skin-2: #d89a69;
  --skin-3: #a9703f;
  --hair-1: #33261a;
  --hair-2: #15120f;
  --hair-3: #5c3b22;
  color-scheme: light;
  background: var(--paper);
  caret-color: var(--blue-ink);
}

/* Dark theme for the home layer. The bands that were ink stay bands: the navy
   steps up from a darker ground instead of down from white, so every light-on-
   navy pair in this file holds its value. Two things stay lit on purpose. The
   report is a document on a light table, so it keeps the light palette for
   everything inside it, and the hero drawing keeps its own background, because
   the figures' dark trousers and shoes need it. */
html[data-theme="dark"] body.home {
  --ink: #eef2f9;
  --paper: #061020;
  --shade: #10203a;
  --tab: #172c4c;
  --line: #2d4670;
  --muted: #bcc9dd;
  --blue: #6ea8ff;
  --blue-ink: #174ea6;
  --band: #152846;
  --rule: #7f96b8;
  --mark: #6ea8ff;
  --rail-on: #6ea8ff;
  --rail-on-ink: #07182f;
  --focus: #6ea8ff;
  --hover-wash: rgba(238, 242, 249, 0.12);
  --crit: #ff9a90;
  --serious: #ffb472;
  --moderate: #a9c6ff;
  --minor: #c3cee0;
  --cleared: #62d6c2;
  color-scheme: dark;
}
html[data-theme="dark"] body.home .plate {
  --ink: #0b1a31;
  --paper: #ffffff;
  --shade: #eef3fb;
  --tab: #dbe5f5;
  --line: #c3d3e8;
  --muted: #3e4c63;
  --blue: #2875f5;
  --blue-ink: #174ea6;
  --mark: #174ea6;
  --rule: #0b1a31;
  --focus: #174ea6;
  --cleared: #0f766e;
  --crit: #b42318;
  --serious: #92400e;
  --moderate: #174ea6;
  --minor: #3e4c63;
  --hover-wash: rgba(11, 26, 49, 0.08);
  background: #ffffff;
  color: var(--ink);
}

/* The page's width belongs to the shared sheet now: this page widened the
   measure to 78rem on its own, and the running head, which takes the same
   wrap, widened with it, so the head changed size from page to page. styles.css
   sets one width for every page, and the notch insets come with it. */

/* The shared sheet caps lists and paragraphs at a reading measure; the home
   page rules its own widths, so the caps come off and go on where they help. */
body.home .flow, body.home .rail, body.home .offer-steps, body.home .strip-standards,
body.home .check-verdicts, body.home .sev-list { max-width: none; }
body.home .flow li, body.home .rail li, body.home .offer-steps li, body.home .strip-standards li,
body.home .sev-list li { margin-bottom: 0; }
body.home { -webkit-tap-highlight-color: rgba(40, 117, 245, 0.18); }
body.home .btn, body.home button { touch-action: manipulation; }

/* Focus: one ring, two values, chosen by the ground it sits on. */
body.home :focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 3px; }
body.home .ground-ink, body.home .ground-blue, body.home .site-footer { --focus: var(--amber); }
body.home .ground-ink :focus-visible, body.home .ground-blue :focus-visible, body.home .site-footer :focus-visible { outline-color: var(--amber); }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Reading progress and the running head ---------- */
/* The reading progress line lives in styles.css, because the running head is
   one header on every page and the line is part of it. So does the head's own
   dress: what used to sit here - a two pixel rule under it, a wider row, a
   larger wordmark, bolder links with a sweeping underline - made this page's
   head look different from every other page's, and the same head changed as
   you moved between them. The page follows the shared head now, and only keeps
   what is about the hero rather than about the head. */

/* Without scripting the panel cannot open, so every link stays on show, and the
   pause control goes: there is no motion for it to stop. */
html:not(.js) body.home .nav-toggle, html:not(.js) body.home .pause-btn { display: none; }
html:not(.js) body.home .site-nav { display: block; width: 100%; }
html:not(.js) body.home .site-nav ul { flex-wrap: wrap; }

/* ---------- Type ---------- */
body.home h1, body.home h2, body.home h3 { letter-spacing: -0.035em; }
body.home h1 { line-height: 0.94; }
body.home h2 { font-size: clamp(2rem, 1.1rem + 3.4vw, 3.6rem); font-weight: 800; line-height: 0.98; margin: 0; }
body.home h3 { font-size: clamp(1.15rem, 1rem + 0.7vw, 1.55rem); font-weight: 700; line-height: 1.15; margin: 0; }
body.home .lead { font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.25rem); line-height: 1.5; color: var(--muted); margin: 0; max-width: 52ch; }
body.home .ground-ink .lead, body.home .ground-blue .lead { color: #cfd9ea; }

/* ---------- Section shape: a wide opener on a rule, then full-width body ---------- */
.sec { padding-block: clamp(3.25rem, 6.5vw, 6rem); }
.sec-open { position: relative; display: grid; gap: 1.1rem; border-top: 5px solid var(--rule); padding-top: 1.5rem; }
.sec-body { margin-top: clamp(2.25rem, 4vw, 3.5rem); }
.sec-body > * + * { margin-top: clamp(1.5rem, 2.6vw, 2.25rem); }

/* ---------- Grounds ---------- */
.ground-shade { background: var(--shade); }
.ground-ink { background: var(--band); color: #eef2f9; }
.ground-blue { background: var(--blue-ink); color: #ffffff; }
.ground-ink .sec-open, .ground-blue .sec-open { border-top-color: var(--amber); }
.ground-ink h2, .ground-blue h2, .ground-ink h3, .ground-blue h3 { color: #ffffff; }
.ground-ink p, .ground-blue p { color: #dfe6f2; }
.ground-ink a, .ground-blue a { color: #ffffff; }
.ground-ink .muted, .ground-blue .muted { color: #cfd9ea; }

/* Rules: tables and rows share one line weight, no boxes. */
.rule-top { border-top: 2px solid var(--rule); }
.ground-ink .rule-top, .ground-blue .rule-top { border-top-color: rgba(255, 255, 255, 0.34); }

/* ---------- Plates: the report and the drawn scenes ---------- */
.plate { position: relative; background: var(--paper); border: 2px solid var(--rule); padding: clamp(1.15rem, 2vw, 1.75rem); }
.ground-blue .plate { background: #ffffff; }

/* ---------- Hero ---------- */
.hero { padding-block: clamp(1.75rem, 4vw, 3rem) clamp(2.5rem, 5vw, 4rem); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(1.75rem, 4vw, 2.5rem); align-items: center; }
.hero h1 { font-size: clamp(2.35rem, 1.05rem + 5.4vw, 4.2rem); font-weight: 800; margin: 0; }
.mt { display: block; }
.hero-aside { border-top: 2px solid var(--rule); padding-top: 1.35rem; margin-top: clamp(1.35rem, 2.6vw, 2rem); }
.hero-scope { font-size: clamp(1.08rem, 1rem + 0.5vw, 1.32rem); line-height: 1.5; color: var(--muted); max-width: 46ch; margin: 0 0 1.5rem; }
.hero-acts { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.hero-note { margin: 1.1rem 0 0; color: var(--muted); font-size: 1rem; }

.hero-scene { margin: 0; }
.scene { display: block; width: 100%; height: auto; max-width: 40rem; margin-inline: auto; }

/* Entrance: the four words of the motto arrive in order, once. */
html.js[data-motion="on"] .mt { opacity: 0; animation: word-in 0.66s cubic-bezier(0.16, 0.84, 0.24, 1) both; }
html.js[data-motion="on"] .mt:nth-child(1) { animation-delay: 0.05s; }
html.js[data-motion="on"] .mt:nth-child(2) { animation-delay: 0.15s; }
html.js[data-motion="on"] .mt:nth-child(3) { animation-delay: 0.25s; }
html.js[data-motion="on"] .mt:nth-child(4) { animation-delay: 0.35s; }
@keyframes word-in { from { opacity: 0; transform: translate3d(0, 0.28em, 0); } to { opacity: 1; transform: none; } }

/* ---------- The cast: the reading order follows the reader's scroll ----------
   --sp runs 0 to 1 as the scene crosses the viewport; the sweep and the
   travelling focus outline are driven from it, so scrolling the page is what
   walks the page. Both rest in a sensible place with no script at all. */
.hero-scene { --sp: 0.42; }
.sc-scan { transform: translateY(calc(42px + var(--sp) * 196px)); }
.sc-ring { transform: translate(14px, calc(112px + var(--sp) * 114px)); }
.sc-caret { transform-box: fill-box; transform-origin: 50% 50%; }
.sc-scan rect:first-child { opacity: 0.55; }
.sc-scan rect:last-child { opacity: 0.09; }

html.js[data-motion="on"] .sc-scan, html.js[data-motion="on"] .sc-ring { transition: transform 0.45s linear; }
html.js[data-motion="on"] .sc-caret { animation: caret-blink 1.15s steps(1, end) infinite; }
@keyframes caret-blink { 0%, 45% { opacity: 1; } 55%, 100% { opacity: 0; } }

/* The figures: a slow bob for the group, and one gesture each. */
.ch { transform-box: fill-box; transform-origin: 50% 100%; }
html.js[data-motion="on"] .ch { animation: ch-bob 4.8s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes ch-bob { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, -4px, 0); } }

.sc-head { transform-box: fill-box; transform-origin: 50% 96%; }
html.js[data-motion="on"] .sc-head { animation: ch-tilt 7.4s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes ch-tilt { 0%, 100% { transform: rotate(0deg); } 35% { transform: rotate(-5deg); } 70% { transform: rotate(3deg); } }

.sc-eye { transform-box: fill-box; transform-origin: 50% 50%; }
html.js[data-motion="on"] .sc-eye { animation: ch-blink 5.6s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes ch-blink { 0%, 90%, 100% { transform: scaleY(1); } 94%, 96% { transform: scaleY(0.12); } }

.sc-arm { transform-box: fill-box; transform-origin: 50% 6%; }
html.js[data-motion="on"] .sc-arm { animation: ch-sway 5.2s ease-in-out infinite; animation-delay: var(--d, 0s); }
@keyframes ch-sway { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2.5deg); } }

.sc-cane { transform-box: fill-box; transform-origin: 50% 0%; }
html.js[data-motion="on"] .sc-cane { animation: ch-cane 3.4s ease-in-out infinite; }
@keyframes ch-cane { 0%, 100% { transform: rotate(-9deg); } 46%, 62% { transform: rotate(5deg); } }

.sc-sign-a { transform-box: fill-box; transform-origin: 50% 100%; }
.sc-sign-b { transform-box: fill-box; transform-origin: 50% 100%; }
html.js[data-motion="on"] .sc-sign-a { animation: ch-sign-a 3.6s ease-in-out infinite; }
html.js[data-motion="on"] .sc-sign-b { animation: ch-sign-b 4.2s ease-in-out infinite; }
@keyframes ch-sign-a { 0%, 100% { transform: rotate(0deg); } 50% { transform: translate3d(-2.5px, -5px, 0) rotate(-13deg); } }
@keyframes ch-sign-b { 0%, 100% { transform: rotate(0deg); } 50% { transform: translate3d(2.5px, -3px, 0) rotate(10deg); } }

.sc-lens { transform: translate(0, 0); }
html.js[data-motion="on"] .sc-lens { animation: ch-lens 9s ease-in-out infinite; }
@keyframes ch-lens {
  0%, 100% { transform: translate(0, 0); }
  28% { transform: translate(-16px, 14px); }
  55% { transform: translate(8px, 30px); }
  78% { transform: translate(-13px, 8px); }
}

.sc-ping { transform-box: fill-box; transform-origin: 100% 50%; opacity: 0.55; }
html.js[data-motion="on"] .sc-ping { animation: ch-ping 2.8s ease-out infinite; }
html.js[data-motion="on"] .sc-ping-b { animation-delay: 0.32s; }
html.js[data-motion="on"] .sc-ping-c { animation-delay: 0.64s; }
@keyframes ch-ping { 0% { opacity: 0; transform: scale(0.86); } 30% { opacity: 0.85; } 100% { opacity: 0; transform: scale(1.06); } }

/* ---------- Standards strip: the masthead line on ink ---------- */
.strip { padding-block: clamp(1.35rem, 2.6vw, 2.1rem); }
body.home .strip-grid { display: grid; gap: 1.1rem 3rem; align-items: start; }
.strip-who { margin: 0; font-size: 1.05rem; font-weight: 600; max-width: 42ch; }
.strip-mail { margin: 0.4rem 0 0; }
/* The mail link carries a glyph beside its word, so it has to be laid out as a
   row. The target-size rule for a lone link in a paragraph gives it display and
   padding to reach 24 pixels, and that rule outranks this one on its own, which
   left the envelope sitting on the text baseline instead of centred with the
   word. body.home lifts this rule above it. The padding is kept, because it is
   what gives the link its target, and the same amount is taken back out of the
   line with a negative margin so the strip keeps its rhythm. */
body.home .strip-mail a { display: inline-flex; align-items: center; gap: 0.5rem; padding-block: 0.28rem; margin-block: -0.28rem; }
.mail-icon { flex: none; color: var(--amber); }
/* The label that says what the abbreviations beside it are. */
body.home .strip-label { font-size: 0.95rem; font-weight: 800; letter-spacing: 0.02em; color: #ffffff; margin: 0 0 0.75rem; }
.strip-standards { display: flex; flex-wrap: wrap; gap: 0.55rem 1.6rem; list-style: none; margin: 0; padding: 0; font-weight: 700; }
.strip-standards a { color: var(--amber); text-decoration: none; border-bottom: 2px solid rgba(255, 194, 75, 0.4); padding-bottom: 0.2rem; transition: border-color 0.2s, color 0.2s; }
.strip-standards a:hover, .strip-standards a:focus-visible { color: #ffffff; border-bottom-color: #ffffff; }

/* ---------- What we test: one component, five scopes ----------
   A tab strip, then the panel that names what that product is put through. The
   underline travels between the tabs on a transform, and the panel settles in
   as it is chosen. Without scripting the strip is gone and every panel is on
   the page in order, since only the first is left unmarked in the markup. */
.scope-rail { display: flex; flex-wrap: wrap; gap: 0.2rem 0.3rem; border-bottom: 2px solid var(--rule); }
.scope-tab {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  font: inherit; font-weight: 700; font-size: clamp(0.98rem, 0.9rem + 0.4vw, 1.15rem);
  color: var(--muted); padding: 0.85rem clamp(0.7rem, 1.6vw, 1.2rem); min-height: 2.9rem;
  position: relative;
}
.scope-tab::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 4px;
  background: var(--mark); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 0.3s cubic-bezier(0.16, 0.84, 0.24, 1);
}
.scope-tab:hover { color: var(--ink); }
.scope-tab[aria-selected="true"] { color: var(--ink); }
.scope-tab[aria-selected="true"]::after { transform: scaleX(1); }
.scope-panel { padding-top: clamp(1.6rem, 3vw, 2.4rem); }
body.home .scope-panel h3 { font-size: clamp(1.3rem, 1.15rem + 0.8vw, 1.8rem); margin-bottom: 0.6rem; }
.scope-lead { color: var(--muted); max-width: 62ch; margin: 0 0 1.5rem; }
html:not(.js) .scope-rail { display: none; }
html:not(.js) .scope-panel[hidden] { display: block; }
html.js .scope-panel[hidden] { display: none; }
html.js[data-motion="on"] .scope-panel.sw-in { animation: scope-in 0.32s cubic-bezier(0.16, 0.84, 0.24, 1) both; }
@keyframes scope-in { from { opacity: 0; transform: translate3d(0, 10px, 0); } to { opacity: 1; transform: none; } }
.scope-note {
  color: var(--muted); max-width: 88ch; margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding-top: clamp(1.5rem, 3vw, 2.25rem); border-top: 1px solid var(--line);
}

body.home .checks { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
body.home .checks caption { text-align: left; font-weight: 800; font-size: 1.05rem; padding-bottom: 0.85rem; }
body.home .checks th, body.home .checks td { text-align: left; vertical-align: top; padding: 0.85rem 1rem 0.85rem 0; border-top: 1px solid var(--line); }
body.home .checks th[scope="row"] { padding-left: 0; }
body.home .checks tr:first-child th, body.home .checks tr:first-child td { border-top: 0; }
body.home .checks td { color: var(--muted); }
body.home .checks tr { transition: background 0.2s; }
body.home .checks tr:hover { background: var(--shade); }
body.home .ground-shade .checks tr:hover { background: rgba(255, 255, 255, 0.7); }
body.home .ground-ink .checks th, body.home .ground-ink .checks td { border-color: rgba(255, 255, 255, 0.24); }

/* ---------- What we do: the five stages, drawn as they are reached ----------
   One run down the page on a single spine: the numbered node, the drawing, then
   what happens and what comes back. Little of this switches on. The spine fill,
   each drawing's plot and each stage's settle are written from the reader's own
   scroll position, so the run reads in order because it is being read: --spine
   is the run's own progress and --lp is the stage's. With no scripting, or with
   motion paused or reduced, every stage rests at --lp: 1, already complete. */
.flow { position: relative; list-style: none; margin: 0; padding: 0; }
/* The spine: a track the length of the run and the same line filled from the
   top. Both run behind the nodes, which are opaque and cover the join. */
.flow::before, .flow::after {
  content: ""; position: absolute; left: 1.75rem; width: 3px;
  top: 3.4rem; bottom: 3.4rem; background: rgba(255, 255, 255, 0.24);
}
.flow::after { background: var(--amber); transform: scaleY(1); transform-origin: 50% 0; }
.flow-step {
  --lp: 1;
  position: relative; display: grid; align-content: start;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  column-gap: 1.5rem; row-gap: 0.9rem;
  padding-block: clamp(1.75rem, 3.4vw, 2.6rem);
}
/* The stage's own marker, sitting on the spine where the fill reaches it. */
.flow-node {
  position: relative; z-index: 1; align-self: start; grid-column: 1; grid-row: 1;
  width: 3.5rem; height: 3.5rem; border-radius: 50%;
  display: grid; place-items: center;
  border: 3px solid var(--amber); background: var(--amber); color: var(--band);
  font-weight: 800; font-size: 1.1rem; font-variant-numeric: tabular-nums;
}
html.js[data-motion="on"] .flow-node { transition: border-color 0.3s, background 0.3s, color 0.3s; }
.flow-art { position: relative; grid-column: 2; grid-row: 1; margin: 0; width: clamp(6rem, 16vw, 9.5rem); color: #ffffff; }
/* The plot: the drawing is wiped in from the left by --lp, and the amber edge is
   the line doing the drawing. The edge shows only while the sweep is in flight,
   so it never sits on a drawing that is already complete. */
.flow-art svg { display: block; width: 100%; height: auto; clip-path: inset(0 calc((1 - var(--lp)) * 100%) 0 0); }
.fa-edge {
  position: absolute; top: 0; bottom: 0; width: 3px; background: var(--amber);
  left: calc(var(--lp) * 100%); opacity: calc(var(--lp) * (1 - var(--lp)) * 3.4);
}
.flow-body { grid-column: 2; grid-row: 2; display: grid; gap: 0.5rem; justify-items: start; }
.flow-side { grid-column: 2; grid-row: 3; display: grid; gap: 0.55rem; justify-items: start; }
/* The words keep their full weight; only their place settles, so nothing is ever
   read at a contrast the reader did not ask for. */
.flow-body, .flow-side { transform: translate3d(0, calc((1 - var(--lp)) * 16px), 0); }
html.js[data-motion="on"] .flow-body, html.js[data-motion="on"] .flow-side { transition: transform 0.25s linear; }
.flow-num { margin: 0; font-size: 0.88rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--amber); }
.flow-step h3 { margin: 0; color: #ffffff; }
.flow-step p { margin: 0; color: #cfd9ea; max-width: 64ch; }
.flow-get span { color: var(--amber); font-weight: 800; }
.flow-step .flow-link { margin: 0; font-weight: 700; }
.flow-step .flow-link a { color: #ffffff; }
.flow-note { margin-top: clamp(2rem, 4vw, 2.75rem); padding-top: clamp(1.5rem, 3vw, 2rem); border-top: 1px solid rgba(255, 255, 255, 0.24); }

/* The drawings' own detail, all reading the stage's --lp. */
.flow-step .fl-mask { fill: var(--band); }
.fl-lens { transform: translate(calc(var(--lp) * -6px), calc(var(--lp) * -6px)); }
.fl-tick { stroke-dasharray: 26; stroke-dashoffset: calc(26 - 26 * var(--lp)); }
.fl-loop { transform: rotate(calc(var(--lp) * 22deg)); transform-origin: 50% 50%; }
.fl-line { stroke-dasharray: 80; stroke-dashoffset: calc(80 - 80 * var(--lp)); }
html.js[data-motion="on"] .fl-lens, html.js[data-motion="on"] .fl-loop { transition: transform 0.3s linear; }

/* Everything above rests complete; only the live run starts from nothing. */
html.js[data-motion="on"]:not(.reduce) .flow[data-live] .flow-step { --lp: 0; }
html.js[data-motion="on"]:not(.reduce) .flow[data-live]::after { transform: scaleY(var(--spine, 0)); }
html.js[data-motion="on"]:not(.reduce) .flow[data-live] .flow-step:not(.on) .flow-node {
  border-color: rgba(255, 255, 255, 0.5); background: var(--band); color: #cfd9ea;
}

/* ---------- Why choose Perceivio: claim against note ---------- */
.why { border-top: 2px solid var(--rule); }
body.home .why-item { display: block; gap: 0; padding: clamp(1.25rem, 2.4vw, 1.85rem) 0; border-bottom: 1px solid var(--line); }
body.home .why-item h3 { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.55rem 0.75rem; }
body.home .why-item p { margin: 0.5rem 0 0; color: var(--muted); max-width: 62ch; }
body.home .why-item strong { color: var(--ink); font-weight: 800; }
/* One drawn mark per claim, matched to what the claim says: a hand for the
   manual pass, a seal for the certification, brackets for the developer
   report, a returning arrow for the retest, a page under a glass for the free
   proof. */
.why-icon { display: inline-flex; flex: none; align-self: flex-start; margin-top: 0.12rem; color: var(--link); }
.why-icon svg { display: block; width: 1.55rem; height: 1.55rem; }
body.home .why-item:nth-child(4) .why-icon { color: var(--cleared); }

/* ---------- How we test: the statement, the proof, the two named lists ----------
   One column and three clear beats. The statement stands alone, the proof takes
   the width of the section, and the tools follow behind a rule. No two of them
   share a row, so nothing crowds anything else. */
body.home .manual-first { border: 0; border-top: 5px solid var(--mark); border-radius: 0; background: transparent; padding: clamp(1.6rem, 3vw, 2.4rem) 0 0; margin: 0; max-width: none; }
body.home .manual-first p { margin: 0; font-size: clamp(1.15rem, 1rem + 0.9vw, 1.7rem); font-weight: 500; line-height: 1.4; max-width: 56ch; letter-spacing: -0.02em; }
.method-open { display: grid; gap: clamp(2.75rem, 6vw, 4.5rem); }
body.home .method-depth { margin: 0; color: var(--muted); font-size: clamp(1.02rem, 0.98rem + 0.3vw, 1.15rem); max-width: 74ch; }
body.home .method-depth strong { color: var(--ink); font-weight: 800; }

/* How one finding is proven: the methods the section names on the left, a line
   collecting them, and the single finding they produce on the right. The
   reader's scroll feeds each lane into the line (--lc per lane), the line down
   into the finding (--pk), and the finding's retest mark last of all. With no
   scripting, or with motion paused or reduced, every lane is already in and the
   diagram reads as the finished statement it is. */
.proof-open { display: grid; gap: 1.1rem; }
.proof-open h3 { margin: 0; }
.proof { --pk: 1; margin: 0; display: grid; gap: clamp(1.75rem, 3.5vw, 3rem); align-items: start; }
.proof-lanes { position: relative; list-style: none; margin: 0; padding: 0; }
/* The collecting line, down the right edge of the lanes, where the connectors
   in the third column of every lane arrive. */
.proof-lanes::before, .proof-lanes::after {
  content: ""; position: absolute; right: 0; width: 3px; top: 1rem; bottom: 1rem;
  background: var(--line);
}
.proof-lanes::after { background: var(--mark); transform: scaleY(var(--pk)); transform-origin: 50% 0; }
.proof-lanes li {
  display: grid; grid-template-columns: 1.6rem minmax(0, 1fr) 2.6rem;
  align-items: center; gap: 0 0.85rem; padding-block: 0.7rem;
  border-top: 1px solid var(--line); color: var(--muted);
}
.proof-lanes li:first-child { border-top: 0; }
/* Each lane feeds the line along its own connector, which grows as the reader's
   scroll reaches that lane. The connector sits on the lane's first line rather
   than in the middle of its box, so the six of them read as one evenly spaced
   run however many lines each lane's note wraps to. */
.proof-lanes li::after {
  content: ""; grid-column: 3; align-self: start; margin-top: 0.72rem;
  height: 3px; background: var(--mark);
  transform: scaleX(var(--lc, 1)); transform-origin: 0 50%;
}
.pl-icon { display: inline-flex; color: var(--muted); }
.pl-icon svg { display: block; width: 1.5rem; height: 1.5rem; }
.pl-text strong { color: var(--ink); font-weight: 700; }
.proof-lanes li.on { color: var(--ink); }
.proof-lanes li.on .pl-icon { color: var(--mark); }
html.js[data-motion="on"] .proof-lanes li,
html.js[data-motion="on"] .proof-lanes li .pl-icon { transition: color 0.35s ease-out; }

/* The finding, which is what all of that produces. */
.proof-out {
  display: grid; gap: 0.9rem; padding: clamp(1.1rem, 2.4vw, 1.6rem);
  background: var(--paper); border: 2px solid var(--rule); border-left-width: 6px;
  border-left-color: var(--mark);
  transform: translate3d(0, calc((1 - var(--pk)) * 18px), 0);
}
html.js[data-motion="on"] .proof-out { transition: transform 0.3s linear; }
.po-tag { margin: 0; font-size: 0.86rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--mark); }
.po-rows { margin: 0; display: grid; gap: 0.55rem; }
.po-rows > div { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: 0.75rem; border-top: 1px solid var(--line); padding-top: 0.55rem; }
.po-rows > div:first-child { border-top: 0; padding-top: 0; }
.po-rows dt { color: var(--muted); font-weight: 700; }
.po-rows dd { margin: 0; color: var(--ink); }
.po-clear { margin: 0; display: grid; grid-template-columns: 1.4rem minmax(0, 1fr); gap: 0.7rem; align-items: start; color: var(--muted); }
.po-clear strong { color: var(--ink); font-weight: 700; }
.po-mark { display: inline-flex; margin-top: 0.12rem; color: var(--cleared); }
.po-mark svg { display: block; width: 1.35rem; height: 1.35rem; }
.po-tick { stroke-dasharray: 20; stroke-dashoffset: calc(20 - 20 * var(--pk)); }
.po-note { margin: 0; color: var(--muted); font-size: 0.95rem; }

/* Only the live diagram starts from nothing; every other case is complete. */
html.js[data-motion="on"]:not(.reduce) .proof[data-live] { --pk: 0; }
html.js[data-motion="on"]:not(.reduce) .proof[data-live] .proof-lanes li { --lc: 0; }

/* The tools and the assistive technology, named in two lists of their own. */
.method-tools { display: grid; gap: clamp(2.5rem, 5vw, 3.75rem); border-top: 1px solid var(--line); padding-top: clamp(2.25rem, 4.5vw, 3.25rem); }
body.home .method-tools .checks caption { padding-bottom: 1.15rem; }
body.home .method-tools .checks th, body.home .method-tools .checks td { padding-block: 1.05rem; }

/* ---------- What you get: the report, its rating legend, the papers ---------- */
.get-grid { display: grid; gap: clamp(1.75rem, 3vw, 3rem); align-items: start; }
.specimen { margin: 0; }
.specimen-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; padding-bottom: 0.85rem; border-bottom: 2px solid var(--ink); }
.specimen-head > span:first-child { font-weight: 800; margin-right: auto; }
.specimen-tag { font-size: 0.85rem; font-weight: 700; color: var(--muted); }
.spec { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.spec th, .spec td { text-align: left; vertical-align: top; padding: 0.85rem 1rem 0.85rem 0; border-top: 1px solid var(--line); }
.spec thead th { border-top: 0; padding-top: 0.7rem; font-size: 0.9rem; color: var(--muted); font-weight: 700; }
.spec tbody th { font-weight: 700; }
.spec td { color: var(--muted); }
.spec .crit { font-variant-numeric: tabular-nums; font-weight: 700; margin-left: 0.5rem; white-space: nowrap; color: var(--ink); }
.spec tr.is-filtered { display: none; }
.spec-mark { display: block; }
.spec-mark circle { fill: none; stroke: #7b8aa3; stroke-width: 2; transition: stroke 0.25s; }
.spec-mark path { fill: none; stroke: var(--cleared); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 18; stroke-dashoffset: 0; }

/* One scroll-driven pass over the findings: a line travels down the report and
   each finding it reaches takes its rating and its retest mark. Scrolling is the
   reader doing the reading, so the pass is complete the moment it is seen. */
.scan { display: none; }
html.js[data-motion="on"] .specimen .scan {
  display: block; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: var(--blue); pointer-events: none;
  transform: translateY(var(--scan, 0px));
  transition: transform 0.2s linear;
}
.spec tbody tr.lit .sev-pill { color: #ffffff; }
.spec tbody tr.lit .sev-critical { background: var(--crit-fill); border-color: var(--crit-fill); }
.spec tbody tr.lit .sev-serious { background: var(--serious-fill); border-color: var(--serious-fill); }
.spec tbody tr.lit .sev-moderate { background: var(--moderate-fill); border-color: var(--moderate-fill); }
.specimen-foot { margin: 1.05rem 0 0; color: var(--muted); }

/* The small press: the retest toggle on the specimen. */
.btn-mini {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 2.6rem; padding: 0.35rem 1.1rem; border-radius: 999px;
  background: var(--paper); border: 2px solid var(--ink); color: var(--ink);
  font: inherit; font-weight: 700; font-size: 0.95rem; cursor: pointer;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.btn-mini:hover { background: var(--ink); color: var(--paper); }
.btn-mini[aria-pressed="true"] { background: var(--cleared); border-color: var(--cleared); color: #ffffff; }
.btn-mini[aria-pressed="true"]:hover { background: #0b5c56; border-color: #0b5c56; color: #ffffff; }
.specimen figcaption { margin-top: 0.6rem; font-size: 0.95rem; color: var(--muted); }

/* The ratings read as one named group of controls beside the report they filter. */
.legend { border-top: 5px solid var(--rule); padding-top: 1.35rem; }
.legend h3 { margin-bottom: 0.6rem; }
.legend-note { color: var(--muted); margin: 0 0 1.35rem; }
.sev-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.1rem; }
.sev-list li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.5rem 0.85rem; align-items: center; }
.sev-list span { color: var(--muted); }
body.home .sev-pill { display: inline-block; border: 2px solid currentColor; border-radius: 2px; background: transparent; font: inherit; font-weight: 800; font-size: 0.9rem; padding: 0.25rem 0.7rem; min-height: 2.6rem; min-width: 6.5rem; text-align: center; }
button.sev-pill { cursor: pointer; transition: background 0.18s, color 0.18s, border-color 0.18s; }
button.sev-pill:hover { background: var(--hover-wash); }
button.sev-pill:focus-visible { background: var(--hover-wash); }
.sev-pill[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.sev-critical { color: var(--crit); }
.sev-serious { color: var(--serious); }
.sev-moderate { color: var(--moderate); }
.sev-minor { color: var(--minor); }

/* What comes back: the same ruled table, with a mark that draws itself. */
.get-back { padding-top: clamp(1.5rem, 2.6vw, 2.25rem); }
.get-back th[scope="row"] { display: flex; align-items: baseline; gap: 0.6rem; }
.mk { display: inline-flex; flex: none; align-self: center; color: var(--cleared); }
.mk-tick { stroke-dasharray: 18; stroke-dashoffset: 0; }
html.js[data-motion="on"] .mk-tick { stroke-dashoffset: 18; }
html.js[data-motion="on"] [data-reveal].in .mk-tick { animation: mk-draw 0.55s cubic-bezier(0.16, 0.84, 0.24, 1) both; }
html.js[data-motion="on"] [data-reveal].in tr:nth-child(2) .mk-tick { animation-delay: 0.14s; }
html.js[data-motion="on"] [data-reveal].in tr:nth-child(3) .mk-tick { animation-delay: 0.28s; }
html.js[data-motion="on"] [data-reveal].in tr:nth-child(4) .mk-tick { animation-delay: 0.42s; }
@keyframes mk-draw { from { stroke-dashoffset: 18; } to { stroke-dashoffset: 0; } }

/* The specimen rows take their retest mark as the scan line reaches them. */
html.js[data-motion="on"] .spec-mark path { stroke-dashoffset: 18; }
html.js[data-motion="on"] .spec tbody tr.lit .spec-mark path { animation: mk-draw 0.5s cubic-bezier(0.16, 0.84, 0.24, 1) both; }
.is-retested .spec-mark circle { stroke: var(--cleared); }
.is-retested .spec-mark path { stroke-dashoffset: 0; animation: none; }

/* ---------- Free one-page audit: the one loud field ---------- */
.offer { display: grid; gap: clamp(1.75rem, 3vw, 3rem); align-items: start; }
.offer > div > p { color: #dfe6f2; }
.sheet { --sp: 0; margin: 0 0 1.5rem; max-width: 18rem; }
.sheet svg { display: block; width: 100%; height: auto; }
/* The magnifier passes down the page as the reader scrolls past it. */
.sh-lens { transform: translate(196px, calc(56px + var(--sp) * 190px)); }
html.js[data-motion="on"] .sh-lens { transition: transform 0.45s linear; }
.offer-steps { display: grid; gap: clamp(1.25rem, 2.4vw, 2rem); list-style: none; margin: 0; padding: 0; border-top: 1px solid rgba(255, 255, 255, 0.34); }
.offer-steps li { display: grid; grid-template-columns: auto 1fr; gap: 0.9rem; align-items: start; padding-top: clamp(1.1rem, 2vw, 1.6rem); border-top: 1px solid rgba(255, 255, 255, 0.2); }
.offer-steps li:first-child { border-top: 0; }
.offer-terms { margin-top: clamp(1.75rem, 3vw, 2.5rem); padding-top: clamp(1.25rem, 2.4vw, 1.75rem); border-top: 1px solid rgba(255, 255, 255, 0.34); }
.offer-num { font-size: clamp(2rem, 1.4rem + 1.8vw, 3rem); font-weight: 800; line-height: 0.85; font-variant-numeric: tabular-nums; color: var(--amber); }
.offer h3 { margin: 0 0 0.3rem; }
/* A light button keeps ink text on every dark ground, including the close band. */
body.home .ground-ink .btn-light, body.home .ground-blue .btn-light { background: var(--paper); color: var(--ink); }
body.home .ground-ink .btn-light:hover, body.home .ground-blue .btn-light:hover { background: var(--amber); color: var(--ink); }

/* ---------- How it works: the rail fills as the steps pass ----------
   The line is laid behind the numbers, never across them. With no script the
   rail is already complete, so the steps read as a finished sequence. */
.rail { position: relative; list-style: none; margin: 0; padding: 0; display: grid; gap: 0; counter-reset: rail; }
.rail::before, .rail::after { content: ""; position: absolute; background: var(--line); }
.rail::after { background: var(--rail-on); transform: scaleY(var(--fill, 1)); transform-origin: 50% 0; }
.rail li { position: relative; display: grid; padding-block: clamp(1rem, 1.8vw, 1.4rem); }
.rail li::before {
  content: counter(rail); counter-increment: rail;
  position: relative; z-index: 2;
  width: 2.55rem; height: 2.55rem; border-radius: 50%;
  margin-bottom: 0.85rem;
  border: 3px solid var(--rail-on); background: var(--rail-on); color: var(--rail-on-ink);
  display: grid; place-items: center; font-weight: 800; font-variant-numeric: tabular-nums;
}
/* Each step carries its own drawing, so the pinned pass travels with pictures as
   well as words and the screen has something to hold. */
.rail-art { margin: 0 0 0.9rem; width: clamp(4.6rem, 12vw, 5.6rem); color: var(--ink); }
.rail-art svg { display: block; width: 100%; height: auto; }
.rail h3 { margin-bottom: 0.2rem; }
.rail p { margin: 0; color: var(--muted); max-width: 40ch; }
/* What each step gives back, which lights with the step it belongs to. */
.rail-get { margin-top: 0.65rem; font-size: 0.98rem; }
.rail-get span { color: var(--mark); font-weight: 800; }
html.js[data-motion="on"] .rail-get { opacity: 0; transform: translate3d(0, 6px, 0); transition: opacity 0.4s ease-out, transform 0.4s cubic-bezier(0.16, 0.84, 0.24, 1); }
html.js[data-motion="on"] .rail li.on .rail-get { opacity: 1; transform: none; }
/* The count above the rail, so the run is legible from the top of the pass. */
/* The count above the rail, so the run is legible from the top of the pass: the
   step the reader is on, named, beside the hint. */
.rail-head { position: relative; display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0.6rem 1.5rem; border-bottom: 2px solid var(--rule); padding-bottom: 1rem; margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
/* The pass's own progress, as one bar sitting in the head's rule, so the reader
   can see how far the run has come from anywhere on the screen. */
.rail-head::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: var(--mark); transform: scaleX(var(--sp, 1)); transform-origin: 0 50%;
}
.rail-now { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.9rem; }
.rail-big { font-size: clamp(2.1rem, 1.2rem + 3.4vw, 3.2rem); font-weight: 800; line-height: 0.85; color: var(--mark); font-variant-numeric: tabular-nums; }
.rail-name { font-size: 0.92rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--mark); }
.rail-hint { margin: 0; color: var(--muted); font-size: 0.98rem; max-width: 46ch; }

/* ---------- The rail's step controls ----------
   On the pinned pass the row of steps travels sideways under the reader's
   scroll. That is the whole point of the pass and it is also the reason steps
   two to five stand off the side of the screen with nothing on the page that
   reaches them but the wheel: the document has no horizontal scroll, the row is
   clipped, and the only way along it is more vertical scroll. These two
   buttons are that missing key. They move the reader one step at a time and
   they work in every state of the section, so pausing the page, asking for
   reduced motion or opening it on a narrow screen all end with the same set of
   steps and the same way through them.

   They need scripting to do anything, so without it they are not offered and
   the plain rail stands on its own, which is the state a reader without
   scripting has always had. */
.rail-nav { display: flex; align-items: center; gap: 0.5rem; }
html:not(.js) .rail-nav { display: none; }
.rail-step {
  width: 2.9rem; height: 2.9rem; padding: 0; border-radius: 999px;
  display: inline-grid; place-items: center;
  background: transparent; border: 2px solid var(--ink); color: var(--ink);
  cursor: pointer; transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
}
.rail-step:hover:not(:disabled) { background: var(--ink); color: var(--paper); }
/* At either end of the rail there is nowhere to go, so the button says so and
   steps out of the tab order rather than waiting to do nothing. */
.rail-step:disabled { opacity: 0.35; cursor: default; }
.rail-step svg { display: block; }

html.js[data-motion="on"] .rail li::before {
  border-color: var(--line); background: var(--paper); color: var(--muted);
  transition: border-color 0.35s, background 0.35s, color 0.35s;
}
html.js[data-motion="on"] .rail li.on::before { border-color: var(--rail-on); background: var(--rail-on); color: var(--rail-on-ink); }
/* Once the pass is settled the line stands full and every number is lit,
   because every step has been reached, so nothing there says which step the
   controls have landed on. The chosen step lights its own number. That is the
   only difference between settled and moving, and it is the one a reader who
   has paused needs: the rail stops moving but the rail still knows where they
   are. */
html.js[data-motion="off"] .rail li[aria-current="step"]::before {
  border-color: var(--rail-on); background: var(--rail-on); color: var(--rail-on-ink);
}

/* ---------- FAQ ---------- */
.faq { border-top: 2px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary { cursor: pointer; list-style: none; padding: 1.2rem 3rem 1.2rem 0; position: relative; font-weight: 800; font-size: clamp(1.05rem, 0.98rem + 0.5vw, 1.3rem); min-height: 44px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 0.35rem; top: 1.6rem; width: 0.72rem; height: 0.72rem;
  border-right: 3px solid var(--mark); border-bottom: 3px solid var(--mark);
  transform: rotate(45deg); transition: transform 0.3s cubic-bezier(0.16, 0.84, 0.24, 1);
}
.faq details[open] summary::after { transform: rotate(225deg); }
.faq details[open] .panel { animation: faq-in 0.32s cubic-bezier(0.16, 0.84, 0.24, 1) both; }
@keyframes faq-in { from { opacity: 0; transform: translate3d(0, -8px, 0); } to { opacity: 1; transform: none; } }
.faq p { margin: 0 0 1.2rem; color: var(--muted); max-width: 74ch; }

/* ---------- Closing band ---------- */
.close-band { padding-block: clamp(3rem, 6vw, 5rem); }
.close-band h2 { font-size: clamp(2rem, 1.1rem + 3.6vw, 3.8rem); }
.close-band p { margin: 0.9rem 0 0; max-width: 48ch; }
.close-band .btn-row { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-top: 1.9rem; }

/* ---------- Footer ---------- */
body.home .site-footer { border-top: 5px solid var(--amber); padding-block: 3rem 2rem; }

/* ---------- Motion: rules draw, content settles ---------- */
html.js[data-motion="on"] [data-reveal] { opacity: 0; transform: translate3d(0, 26px, 0); transition: opacity 0.55s ease-out, transform 0.75s cubic-bezier(0.16, 0.84, 0.24, 1); }
html.js[data-motion="on"] [data-reveal].in { opacity: 1; transform: none; }
html.js[data-motion="on"] .sec-open[data-reveal] { opacity: 1; transform: none; }
html.js[data-motion="on"] .sec-open[data-reveal]::before {
  content: ""; position: absolute; left: 0; top: -5px; height: 5px; width: 100%;
  background: var(--rule); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 0.75s cubic-bezier(0.16, 0.84, 0.24, 1);
}
html.js[data-motion="on"] .ground-ink .sec-open[data-reveal]::before,
html.js[data-motion="on"] .ground-blue .sec-open[data-reveal]::before { background: var(--amber); }
html.js[data-motion="on"] .sec-open[data-reveal].in::before { transform: scaleX(1); }

/* Rows settle in the order they are read rather than all at once. */
html.js[data-motion="on"] .why-item[data-reveal].in:nth-child(2) { transition-delay: 0.06s; }
html.js[data-motion="on"] .why-item[data-reveal].in:nth-child(3) { transition-delay: 0.12s; }
html.js[data-motion="on"] .why-item[data-reveal].in:nth-child(4) { transition-delay: 0.18s; }
html.js[data-motion="on"] .why-item[data-reveal].in:nth-child(5) { transition-delay: 0.24s; }
html.js[data-motion="on"] .offer-steps li[data-reveal].in:nth-child(2) { transition-delay: 0.1s; }
html.js[data-motion="on"] .offer-steps li[data-reveal].in:nth-child(3) { transition-delay: 0.2s; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .mk-tick, .spec-mark path { stroke-dashoffset: 0 !important; }
}

/* ---------- Wider screens ---------- */
@media (min-width: 60rem) {
  .sec-open { grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); align-items: end; gap: 1rem 3rem; }
  .sec-open > *:only-child { grid-column: 1 / -1; }
  body.home .strip-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
  .hero-grid { grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr); gap: 2.5rem 3.5rem; }
  .method-tools { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* A roomy screen puts the four parts of a stage on one line: node, drawing,
     what happens, what comes back. The spine keeps its column, so the run still
     reads as one line travelling down the page. */
  .flow-step {
    grid-template-columns: 3.5rem minmax(0, 9.5rem) minmax(0, 1.15fr) minmax(0, 0.85fr);
    column-gap: clamp(1.75rem, 3vw, 3rem); row-gap: 0; align-items: start;
  }
  .flow-node { grid-column: 1; grid-row: 1; }
  .flow-art { grid-column: 2; grid-row: 1; width: 100%; }
  .flow-body { grid-column: 3; grid-row: 1; }
  .flow-side { grid-column: 4; grid-row: 1; }
  .flow-body p { max-width: 46ch; }
  body.home .why-item { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 0.5rem 3rem; align-items: baseline; }
  body.home .why-item p { margin: 0; }
  .proof { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: clamp(2.5rem, 5vw, 4rem); }
  .get-grid { grid-template-columns: minmax(0, 1.34fr) minmax(0, 0.66fr); }
  .offer { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 3rem; }
  .offer-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 0; }
  .offer-steps li, .offer-steps li:first-child { border-top: 2px solid rgba(255, 255, 255, 0.4); }

  /* Process: five steps on one horizontal rail, filled as the section passes. */
  .rail { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1.5rem; }
  .rail::before, .rail::after { top: 1.275rem; height: 3px; left: 1.275rem; right: calc(20% - 1.275rem); bottom: auto; width: auto; }
  .rail::after { transform: scaleX(var(--fill, 1)); transform-origin: 0 50%; }
  .rail li { padding-block: 0; }
  .rail h3 { min-height: 2.6em; }

  /* With scripting, motion allowed and no request for less motion, the same
     five steps become one pinned pass: the section holds still while the row
     of steps travels left under the reader's scroll, the line filling and the
     numbers lighting in step. Everywhere else, and with no scripting at all,
     the plain rail above stands on its own.

     The pass is tied to the motion control as well as to the media query,
     because pausing the page promises that nothing moves without the reader
     moving it. A pinned pass keeps claiming 125vh of scroll and keeps sliding
     its steps sideways after the pause, which is the one state in which the
     reader is asked to scroll through a long sticky section to reach four steps
     that are sitting off the side of their own screen. Pausing hands the
     section back its plain reading order instead, which is the order a reader
     who asked for reduced motion has always been given. */
  html.js[data-motion="on"]:not(.reduce) .rail-pin { height: 125vh; overflow-x: clip; }
  html.js:not(.reduce) .rail-stick {
    position: sticky; top: 0; min-height: 100vh;
    display: grid; align-content: center;
    /* One fixed column, so the row of steps travels inside it instead of
       stretching the heading above them off the page. */
    grid-template-columns: minmax(0, 1fr);
    padding-block: 4.5rem 2.5rem;
  }
  /* On a pinned pass the count is a headline for the screen, not a caption. */
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail-big { font-size: clamp(3.2rem, 2rem + 3.6vw, 5rem); }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail-name { font-size: 1.05rem; }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 20rem;
    width: max-content; gap: 2.25rem;
    transform: translateX(calc(var(--travel, 0px) * var(--sp, 0) * -1));
    transition: transform 0.25s linear;
    will-change: transform;
  }
  /* On a pinned pass the station has the room to say a little more, so the five
     steps carry their weight instead of floating in the middle of a screen. */
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail li::before { width: 3.6rem; height: 3.6rem; font-size: 1.25rem; margin-bottom: 1.2rem; }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail h3 { font-size: clamp(1.7rem, 1.3rem + 0.9vw, 2.1rem); min-height: 0; }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail p { font-size: 1.15rem; }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail-art { width: clamp(7rem, 5rem + 4vw, 10rem); margin-bottom: 1.4rem; }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail-get { margin-top: 1.15rem; border-left: 3px solid var(--mark); padding-left: 0.9rem; }
  /* On the pinned pass the columns are 20rem and the node is 3.6rem, so the
     line runs centre of the first node to centre of the last: 1.8rem in from
     each end. The unpinned rule's 1.275rem belongs to the smaller node it was
     written for, and leaves the fill about eight pixels behind the number it
     is supposed to arrive at. */
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail::before,
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail::after { left: 1.8rem; right: calc(20rem - 1.8rem); }
  html.js[data-motion="on"]:not(.reduce) .rail-pin .rail::after { transform: scaleX(var(--fill, 0)); }
}

@media (max-width: 59.99rem) {
  body.home .why-item h3 { display: block; }
  body.home .why-item h3 .why-icon { margin-bottom: 0.5rem; }
  .scene { max-width: 34rem; }

  /* Process: the same rail, standing up. */
  .rail { padding-left: 3.6rem; }
  .rail::before, .rail::after { width: 3px; left: 1.275rem; top: 1.4rem; bottom: 1.4rem; }
  .rail li::before { position: absolute; left: -3.6rem; top: 0.9rem; }
}

/* The head's own breakpoints live with the head in styles.css: below 1200 the
   panel takes it, so the tight band this page used to dress for no longer
   exists, and the call to action keeps its full label on one line. */

@media (max-width: 39.99rem) {
  .spec th, .spec td { padding-right: 0.6rem; }
  .spec thead th { font-size: 0.82rem; }
  .spec .crit { display: block; margin-left: 0; }
}

/* On a phone the four columns stop being readable side by side, so each finding
   becomes its own block and the column names move onto the values. */
@media (max-width: 30rem) {
  .spec thead { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .spec, .spec tbody, .spec tr, .spec th, .spec td { display: block; }
  .spec tr { position: relative; padding: 0.95rem 2.25rem 0.95rem 0; border-top: 1px solid var(--line); }
  .spec tbody th, .spec tbody td { padding: 0; border: 0; }
  .spec .crit { display: inline; }
  .spec tbody td { margin-top: 0.3rem; }
  .spec tbody td:nth-child(4) { position: absolute; top: 1.15rem; right: 0.25rem; margin-top: 0; }
  .spec td:nth-child(2)::before { content: "Severity and criterion: "; }
  .spec td:nth-child(3)::before { content: "Fix: "; }
  .spec td:nth-child(2)::before, .spec td:nth-child(3)::before { color: var(--ink); font-weight: 700; }
}
